From 6abe0f3a734f4a567db157c7627aa82f1c84c1f0 Mon Sep 17 00:00:00 2001
From: Cosmic Linden <cosmic@lindenlab.com>
Date: Wed, 6 Mar 2024 15:59:08 -0800
Subject: secondlife/viewer-issues#75: Remove "HTTP Textures" setting in
 Developer menu

---
 indra/newview/skins/default/xui/en/menu_viewer.xml | 10 ----------
 1 file changed, 10 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 38763cd9a8..58397afeb5 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -3969,16 +3969,6 @@ function="World.EnvPreset"
 
         <menu_item_separator/>
 
-        <menu_item_check
-         label="HTTP Textures"
-         name="HTTP Textures">
-            <menu_item_check.on_check
-             function="CheckControl"
-             parameter="ImagePipelineUseHTTP" />
-            <menu_item_check.on_click
-             function="ToggleControl"
-             parameter="ImagePipelineUseHTTP" />
-        </menu_item_check>
         <menu_item_call
          label="Compress Images"
          name="Compress Images">
-- 
cgit v1.2.3


From 1ebd23ffed912a5c8c94d109f37a2c25cf169523 Mon Sep 17 00:00:00 2001
From: JamesFoxpaws <162667174+JamesFoxpaws@users.noreply.github.com>
Date: Fri, 8 Mar 2024 16:10:55 +1000
Subject: Remove gender-based restrictions on shape and physics sliders

---
 indra/newview/character/avatar_lad.xml             | 59 +++-------------------
 indra/newview/skins/default/xui/da/strings.xml     |  3 ++
 indra/newview/skins/default/xui/de/strings.xml     |  1 +
 .../skins/default/xui/en/panel_edit_wearable.xml   | 51 -------------------
 indra/newview/skins/default/xui/en/strings.xml     |  1 +
 indra/newview/skins/default/xui/es/strings.xml     |  1 +
 indra/newview/skins/default/xui/fr/strings.xml     |  1 +
 indra/newview/skins/default/xui/it/strings.xml     |  1 +
 indra/newview/skins/default/xui/ja/strings.xml     |  3 ++
 indra/newview/skins/default/xui/pl/strings.xml     |  3 ++
 indra/newview/skins/default/xui/pt/strings.xml     |  1 +
 indra/newview/skins/default/xui/ru/strings.xml     |  3 ++
 indra/newview/skins/default/xui/tr/strings.xml     |  3 ++
 indra/newview/skins/default/xui/zh/strings.xml     |  3 ++
 14 files changed, 30 insertions(+), 104 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml
index 2cdd86267e..9be6275929 100644
--- a/indra/newview/character/avatar_lad.xml
+++ b/indra/newview/character/avatar_lad.xml
@@ -3822,7 +3822,6 @@
 	<param
      id="30879"
      group="1"
-     sex="male"
      name="Male_Package"
      value_min="-.5"
      value_max="2">
@@ -5813,7 +5812,6 @@
 
     <param
      id="400"
-     sex="male"
      group="1"
      name="Displace_Hair_Facial"
      label="Hair Thickess"
@@ -6838,7 +6836,6 @@
 
     <param
      id="626"
-     sex="female"
      group="1"
      name="Big_Chest"
      label="Chest Size"
@@ -6865,7 +6862,6 @@
 
     <param
      id="627"
-     sex="female"
      group="1"
      name="Small_Chest"
      label="Chest Size"
@@ -6891,7 +6887,6 @@
 
     <param
      id="843"
-     sex="female"
      group="1"
      name="No_Chest"
      label="Chest Size"
@@ -6920,7 +6915,6 @@
      group="1"
      name="Muscular_Torso"
      label="Torso Muscles"
-   sex="male"
      show_simple="true"
      wearable="shape"
      edit_group="shape_torso"
@@ -6963,7 +6957,6 @@
         group="1"
         name="Muscular_Torso"
         label="Torso Muscles"
-        sex="female"
         show_simple="true"
      wearable="shape"
      edit_group="shape_torso"
@@ -7004,7 +6997,6 @@
     <param
      id="648"
      group="1"
-     sex="female"
      name="Scrawny_Torso"
      label="Torso Muscles"
    show_simple="true"
@@ -7059,7 +7051,6 @@
     <param
      id="677"
      group="1"
-     sex="male"
      name="Scrawny_Torso_Male"
      label="Torso Scrawny"
      wearable="shape"
@@ -7192,7 +7183,6 @@
     <param
      id="507"
      group="0"
-     sex="female"
      name="Breast_Gravity"
      label="Breast Buoyancy"
      wearable="shape"
@@ -7279,7 +7269,6 @@
     <param
      id="684"
      group="0"
-     sex="female"
      name="Breast_Female_Cleavage"
      label="Breast Cleavage"
      wearable="shape"
@@ -7307,7 +7296,6 @@
     <param
      id="685"
      group="0"
-     sex="male"
      name="Chest_Male_No_Pecs"
      label="Pectorals"
      wearable="shape"
@@ -7525,7 +7513,6 @@
     <param
      id="1200"
      group="1"
-     sex="female"
      name="Breast_Physics_UpDown_Driven"
      wearable="physics"
      edit_group="driven"
@@ -7547,7 +7534,6 @@
     <param
      id="1201"
      group="1"
-     sex="female"
      name="Breast_Physics_InOut_Driven"
      wearable="physics"
      edit_group="driven"
@@ -8079,7 +8065,6 @@
     <param
      id="20879"
      group="1"
-     sex="male"
      name="Male_Package"
      value_min="-.5"
      value_max="2">
@@ -9837,7 +9822,6 @@ render_pass="bump">
 
       <param
        id="1004"
-       sex="male"
        group="1"
        wearable="hair"
        edit_group="driven"
@@ -9852,7 +9836,6 @@ render_pass="bump">
 
       <param
        id="1006"
-       sex="male"
        group="1"
        wearable="hair"
        edit_group="driven"
@@ -9867,7 +9850,6 @@ render_pass="bump">
 
       <param
        id="1008"
-       sex="male"
        group="1"
        wearable="hair"
        edit_group="driven"
@@ -9882,7 +9864,6 @@ render_pass="bump">
 
       <param
        id="1010"
-       sex="male"
        group="1"
        edit_group="driven"
        wearable="hair"
@@ -9898,7 +9879,6 @@ render_pass="bump">
       <param
        id="1012"
        group="1"
-       sex="male"
        wearable="hair"
        edit_group="driven"
        name="5 O'Clock Shadow bump"
@@ -9924,7 +9904,6 @@ render_pass="bump">
 
       <param
        id="1005"
-       sex="male"
        group="1"
        wearable="hair"
        edit_group="driven"
@@ -9939,7 +9918,6 @@ render_pass="bump">
 
       <param
        id="1007"
-       sex="male"
        group="1"
        wearable="hair"
        edit_group="driven"
@@ -9954,7 +9932,6 @@ render_pass="bump">
 
       <param
        id="1009"
-       sex="male"
        group="1"
        wearable="hair"
        edit_group="driven"
@@ -9969,7 +9946,6 @@ render_pass="bump">
 
       <param
        id="1011"
-       sex="male"
        group="1"
        wearable="hair"
        edit_group="driven"
@@ -9986,7 +9962,6 @@ render_pass="bump">
        id="751"
        group="1"
        wearable="hair"
-       sex="male"
        edit_group="hair_facial"
        name="5 O'Clock Shadow"
        label_min="Dense hair"
@@ -15097,7 +15072,6 @@ render_pass="bump">
     <param
      id="105"
      group="0"
-     sex="female"
      wearable="shape"
      edit_group="shape_torso"
      edit_group_order="6"
@@ -15262,7 +15236,6 @@ render_pass="bump">
     <param
      id="649"
      group="0"
-     sex="female"
      wearable="shape"
      edit_group="shape_torso"
      edit_group_order="1.1"
@@ -15297,7 +15270,6 @@ render_pass="bump">
     <param
      id="678"
      group="0"
-     sex="male"
      wearable="shape"
      edit_group="shape_torso"
      edit_group_order="1"
@@ -15365,10 +15337,14 @@ render_pass="bump">
      id="80"
      name="male"
      group="0"
-     edit_group="dummy"
+     edit_group="shape_body"
+     label="Gender"
+     label_min="Female"
+     label_max="Male"
      wearable="shape"
      value_min="0"
-     value_max="1">
+     value_max="1"
+     camera_distance="2.2">
       <param_driver>
         <driven
          id="32" />
@@ -15583,7 +15559,6 @@ render_pass="bump">
     <param
      id="752"
      group="0"
-     sex="male"
      wearable="hair"
      edit_group="hair_facial"
      edit_group_order="1"
@@ -15865,7 +15840,6 @@ render_pass="bump">
     <param
      id="879"
      group="0"
-     sex="male"
      name="Male_Package"
      label="Package"
      wearable="shape"
@@ -16053,7 +16027,6 @@ render_pass="bump">
 
     <param
      id="166"
-     sex="male"
      group="0"
      wearable="hair"
      edit_group="hair_facial"
@@ -16079,7 +16052,6 @@ render_pass="bump">
 
     <param
      id="167"
-     sex="male"
      group="0"
      wearable="hair"
      edit_group="hair_facial"
@@ -16105,7 +16077,6 @@ render_pass="bump">
 
     <param
      id="168"
-     sex="male"
      group="0"
      wearable="hair"
      edit_group="hair_facial"
@@ -16131,7 +16102,6 @@ render_pass="bump">
 
     <param
      id="169"
-     sex="male"
      group="0"
      wearable="hair"
      edit_group="hair_facial"
@@ -16944,7 +16914,6 @@ render_pass="bump">
    <param
      id="1100"
      group="1"
-     sex="female"
      wearable="physics"
      name="Breast_Physics_UpDown_Controller"
      label="Breast Physics UpDown Controller"
@@ -16960,7 +16929,6 @@ render_pass="bump">
    <param
      id="1101"
      group="1"
-     sex="female"
      wearable="physics"
      name="Breast_Physics_InOut_Controller"
      label="Breast Physics InOut Controller"
@@ -17040,7 +17008,6 @@ render_pass="bump">
     <param
      id="10000"
      group="0"
-     sex="female"
      name="Breast_Physics_Mass"
      label="Breast Physics Mass"
      wearable="physics"
@@ -17053,7 +17020,6 @@ render_pass="bump">
     <param
      id="10001"
      group="0"
-     sex="female"
      name="Breast_Physics_Gravity"
      label="Breast Physics Gravity"
      wearable="physics"
@@ -17067,7 +17033,6 @@ render_pass="bump">
    <param
      id="10002"
      group="0"
-     sex="female"
      name="Breast_Physics_Drag"
      label="Breast Physics Drag"
      wearable="physics"
@@ -17081,7 +17046,6 @@ render_pass="bump">
    <param
      id="10003"
      group="0"
-     sex="female"
      name="Breast_Physics_UpDown_Max_Effect"
      label="Breast Physics UpDown Max Effect"
      wearable="physics"
@@ -17094,7 +17058,6 @@ render_pass="bump">
     <param
      id="10004"
      group="0"
-     sex="female"
      name="Breast_Physics_UpDown_Spring"
      label="Breast Physics UpDown Spring"
      wearable="physics"
@@ -17107,7 +17070,6 @@ render_pass="bump">
     <param
      id="10005"
      group="0"
-     sex="female"
      name="Breast_Physics_UpDown_Gain"
      label="Breast Physics UpDown Gain"
      wearable="physics"
@@ -17120,7 +17082,6 @@ render_pass="bump">
     <param
      id="10006"
      group="0"
-     sex="female"
      name="Breast_Physics_UpDown_Damping"
      label="Breast Physics UpDown Damping"
      wearable="physics"
@@ -17134,7 +17095,6 @@ render_pass="bump">
    <param
      id="10007"
      group="0"
-     sex="female"
      name="Breast_Physics_InOut_Max_Effect"
      label="Breast Physics InOut Max Effect"
      wearable="physics"
@@ -17147,7 +17107,6 @@ render_pass="bump">
     <param
      id="10008"
      group="0"
-     sex="female"
      name="Breast_Physics_InOut_Spring"
      label="Breast Physics InOut Spring"
      wearable="physics"
@@ -17160,7 +17119,6 @@ render_pass="bump">
     <param
      id="10009"
      group="0"
-     sex="female"
      name="Breast_Physics_InOut_Gain"
      label="Breast Physics InOut Gain"
      wearable="physics"
@@ -17173,7 +17131,6 @@ render_pass="bump">
     <param
      id="10010"
      group="0"
-     sex="female"
      name="Breast_Physics_InOut_Damping"
      label="Breast Physics InOut Damping"
      wearable="physics"
@@ -17407,7 +17364,6 @@ render_pass="bump">
    <param
      id="10029"
      group="0"
-     sex="female"
      name="Breast_Physics_LeftRight_Max_Effect"
      label="Breast Physics LeftRight Max Effect"
      wearable="physics"
@@ -17420,7 +17376,6 @@ render_pass="bump">
     <param
      id="10030"
      group="0"
-     sex="female"
      name="Breast_Physics_LeftRight_Spring"
      label="Breast Physics LeftRight Spring"
      wearable="physics"
@@ -17433,7 +17388,6 @@ render_pass="bump">
     <param
      id="10031"
      group="0"
-     sex="female"
      name="Breast_Physics_LeftRight_Gain"
      label="Breast Physics LeftRight Gain"
      wearable="physics"
@@ -17446,7 +17400,6 @@ render_pass="bump">
     <param
      id="10032"
      group="0"
-     sex="female"
      name="Breast_Physics_LeftRight_Damping"
      label="Breast Physics LeftRight Damping"
      wearable="physics"
diff --git a/indra/newview/skins/default/xui/da/strings.xml b/indra/newview/skins/default/xui/da/strings.xml
index e4f99d14e9..2e351cbc65 100644
--- a/indra/newview/skins/default/xui/da/strings.xml
+++ b/indra/newview/skins/default/xui/da/strings.xml
@@ -2688,6 +2688,9 @@ Hvis du bliver ved med at modtage denne besked, kontakt venligst [SUPPORT_SITE].
 	<string name="Full Sides">
 		Meget hår
 	</string>
+	<string name="Gender">
+		Køn
+	</string>
 	<string name="Glossy">
 		Skinnende
 	</string>
diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml
index a9e7626dc5..4a4a34911d 100644
--- a/indra/newview/skins/default/xui/de/strings.xml
+++ b/indra/newview/skins/default/xui/de/strings.xml
@@ -1248,6 +1248,7 @@ Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_
 	<string name="Full Front">Vorne volles Haar</string>
 	<string name="Full Hair Sides">Seitlich volles Haar</string>
 	<string name="Full Sides">Volle Seiten</string>
+	<string name="Gender">Geschlecht</string>
 	<string name="Glossy">Glänzend</string>
 	<string name="Glove Fingers">Handschuhfinger</string>
 	<string name="Glove Length">Handschuhlänge</string>
diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
index 85d73ece48..b3aadb8ea1 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
@@ -202,57 +202,6 @@
          top="10"
          value="Shape:"
          width="150" />
-        <radio_group
-         control_name="AvatarSex"
-         follows="top|right"
-         height="20"
-         layout="topleft"
-         left="210"
-         name="sex_radio"
-         top="5"
-         width="110">
-            <radio_item
-             follows="all"
-             height="16"
-             label=""
-             layout="topleft"
-             left="0"
-             name="sex_male"
-             tool_tip="Male"
-             value="1"
-             width="40" />
-            <radio_item
-             follows="all"
-             height="16"
-             label=""
-             layout="topleft"
-             left_pad="10"
-             name="sex_female"
-             tool_tip="Female"
-             value="0"
-             width="40"/>
-        </radio_group>
-        <!--  graphical labels for the radio buttons above -->
-        <icon
-         follows="top|right"
-         height="16"
-         image_name="icons/Male.png"
-         layout="topleft"
-         left="230"
-         name="male_icon"
-         tool_tip="Male"
-         top="7"
-         width="16" />
-        <icon
-         follows="top|right"
-         height="16"
-         image_name="icons/Female.png"
-         layout="topleft"
-         left="280"
-         name="female_icon"
-         tool_tip="Female"
-         top="7"
-         width="16" />
         <line_editor
          follows="all"
          height="23"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 3fbb5bc7e8..e7d1233890 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3232,6 +3232,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
 <string name="Full Front">Full Front</string>
 <string name="Full Hair Sides">Full Hair Sides</string>
 <string name="Full Sides">Full Sides</string>
+<string name="Gender">Gender</string>
 <string name="Glossy">Glossy</string>
 <string name="Glove Fingers">Glove Fingers</string>
 
diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml
index cd8e7687ae..fd85cdc252 100644
--- a/indra/newview/skins/default/xui/es/strings.xml
+++ b/indra/newview/skins/default/xui/es/strings.xml
@@ -1227,6 +1227,7 @@ Si sigues recibiendo este mensaje, contacta con [SUPPORT_SITE].</string>
 	<string name="Full Front">Sin cortar</string>
 	<string name="Full Hair Sides">Pelo: volumen a los lados</string>
 	<string name="Full Sides">Volumen total</string>
+	<string name="Gender">Sexo</string>
 	<string name="Glossy">Con brillo</string>
 	<string name="Glove Fingers">Guantes: dedos</string>
 	<string name="Glove Length">Guantes: largo</string>
diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml
index 0a3fbeb603..5969856086 100644
--- a/indra/newview/skins/default/xui/fr/strings.xml
+++ b/indra/newview/skins/default/xui/fr/strings.xml
@@ -1249,6 +1249,7 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].</string>
 	<string name="Full Front">Devant touffu</string>
 	<string name="Full Hair Sides">Côtés touffus</string>
 	<string name="Full Sides">Côtés touffus</string>
+	<string name="Gender">Sexe</string>
 	<string name="Glossy">Brillant</string>
 	<string name="Glove Fingers">Gants avec doigts</string>
 	<string name="Glove Length">Longueur</string>
diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml
index 178bb90ca6..e12203c6b7 100644
--- a/indra/newview/skins/default/xui/it/strings.xml
+++ b/indra/newview/skins/default/xui/it/strings.xml
@@ -1229,6 +1229,7 @@ Se il messaggio persiste, contatta [SUPPORT_SITE].</string>
 	<string name="Full Front">Anteriore gonfio</string>
 	<string name="Full Hair Sides">Lati capelli gonfi</string>
 	<string name="Full Sides">Lati gonfi</string>
+	<string name="Gender">Sesso</string>
 	<string name="Glossy">Lucido</string>
 	<string name="Glove Fingers">Dita con guanti</string>
 	<string name="Glove Length">Lunghezza guanti</string>
diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml
index fa6c329fe7..8fe69162c5 100644
--- a/indra/newview/skins/default/xui/ja/strings.xml
+++ b/indra/newview/skins/default/xui/ja/strings.xml
@@ -5052,6 +5052,9 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
 	<string name="Full Sides">
 		生え揃ったサイド
 	</string>
+	<string name="Gender">
+		性別
+	</string>
 	<string name="Glossy">
 		あり
 	</string>
diff --git a/indra/newview/skins/default/xui/pl/strings.xml b/indra/newview/skins/default/xui/pl/strings.xml
index 26ec6cc9dc..a2d386e8ac 100644
--- a/indra/newview/skins/default/xui/pl/strings.xml
+++ b/indra/newview/skins/default/xui/pl/strings.xml
@@ -3318,6 +3318,9 @@ Jeżeli nadal otrzymujesz ten komunikat, skontaktuj się z [SUPPORT_SITE].
 	<string name="Full Sides">
 		Gęste boki
 	</string>
+	<string name="Gender">
+		Płeć
+	</string>
 	<string name="Glossy">
 		Błyszcząca
 	</string>
diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml
index 6db5da2e89..5076e21198 100644
--- a/indra/newview/skins/default/xui/pt/strings.xml
+++ b/indra/newview/skins/default/xui/pt/strings.xml
@@ -1192,6 +1192,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].</string>
 	<string name="Full Front">Frente cheia</string>
 	<string name="Full Hair Sides">Cabelos laterais cheios</string>
 	<string name="Full Sides">Lados cheios</string>
+	<string name="Gender">Sexo</string>
 	<string name="Glossy">Brilhante</string>
 	<string name="Glove Fingers">Dedos da luva</string>
 	<string name="Glove Length">Comprimento das luvas</string>
diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml
index 61d836a2d1..8fc9641624 100644
--- a/indra/newview/skins/default/xui/ru/strings.xml
+++ b/indra/newview/skins/default/xui/ru/strings.xml
@@ -3479,6 +3479,9 @@ support@secondlife.com.
 	<string name="Full Sides">
 		По бокам
 	</string>
+	<string name="Gender">
+		Пол
+	</string>
 	<string name="Glossy">
 		Блестящие
 	</string>
diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml
index e709a4c5d6..687de84401 100644
--- a/indra/newview/skins/default/xui/tr/strings.xml
+++ b/indra/newview/skins/default/xui/tr/strings.xml
@@ -3482,6 +3482,9 @@ Bu iletiyi almaya devam ederseniz, lütfen [SUPPORT_SITE] bölümüne başvurun.
 	<string name="Full Sides">
 		Saçlar Yanda
 	</string>
+	<string name="Gender">
+		Cinsiyet
+	</string>
 	<string name="Glossy">
 		Parlak
 	</string>
diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml
index bdb16c9bf1..cf94391aa4 100644
--- a/indra/newview/skins/default/xui/zh/strings.xml
+++ b/indra/newview/skins/default/xui/zh/strings.xml
@@ -3475,6 +3475,9 @@ http://secondlife.com/support 求助解決問題。
 	<string name="Full Sides">
 		兩側飽滿
 	</string>
+	<string name="Gender">
+		性别
+	</string>
 	<string name="Glossy">
 		光亮
 	</string>
-- 
cgit v1.2.3


From 4a07fd3762b6707b737942c87d1c4d5aeb229678 Mon Sep 17 00:00:00 2001
From: nerodevo <100370411+nerodevo@users.noreply.github.com>
Date: Tue, 12 Mar 2024 14:03:19 -0500
Subject: Remove invalid text color parameter from login screen #960 (#972)

Removed parameter since 'Remember me' isn't using color emphasis.
If emphasis color is desired, then let me know if 'Remember me'
should use same color emphasis for consistency.
---
 indra/newview/skins/default/xui/en/panel_login.xml | 1 -
 1 file changed, 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index 3aba80909a..86b08bb24a 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -144,7 +144,6 @@
     control_name="RememberPassword"
     follows="left|top"
     font="SansSerifMedium"
-    text_color="EmphasisColor"
     height="24"
     left="408"
     bottom_delta="0"
-- 
cgit v1.2.3


From b0ea6f5e0aed993b0f05de6bf7d03d81b520a5d0 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 13 Mar 2024 22:15:56 +0200
Subject: viewer#945 Some worn items are missing from Avatar floater's Outfits
 tab

---
 indra/newview/llaisapi.cpp                        |  2 --
 indra/newview/llinventorymodelbackgroundfetch.cpp | 17 +++++++++++++++++
 indra/newview/lloutfitslist.cpp                   | 12 ++----------
 3 files changed, 19 insertions(+), 12 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 17e1a27934..68b07a46c4 100644
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -1385,8 +1385,6 @@ void AISUpdate::parseCategory(const LLSD& category_map, S32 depth)
                      && curr_cat->getVersion() > LLViewerInventoryCategory::VERSION_UNKNOWN
                      && version > curr_cat->getVersion())
             {
-                // Potentially should new_cat->setVersion(unknown) here,
-                // but might be waiting for a callback that would increment
                 LL_DEBUGS("Inventory") << "Category " << category_id
                     << " is stale. Known version: " << curr_cat->getVersion()
                     << " server version: " << version << LL_ENDL;
diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index 1f410bea10..c36b4b9726 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -30,6 +30,7 @@
 #include "llaisapi.h"
 #include "llagent.h"
 #include "llappviewer.h"
+#include "llappearancemgr.h"
 #include "llcallbacklist.h"
 #include "llinventorymodel.h"
 #include "llinventorypanel.h"
@@ -423,6 +424,22 @@ void LLInventoryModelBackgroundFetch::fetchCOF(nullary_func_t callback)
                          callback();
                          LLUUID cat_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
                          LLInventoryModelBackgroundFetch::getInstance()->onAISFolderCalback(cat_id, id, FT_DEFAULT);
+
+                         if (id.notNull())
+                         {
+                             // COF might have fetched base outfit folder through a link, but it hasn't
+                             // fetched base outfit's content, which doesn't nessesary match COF,
+                             // so make sure it's up to date
+                             LLUUID baseoutfit_id = LLAppearanceMgr::getInstance()->getBaseOutfitUUID();
+                             if (baseoutfit_id.notNull())
+                             {
+                                 LLViewerInventoryCategory* cat = gInventory.getCategory(baseoutfit_id);
+                                 if (!cat || cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)
+                                 {
+                                     LLInventoryModelBackgroundFetch::getInstance()->fetchFolderAndLinks(baseoutfit_id, no_op);
+                                 }
+                             }
+                         }
                      });
 
     // start idle loop to track completion
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 5c7792b0df..ba714cbedd 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -885,18 +885,10 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id)
         ++items_iter)
     {
         LLViewerInventoryCategory *cat = gInventory.getCategory(*items_iter);
-        if (!cat)
+        if (cat)
         {
-            LLInventoryObject* obj = gInventory.getObject(*items_iter);
-            if(!obj || (obj->getType() != LLAssetType::AT_CATEGORY))
-            {
-                return;
-            }
-            cat = (LLViewerInventoryCategory*)obj;
+            updateChangedCategoryName(cat, cat->getName());
         }
-        std::string name = cat->getName();
-
-        updateChangedCategoryName(cat, name);
     }
 
     sortOutfits();
-- 
cgit v1.2.3


From 7975a45eb0e72c78a90f2fde449e14c1f607561b Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 14 Mar 2024 23:04:54 +0200
Subject: viewer#970 Fixed param validation warnings

---
 indra/newview/llfloateremojipicker.cpp                     | 1 +
 indra/newview/llpanelemojicomplete.cpp                     | 3 +++
 indra/newview/skins/default/xui/en/floater_fast_timers.xml | 2 ++
 indra/newview/skins/default/xui/en/floater_world_map.xml   | 3 ++-
 4 files changed, 8 insertions(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/llfloateremojipicker.cpp b/indra/newview/llfloateremojipicker.cpp
index 1578caa39c..6d80a18599 100644
--- a/indra/newview/llfloateremojipicker.cpp
+++ b/indra/newview/llfloateremojipicker.cpp
@@ -424,6 +424,7 @@ void LLFloaterEmojiPicker::fillGroups()
 
     LLButton::Params params;
     params.font = LLFontGL::getFontEmoji();
+    params.name = "all_categories";
 
     LLRect rect;
     rect.mTop = mGroups->getRect().getHeight();
diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp
index e6e3a10e13..c7c0627009 100644
--- a/indra/newview/llpanelemojicomplete.cpp
+++ b/indra/newview/llpanelemojicomplete.cpp
@@ -68,6 +68,9 @@ LLPanelEmojiComplete::LLPanelEmojiComplete(const LLPanelEmojiComplete::Params& p
     {
         LLScrollbar::Params sbparams;
         sbparams.orientation(LLScrollbar::VERTICAL);
+        sbparams.doc_size(mTotalEmojis);
+        sbparams.doc_pos(0);
+        sbparams.page_size(mVisibleEmojis);
         sbparams.change_callback([this](S32 index, LLScrollbar*) { onScrollbarChange(index); });
         mScrollbar = LLUICtrlFactory::create<LLScrollbar>(sbparams);
         addChild(mScrollbar);
diff --git a/indra/newview/skins/default/xui/en/floater_fast_timers.xml b/indra/newview/skins/default/xui/en/floater_fast_timers.xml
index 645003cc14..f4e61a828e 100644
--- a/indra/newview/skins/default/xui/en/floater_fast_timers.xml
+++ b/indra/newview/skins/default/xui/en/floater_fast_timers.xml
@@ -74,6 +74,8 @@
         orientation="vertical"
         step_size="16"
         doc_size="3000"
+        page_size="50"
+        doc_pos="0"
           />
     </layout_panel>
     <layout_panel name="timers_panel"
diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml
index c965a4427c..fbba1290c0 100644
--- a/indra/newview/skins/default/xui/en/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/en/floater_world_map.xml
@@ -34,7 +34,8 @@
    top="16"
    left="0"
    right="-1"
-   bottom="-1">
+   bottom="-1"
+   orientation="horizontal">
     <layout_panel
      name="map_lp"
      width="385"
-- 
cgit v1.2.3


From 18c4d8732aae9a8bf10d6a84bc37261b242d16c6 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 25 Mar 2024 22:53:47 +0200
Subject: viewer-private#216 Viewer fails to rename vivox logs

---
 indra/newview/llvoicevivox.cpp | 1 +
 1 file changed, 1 insertion(+)

(limited to 'indra')

diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 3725510b6a..bda8c35702 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -989,6 +989,7 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
             std::string old_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SLVoice.old");
             if (gDirUtilp->fileExists(new_log))
             {
+                LLFile::remove(old_log, ENOENT);
                 LLFile::rename(new_log, old_log);
             }
             
-- 
cgit v1.2.3


From eeb43b604ccb3348907bd06c0135e7824879fe57 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 25 Mar 2024 22:59:08 +0200
Subject: viewer-private#217 Rotate cef log file

---
 indra/newview/llviewermedia.cpp | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 02108e861a..59701cc5b3 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1723,7 +1723,13 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
 		std::string user_data_path_cache = gDirUtilp->getCacheDir(false);
 		user_data_path_cache += gDirUtilp->getDirDelimiter();
 
-		std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef_log.txt");
+		std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef.txt");
+        std::string user_data_path_cef_old = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef.old");
+        if (gDirUtilp->fileExists(user_data_path_cef_log))
+        {
+            LLFile::remove(user_data_path_cef_old, ENOENT);
+            LLFile::rename(user_data_path_cef_log, user_data_path_cef_old);
+        }
 
 		// See if the plugin executable exists
 		llstat s;
-- 
cgit v1.2.3


From aa892d2c35d1f03ad49aceba0f89f0ab3d40c315 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 25 Mar 2024 15:50:47 +0200
Subject: viewer#1016 Incorrect behavior of Physics Shapes rendering

---
 indra/newview/llphysicsshapebuilderutil.cpp | 53 +++++++++++++++++++++++------
 indra/newview/llphysicsshapebuilderutil.h   |  2 ++
 2 files changed, 45 insertions(+), 10 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llphysicsshapebuilderutil.cpp b/indra/newview/llphysicsshapebuilderutil.cpp
index 9603ee6329..a79cc984c1 100644
--- a/indra/newview/llphysicsshapebuilderutil.cpp
+++ b/indra/newview/llphysicsshapebuilderutil.cpp
@@ -28,6 +28,26 @@
 
 #include "llphysicsshapebuilderutil.h"
 
+#include "llmeshrepository.h"
+
+bool LLPhysicsVolumeParams::hasDecomposition() const
+ {
+    if (!isMeshSculpt())
+    {
+        return false;
+    }
+
+    LLUUID mesh_id = getSculptID();
+    if (mesh_id.isNull())
+    {
+        return false;
+    }
+
+    LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id);
+
+    return decomp != NULL;
+}
+
 /* static */
 void LLPhysicsShapeBuilderUtil::determinePhysicsShape( const LLPhysicsVolumeParams& volume_params, const LLVector3& scale, PhysicsShapeSpecification& specOut)
 {
@@ -200,19 +220,32 @@ void LLPhysicsShapeBuilderUtil::determinePhysicsShape( const LLPhysicsVolumePara
 	{
 		specOut.mType = PhysicsShapeSpecification::PRIM_CONVEX;
 	}
-    else if (volume_params.isMeshSculpt() &&
-             // Check overall dimensions, not individual triangles.
-             (scale.mV[0] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE ||
-              scale.mV[1] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE ||
-              scale.mV[2] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE
-              ) )
+    else if (volume_params.isMeshSculpt())
     {
-        // Server distinguishes between user-specified or default convex mesh, vs server's thin-triangle override, but we don't.
-        specOut.mType = PhysicsShapeSpecification::PRIM_CONVEX;
+        // Check overall dimensions, not individual triangles.
+        if (scale.mV[0] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE
+            || scale.mV[1] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE
+            || scale.mV[2] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE
+            )
+        {
+            if (volume_params.hasDecomposition())
+            {
+                specOut.mType = PhysicsShapeSpecification::USER_MESH;
+            }
+            else
+            {
+                // Server distinguishes between user-specified or default convex mesh, vs server's thin-triangle override, but we don't.
+                specOut.mType = PhysicsShapeSpecification::PRIM_CONVEX;
+            }
+        }
+        else
+        {
+            specOut.mType = PhysicsShapeSpecification::USER_MESH;
+        }
     }
-	else if ( volume_params.isSculpt() ) // Is a sculpt of any kind (mesh or legacy)
+	else if ( volume_params.isSculpt() )
 	{
-		specOut.mType = volume_params.isMeshSculpt() ? PhysicsShapeSpecification::USER_MESH : PhysicsShapeSpecification::SCULPT;
+        specOut.mType = PhysicsShapeSpecification::SCULPT;
 	}
 	else // Resort to mesh 
 	{
diff --git a/indra/newview/llphysicsshapebuilderutil.h b/indra/newview/llphysicsshapebuilderutil.h
index b3b100296f..24e68fcf77 100644
--- a/indra/newview/llphysicsshapebuilderutil.h
+++ b/indra/newview/llphysicsshapebuilderutil.h
@@ -78,6 +78,8 @@ public:
 
 	bool shouldForceConvex() const { return mForceConvex; }
 
+    bool hasDecomposition() const;
+
 private:
 	bool mForceConvex;
 };
-- 
cgit v1.2.3


From f25f51a20a7bcefcf51de5e71f827c74c659571a Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 27 Mar 2024 00:28:04 +0200
Subject: viewer-private#131 landmark panel closes after a rename

if destination was changed
---
 indra/newview/llfloatercreatelandmark.cpp | 4 ++--
 indra/newview/llfloatercreatelandmark.h   | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp
index b82d8a29ba..7dc3e4afe3 100644
--- a/indra/newview/llfloatercreatelandmark.cpp
+++ b/indra/newview/llfloatercreatelandmark.cpp
@@ -389,6 +389,7 @@ void LLFloaterCreateLandmark::setItem(const uuid_set_t& items)
 			{
 				mItem = item;
                 mAssetID = mItem->getAssetUUID();
+                mParentID = mItem->getParentUUID();
                 setVisibleAndFrontmost(true);
 				break;
 			}
@@ -418,8 +419,7 @@ void LLFloaterCreateLandmark::updateItem(const uuid_set_t& items, U32 mask)
                 closeFloater();
             }
 
-            LLUUID folder_id = mFolderCombo->getValue().asUUID();
-            if (folder_id != mItem->getParentUUID())
+            if (mParentID != mItem->getParentUUID())
             {
                 // user moved landmark in inventory,
                 // assume that we are done all other changes should already be commited
diff --git a/indra/newview/llfloatercreatelandmark.h b/indra/newview/llfloatercreatelandmark.h
index d84f5ae1fc..8a1d5ae099 100644
--- a/indra/newview/llfloatercreatelandmark.h
+++ b/indra/newview/llfloatercreatelandmark.h
@@ -69,6 +69,7 @@ private:
 	LLTextEditor*	mNotesEditor;
 	LLUUID			mLandmarksID;
     LLUUID			mAssetID;
+    LLUUID			mParentID;
 
 	LLLandmarksInventoryObserver*	mInventoryObserver;
 	LLPointer<LLInventoryItem>		mItem;
-- 
cgit v1.2.3


From cc68803f24d231b89061d855f7bbfe99b99740b9 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 27 Mar 2024 20:13:04 +0200
Subject: viewer#1061 Altitudes are invisible in region's environment

---
 indra/newview/skins/default/xui/en/panel_region_environment.xml | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/skins/default/xui/en/panel_region_environment.xml b/indra/newview/skins/default/xui/en/panel_region_environment.xml
index 0b3639f779..67eb8f2ca9 100644
--- a/indra/newview/skins/default/xui/en/panel_region_environment.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_environment.xml
@@ -264,8 +264,7 @@
                                 top_pad="1"
                                 halign="right"
                                 name="txt_alt1">
-                            Sky [INDEX]
-                            [ALTITUDE]m
+                            Sky [INDEX]&#xA;[ALTITUDE]m
                         </text>
                         <line_editor
                                 follows="left|top"
@@ -310,8 +309,7 @@
                                 top_pad="1"
                                 halign="right"
                                 name="txt_alt2">
-                            Sky [INDEX]
-                            [ALTITUDE]m
+                            Sky [INDEX]&#xA;[ALTITUDE]m
                         </text>
                         <line_editor
                                 follows="left|top"
@@ -356,8 +354,7 @@
                                 top_pad="1"
                                 halign="right"
                                 name="txt_alt3">
-                            Sky [INDEX]
-                            [ALTITUDE]m
+                            Sky [INDEX]&#xA;[ALTITUDE]m
                         </text>
                         <line_editor
                                 follows="left|top"
-- 
cgit v1.2.3


From 4173fa1a9ef79c27d39d9ab9dbee46f109fbf510 Mon Sep 17 00:00:00 2001
From: AiraYumi <aira.youme@airanyumi.net>
Date: Sat, 30 Mar 2024 06:59:21 -0400
Subject: linux build fix

---
 indra/cmake/Copy3rdPartyLibs.cmake  | 14 +++++++-------
 indra/cmake/ICU4C.cmake             |  4 ++--
 indra/cmake/ViewerMiscLibs.cmake    |  3 ++-
 indra/llcommon/llprocessor.cpp      |  2 +-
 indra/llcommon/llsdutil.cpp         |  4 ++--
 indra/llimagej2coj/llimagej2coj.cpp |  1 -
 indra/llrender/llglheaders.h        | 19 +++++++++++++++++++
 7 files changed, 33 insertions(+), 14 deletions(-)

(limited to 'indra')

diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index 9f79c13a97..48930c1c19 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -225,14 +225,14 @@ elseif(LINUX)
                  libapr-1.so.0
                  libaprutil-1.so.0
                  libatk-1.0.so
-                 libfreetype.so.6.6.2
-                 libfreetype.so.6
+                 #libfreetype.so.6.6.2
+                 #libfreetype.so.6
                  libhunspell-1.3.so.0.0.0
-                 libopenjp2.so
-                 libuuid.so.16
-                 libuuid.so.16.0.22
-                 libfontconfig.so.1.8.0
-                 libfontconfig.so.1
+                 #libopenjp2.so
+                 #libuuid.so.16
+                 #libuuid.so.16.0.22
+                 #libfontconfig.so.1.8.0
+                 #libfontconfig.so.1
                  libgmodule-2.0.so
                  libgobject-2.0.so
                  )
diff --git a/indra/cmake/ICU4C.cmake b/indra/cmake/ICU4C.cmake
index 7b27665483..a9714696b4 100644
--- a/indra/cmake/ICU4C.cmake
+++ b/indra/cmake/ICU4C.cmake
@@ -12,8 +12,8 @@ if (WINDOWS)
   target_link_libraries( ll::icu4c INTERFACE  icuuc)
 elseif(DARWIN)
   target_link_libraries( ll::icu4c INTERFACE  icuuc)
-#elseif(LINUX)
-##  target_link_libraries( ll::icu4c INTERFACE  )
+elseif(LINUX)
+  target_link_libraries( ll::icu4c INTERFACE  icuuc)
 else()
   message(FATAL_ERROR "Invalid platform")
 endif()
diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake
index cae68fbc11..3e5a37b277 100644
--- a/indra/cmake/ViewerMiscLibs.cmake
+++ b/indra/cmake/ViewerMiscLibs.cmake
@@ -6,7 +6,8 @@ if (LINUX)
   add_library( ll::fontconfig INTERFACE IMPORTED )
 
   if( NOT USE_CONAN )
-    use_prebuilt_binary(fontconfig)
+    find_package(Fontconfig REQUIRED)
+    target_link_libraries( ll::fontconfig INTERFACE Fontconfig::Fontconfig )
   else()
     target_link_libraries( ll::fontconfig INTERFACE CONAN_PKG::fontconfig )
   endif()
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index 28f8bc2b93..7bca86119c 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -867,7 +867,7 @@ private:
 		LLPI_SET_INFO_INT(eModel, "model");
 
 		
-		S32 family;							 
+		S32 family = 0;							 
 		if (!cpuinfo["cpu family"].empty() 
 			&& LLStringUtil::convertToS32(cpuinfo["cpu family"], family))	
 		{ 
diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index e98fc0285a..c3e7c544ec 100644
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -161,7 +161,7 @@ LLSD ll_binary_from_string(const LLSD& sd)
 char* ll_print_sd(const LLSD& sd)
 {
 	const U32 bufferSize = 10 * 1024;
-	static char buffer[bufferSize];
+	static char buffer[bufferSize + 1];
 	std::ostringstream stream;
 	//stream.rdbuf()->pubsetbuf(buffer, bufferSize);
 	stream << LLSDOStreamer<LLSDXMLFormatter>(sd);
@@ -183,7 +183,7 @@ char* ll_pretty_print_sd_ptr(const LLSD* sd)
 char* ll_pretty_print_sd(const LLSD& sd)
 {
 	const U32 bufferSize = 100 * 1024;
-	static char buffer[bufferSize];
+	static char buffer[bufferSize + 1];
 	std::ostringstream stream;
 	//stream.rdbuf()->pubsetbuf(buffer, bufferSize);
 	stream << LLSDOStreamer<LLSDXMLFormatter>(sd, LLSDFormatter::OPTIONS_PRETTY);
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index 6c06c6de38..d0351a553c 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -573,7 +573,6 @@ public:
         for (S32 c = 0; c < numcomps; c++)
         {
             cmptparm[c].prec = 8;
-            cmptparm[c].bpp = 8;
             cmptparm[c].sgnd = 0;
             cmptparm[c].dx = parameters.subsampling_dx;
             cmptparm[c].dy = parameters.subsampling_dy;
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index b80680a3d2..c1238ac6b9 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -1029,6 +1029,25 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
 
 #include <OpenGL/gl.h>
 
+#elif LL_LINUX
+
+#define GL_GLEXT_PROTOTYPES
+#define GLX_GLEXT_PROTOTYPES
+
+#include "GL/gl.h"
+#include "GL/glu.h"
+#include "GL/glext.h"
+#include "GL/glx.h"
+
+// The __APPLE__ kludge is to make glh_extensions.h not symbol-clash horribly
+# define __APPLE__
+# include "GL/glh_extensions.h"
+# undef __APPLE__
+
+// #include <X11/Xlib.h>
+// #include <X11/Xutil.h>
+#include "GL/glh_extensions.h"
+
 #endif // LL_MESA / LL_WINDOWS / LL_DARWIN
 
 // Even when GL_ARB_depth_clamp is available in the driver, the (correct)
-- 
cgit v1.2.3


From c2e0ee9231a547b4f6fd65487a7102036a852ed6 Mon Sep 17 00:00:00 2001
From: Bennett Goble <signal@lindenlab.com>
Date: Fri, 29 Mar 2024 14:58:33 -0700
Subject: BUG-134040: Fix broken SOCKS5 proxy

Second Life's SOCKS5 proxy has been broken on windows for at least six
years due to a conflation of milliseconds and microseconds in the APR
timeout value used when attempting to ping the proxy.
---
 indra/llmessage/llproxy.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

(limited to 'indra')

diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp
index 749e599c66..17f0d9f345 100644
--- a/indra/llmessage/llproxy.cpp
+++ b/indra/llmessage/llproxy.cpp
@@ -465,7 +465,7 @@ void LLProxy::applyProxySettings(CURL* handle)
 /**
  * @brief Send one TCP packet and receive one in return.
  *
- * This operation is done synchronously with a 1000ms timeout. Therefore, it should not be used when a blocking
+ * This operation is done synchronously with a 100ms timeout. Therefore, it should not be used when a blocking
  * operation would impact the operation of the viewer.
  *
  * @param handle_ptr 	Pointer to a connected LLSocket of type STREAM_TCP.
@@ -482,7 +482,7 @@ static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataou
 
 	apr_size_t expected_len = outlen;
 
-	handle->setBlocking(1000);
+	handle->setBlocking(100000); // 100ms, 100000us. Should be sufficient for localhost, nearby network
 
   	rv = apr_socket_send(apr_socket, dataout, &outlen);
 	if (APR_SUCCESS != rv)
@@ -498,8 +498,6 @@ static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataou
 		rv = -1;
 	}
 
-	ms_sleep(1);
-
 	if (APR_SUCCESS == rv)
 	{
 		expected_len = maxinlen;
-- 
cgit v1.2.3


From 74900fd4380dd57eb444b2fc1379bd83872a0726 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 1 Apr 2024 23:59:02 +0300
Subject: triage#150 on OSX any file can be chosen for model upload

---
 indra/newview/llfilepicker.cpp | 1 +
 1 file changed, 1 insertion(+)

(limited to 'indra')

diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 4ad136e13a..7ca212e062 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -663,6 +663,7 @@ std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadF
             allowedv->push_back("gltf");
             allowedv->push_back("glb");
             break;
+        case FFLOAD_MODEL:
         case FFLOAD_COLLADA:
             allowedv->push_back("dae");
             break;
-- 
cgit v1.2.3


From a93344b4db2654e91b4daa9f2709daf448c03a8e Mon Sep 17 00:00:00 2001
From: AiraYumi <aira.youme@airanyumi.net>
Date: Mon, 1 Apr 2024 21:41:21 -0400
Subject: enable tracy for linux and build fix

---
 indra/llcommon/llprofiler.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h
index af5e5777bf..0297bbe592 100644
--- a/indra/llcommon/llprofiler.h
+++ b/indra/llcommon/llprofiler.h
@@ -74,6 +74,10 @@
 #define LL_PROFILER_CONFIGURATION           LL_PROFILER_CONFIG_FAST_TIMER
 #endif
 
+#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER
+    #include "Tracy.hpp"
+#endif
+
 extern thread_local bool gProfilerEnabled;
 
 #if defined(LL_PROFILER_CONFIGURATION) && (LL_PROFILER_CONFIGURATION > LL_PROFILER_CONFIG_NONE)
@@ -84,7 +88,6 @@ extern thread_local bool gProfilerEnabled;
 //      #define TRACY_NO_BROADCAST   1
 //      #define TRACY_ONLY_LOCALHOST 1
         #define TRACY_ONLY_IPV4      1
-        #include "Tracy.hpp"
 
         // Enable OpenGL profiling
         #define LL_PROFILER_ENABLE_TRACY_OPENGL 0
-- 
cgit v1.2.3


From dcc77324736c84705fdde1056b7ae04c583b9db1 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 2 Apr 2024 00:38:51 +0300
Subject: viewer#1104 Crash at populateFoldersList

Ensure folder creation callbacks remain alive
---
 indra/newview/llfloatercreatelandmark.cpp | 10 +++++++---
 indra/newview/llfloatercreatelandmark.h   |  2 +-
 indra/newview/llinventorybridge.cpp       | 20 +++++++++++++++++---
 indra/newview/llinventorybridge.h         |  5 ++++-
 4 files changed, 29 insertions(+), 8 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp
index 7dc3e4afe3..351f4a844c 100644
--- a/indra/newview/llfloatercreatelandmark.cpp
+++ b/indra/newview/llfloatercreatelandmark.cpp
@@ -31,6 +31,7 @@
 #include "llagent.h"
 #include "llagentui.h"
 #include "llcombobox.h"
+#include "llfloaterreg.h"
 #include "llinventoryfunctions.h"
 #include "llinventoryobserver.h"
 #include "lllandmarkactions.h"
@@ -286,8 +287,7 @@ void LLFloaterCreateLandmark::onCreateFolderClicked()
 			std::string folder_name = resp["message"].asString();
 			if (!folder_name.empty())
 			{
-				inventory_func_type func = boost::bind(&LLFloaterCreateLandmark::folderCreatedCallback, this, _1);
-				gInventory.createNewCategory(mLandmarksID, LLFolderType::FT_NONE, folder_name, func);
+				gInventory.createNewCategory(mLandmarksID, LLFolderType::FT_NONE, folder_name, folderCreatedCallback);
 				gInventory.notifyObservers();
 			}
 		}
@@ -296,7 +296,11 @@ void LLFloaterCreateLandmark::onCreateFolderClicked()
 
 void LLFloaterCreateLandmark::folderCreatedCallback(LLUUID folder_id)
 {
-	populateFoldersList(folder_id);
+    LLFloaterCreateLandmark* floater = LLFloaterReg::findTypedInstance<LLFloaterCreateLandmark>("add_landmark");
+    if (floater && !floater->isDead())
+    {
+        floater->populateFoldersList(folder_id);
+    }
 }
 
 void LLFloaterCreateLandmark::onSaveClicked()
diff --git a/indra/newview/llfloatercreatelandmark.h b/indra/newview/llfloatercreatelandmark.h
index 8a1d5ae099..f91c302df7 100644
--- a/indra/newview/llfloatercreatelandmark.h
+++ b/indra/newview/llfloatercreatelandmark.h
@@ -62,7 +62,7 @@ private:
 	void onSaveClicked();
 	void onCancelClicked();
 
-	void folderCreatedCallback(LLUUID folder_id);
+	static void folderCreatedCallback(LLUUID folder_id);
 
 	LLComboBox*		mFolderCombo;
 	LLLineEditor*	mLandmarkTitleEditor;
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 932a0316dd..0ed89292a5 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -5118,7 +5118,7 @@ void LLFolderBridge::dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointer<LLI
 
     // Note: creation will take time, so passing folder id to callback is slightly unreliable,
     // but so is collecting and passing descendants' ids
-    inventory_func_type func = boost::bind(&LLFolderBridge::outfitFolderCreatedCallback, this, inv_cat->getUUID(), _1, cb);
+    inventory_func_type func = boost::bind(outfitFolderCreatedCallback, inv_cat->getUUID(), _1, cb, mInventoryPanel);
     gInventory.createNewCategory(dest_id,
                                  LLFolderType::FT_OUTFIT,
                                  inv_cat->getName(),
@@ -5126,11 +5126,25 @@ void LLFolderBridge::dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointer<LLI
                                  inv_cat->getThumbnailUUID());
 }
 
-void LLFolderBridge::outfitFolderCreatedCallback(LLUUID cat_source_id, LLUUID cat_dest_id, LLPointer<LLInventoryCallback> cb)
+void LLFolderBridge::outfitFolderCreatedCallback(LLUUID cat_source_id,
+                                                 LLUUID cat_dest_id,
+                                                 LLPointer<LLInventoryCallback> cb,
+                                                 LLHandle<LLInventoryPanel> inventory_panel)
 {
     LLInventoryModel::cat_array_t* categories;
     LLInventoryModel::item_array_t* items;
-    getInventoryModel()->getDirectDescendentsOf(cat_source_id, categories, items);
+
+    LLInventoryPanel* panel = inventory_panel.get();
+    if (!panel)
+    {
+        return;
+    }
+    LLInventoryModel*  model = panel->getModel();
+    if (!model)
+    {
+        return;
+    }
+    model->getDirectDescendentsOf(cat_source_id, categories, items);
 
     LLInventoryObject::const_object_list_t link_array;
 
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 3cbbd68e51..ea756f5c14 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -379,7 +379,10 @@ public:
 	static void staticFolderOptionsMenu();
 
 protected:
-    void outfitFolderCreatedCallback(LLUUID cat_source_id, LLUUID cat_dest_id, LLPointer<LLInventoryCallback> cb);
+    static void outfitFolderCreatedCallback(LLUUID cat_source_id,
+                                            LLUUID cat_dest_id,
+                                            LLPointer<LLInventoryCallback> cb,
+                                            LLHandle<LLInventoryPanel> inventory_panel);
     void callback_pasteFromClipboard(const LLSD& notification, const LLSD& response);
     void perform_pasteFromClipboard();
     void gatherMessage(std::string& message, S32 depth, LLError::ELevel log_level);
-- 
cgit v1.2.3


From a6b99dbcb4ea69db73401a3101266ee49b88c9bc Mon Sep 17 00:00:00 2001
From: Andrey Lihatskiy <alihatskiy@productengine.com>
Date: Sat, 9 Mar 2024 19:19:49 +0200
Subject: Revert "Remove gender-based restrictions on shape and physics
 sliders"

This reverts commit 1ebd23ffed912a5c8c94d109f37a2c25cf169523.
---
 indra/newview/character/avatar_lad.xml             | 59 +++++++++++++++++++---
 indra/newview/skins/default/xui/da/strings.xml     |  3 --
 indra/newview/skins/default/xui/de/strings.xml     |  1 -
 .../skins/default/xui/en/panel_edit_wearable.xml   | 51 +++++++++++++++++++
 indra/newview/skins/default/xui/en/strings.xml     |  1 -
 indra/newview/skins/default/xui/es/strings.xml     |  1 -
 indra/newview/skins/default/xui/fr/strings.xml     |  1 -
 indra/newview/skins/default/xui/it/strings.xml     |  1 -
 indra/newview/skins/default/xui/ja/strings.xml     |  3 --
 indra/newview/skins/default/xui/pl/strings.xml     |  3 --
 indra/newview/skins/default/xui/pt/strings.xml     |  1 -
 indra/newview/skins/default/xui/ru/strings.xml     |  3 --
 indra/newview/skins/default/xui/tr/strings.xml     |  3 --
 indra/newview/skins/default/xui/zh/strings.xml     |  3 --
 14 files changed, 104 insertions(+), 30 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml
index 9be6275929..2cdd86267e 100644
--- a/indra/newview/character/avatar_lad.xml
+++ b/indra/newview/character/avatar_lad.xml
@@ -3822,6 +3822,7 @@
 	<param
      id="30879"
      group="1"
+     sex="male"
      name="Male_Package"
      value_min="-.5"
      value_max="2">
@@ -5812,6 +5813,7 @@
 
     <param
      id="400"
+     sex="male"
      group="1"
      name="Displace_Hair_Facial"
      label="Hair Thickess"
@@ -6836,6 +6838,7 @@
 
     <param
      id="626"
+     sex="female"
      group="1"
      name="Big_Chest"
      label="Chest Size"
@@ -6862,6 +6865,7 @@
 
     <param
      id="627"
+     sex="female"
      group="1"
      name="Small_Chest"
      label="Chest Size"
@@ -6887,6 +6891,7 @@
 
     <param
      id="843"
+     sex="female"
      group="1"
      name="No_Chest"
      label="Chest Size"
@@ -6915,6 +6920,7 @@
      group="1"
      name="Muscular_Torso"
      label="Torso Muscles"
+   sex="male"
      show_simple="true"
      wearable="shape"
      edit_group="shape_torso"
@@ -6957,6 +6963,7 @@
         group="1"
         name="Muscular_Torso"
         label="Torso Muscles"
+        sex="female"
         show_simple="true"
      wearable="shape"
      edit_group="shape_torso"
@@ -6997,6 +7004,7 @@
     <param
      id="648"
      group="1"
+     sex="female"
      name="Scrawny_Torso"
      label="Torso Muscles"
    show_simple="true"
@@ -7051,6 +7059,7 @@
     <param
      id="677"
      group="1"
+     sex="male"
      name="Scrawny_Torso_Male"
      label="Torso Scrawny"
      wearable="shape"
@@ -7183,6 +7192,7 @@
     <param
      id="507"
      group="0"
+     sex="female"
      name="Breast_Gravity"
      label="Breast Buoyancy"
      wearable="shape"
@@ -7269,6 +7279,7 @@
     <param
      id="684"
      group="0"
+     sex="female"
      name="Breast_Female_Cleavage"
      label="Breast Cleavage"
      wearable="shape"
@@ -7296,6 +7307,7 @@
     <param
      id="685"
      group="0"
+     sex="male"
      name="Chest_Male_No_Pecs"
      label="Pectorals"
      wearable="shape"
@@ -7513,6 +7525,7 @@
     <param
      id="1200"
      group="1"
+     sex="female"
      name="Breast_Physics_UpDown_Driven"
      wearable="physics"
      edit_group="driven"
@@ -7534,6 +7547,7 @@
     <param
      id="1201"
      group="1"
+     sex="female"
      name="Breast_Physics_InOut_Driven"
      wearable="physics"
      edit_group="driven"
@@ -8065,6 +8079,7 @@
     <param
      id="20879"
      group="1"
+     sex="male"
      name="Male_Package"
      value_min="-.5"
      value_max="2">
@@ -9822,6 +9837,7 @@ render_pass="bump">
 
       <param
        id="1004"
+       sex="male"
        group="1"
        wearable="hair"
        edit_group="driven"
@@ -9836,6 +9852,7 @@ render_pass="bump">
 
       <param
        id="1006"
+       sex="male"
        group="1"
        wearable="hair"
        edit_group="driven"
@@ -9850,6 +9867,7 @@ render_pass="bump">
 
       <param
        id="1008"
+       sex="male"
        group="1"
        wearable="hair"
        edit_group="driven"
@@ -9864,6 +9882,7 @@ render_pass="bump">
 
       <param
        id="1010"
+       sex="male"
        group="1"
        edit_group="driven"
        wearable="hair"
@@ -9879,6 +9898,7 @@ render_pass="bump">
       <param
        id="1012"
        group="1"
+       sex="male"
        wearable="hair"
        edit_group="driven"
        name="5 O'Clock Shadow bump"
@@ -9904,6 +9924,7 @@ render_pass="bump">
 
       <param
        id="1005"
+       sex="male"
        group="1"
        wearable="hair"
        edit_group="driven"
@@ -9918,6 +9939,7 @@ render_pass="bump">
 
       <param
        id="1007"
+       sex="male"
        group="1"
        wearable="hair"
        edit_group="driven"
@@ -9932,6 +9954,7 @@ render_pass="bump">
 
       <param
        id="1009"
+       sex="male"
        group="1"
        wearable="hair"
        edit_group="driven"
@@ -9946,6 +9969,7 @@ render_pass="bump">
 
       <param
        id="1011"
+       sex="male"
        group="1"
        wearable="hair"
        edit_group="driven"
@@ -9962,6 +9986,7 @@ render_pass="bump">
        id="751"
        group="1"
        wearable="hair"
+       sex="male"
        edit_group="hair_facial"
        name="5 O'Clock Shadow"
        label_min="Dense hair"
@@ -15072,6 +15097,7 @@ render_pass="bump">
     <param
      id="105"
      group="0"
+     sex="female"
      wearable="shape"
      edit_group="shape_torso"
      edit_group_order="6"
@@ -15236,6 +15262,7 @@ render_pass="bump">
     <param
      id="649"
      group="0"
+     sex="female"
      wearable="shape"
      edit_group="shape_torso"
      edit_group_order="1.1"
@@ -15270,6 +15297,7 @@ render_pass="bump">
     <param
      id="678"
      group="0"
+     sex="male"
      wearable="shape"
      edit_group="shape_torso"
      edit_group_order="1"
@@ -15337,14 +15365,10 @@ render_pass="bump">
      id="80"
      name="male"
      group="0"
-     edit_group="shape_body"
-     label="Gender"
-     label_min="Female"
-     label_max="Male"
+     edit_group="dummy"
      wearable="shape"
      value_min="0"
-     value_max="1"
-     camera_distance="2.2">
+     value_max="1">
       <param_driver>
         <driven
          id="32" />
@@ -15559,6 +15583,7 @@ render_pass="bump">
     <param
      id="752"
      group="0"
+     sex="male"
      wearable="hair"
      edit_group="hair_facial"
      edit_group_order="1"
@@ -15840,6 +15865,7 @@ render_pass="bump">
     <param
      id="879"
      group="0"
+     sex="male"
      name="Male_Package"
      label="Package"
      wearable="shape"
@@ -16027,6 +16053,7 @@ render_pass="bump">
 
     <param
      id="166"
+     sex="male"
      group="0"
      wearable="hair"
      edit_group="hair_facial"
@@ -16052,6 +16079,7 @@ render_pass="bump">
 
     <param
      id="167"
+     sex="male"
      group="0"
      wearable="hair"
      edit_group="hair_facial"
@@ -16077,6 +16105,7 @@ render_pass="bump">
 
     <param
      id="168"
+     sex="male"
      group="0"
      wearable="hair"
      edit_group="hair_facial"
@@ -16102,6 +16131,7 @@ render_pass="bump">
 
     <param
      id="169"
+     sex="male"
      group="0"
      wearable="hair"
      edit_group="hair_facial"
@@ -16914,6 +16944,7 @@ render_pass="bump">
    <param
      id="1100"
      group="1"
+     sex="female"
      wearable="physics"
      name="Breast_Physics_UpDown_Controller"
      label="Breast Physics UpDown Controller"
@@ -16929,6 +16960,7 @@ render_pass="bump">
    <param
      id="1101"
      group="1"
+     sex="female"
      wearable="physics"
      name="Breast_Physics_InOut_Controller"
      label="Breast Physics InOut Controller"
@@ -17008,6 +17040,7 @@ render_pass="bump">
     <param
      id="10000"
      group="0"
+     sex="female"
      name="Breast_Physics_Mass"
      label="Breast Physics Mass"
      wearable="physics"
@@ -17020,6 +17053,7 @@ render_pass="bump">
     <param
      id="10001"
      group="0"
+     sex="female"
      name="Breast_Physics_Gravity"
      label="Breast Physics Gravity"
      wearable="physics"
@@ -17033,6 +17067,7 @@ render_pass="bump">
    <param
      id="10002"
      group="0"
+     sex="female"
      name="Breast_Physics_Drag"
      label="Breast Physics Drag"
      wearable="physics"
@@ -17046,6 +17081,7 @@ render_pass="bump">
    <param
      id="10003"
      group="0"
+     sex="female"
      name="Breast_Physics_UpDown_Max_Effect"
      label="Breast Physics UpDown Max Effect"
      wearable="physics"
@@ -17058,6 +17094,7 @@ render_pass="bump">
     <param
      id="10004"
      group="0"
+     sex="female"
      name="Breast_Physics_UpDown_Spring"
      label="Breast Physics UpDown Spring"
      wearable="physics"
@@ -17070,6 +17107,7 @@ render_pass="bump">
     <param
      id="10005"
      group="0"
+     sex="female"
      name="Breast_Physics_UpDown_Gain"
      label="Breast Physics UpDown Gain"
      wearable="physics"
@@ -17082,6 +17120,7 @@ render_pass="bump">
     <param
      id="10006"
      group="0"
+     sex="female"
      name="Breast_Physics_UpDown_Damping"
      label="Breast Physics UpDown Damping"
      wearable="physics"
@@ -17095,6 +17134,7 @@ render_pass="bump">
    <param
      id="10007"
      group="0"
+     sex="female"
      name="Breast_Physics_InOut_Max_Effect"
      label="Breast Physics InOut Max Effect"
      wearable="physics"
@@ -17107,6 +17147,7 @@ render_pass="bump">
     <param
      id="10008"
      group="0"
+     sex="female"
      name="Breast_Physics_InOut_Spring"
      label="Breast Physics InOut Spring"
      wearable="physics"
@@ -17119,6 +17160,7 @@ render_pass="bump">
     <param
      id="10009"
      group="0"
+     sex="female"
      name="Breast_Physics_InOut_Gain"
      label="Breast Physics InOut Gain"
      wearable="physics"
@@ -17131,6 +17173,7 @@ render_pass="bump">
     <param
      id="10010"
      group="0"
+     sex="female"
      name="Breast_Physics_InOut_Damping"
      label="Breast Physics InOut Damping"
      wearable="physics"
@@ -17364,6 +17407,7 @@ render_pass="bump">
    <param
      id="10029"
      group="0"
+     sex="female"
      name="Breast_Physics_LeftRight_Max_Effect"
      label="Breast Physics LeftRight Max Effect"
      wearable="physics"
@@ -17376,6 +17420,7 @@ render_pass="bump">
     <param
      id="10030"
      group="0"
+     sex="female"
      name="Breast_Physics_LeftRight_Spring"
      label="Breast Physics LeftRight Spring"
      wearable="physics"
@@ -17388,6 +17433,7 @@ render_pass="bump">
     <param
      id="10031"
      group="0"
+     sex="female"
      name="Breast_Physics_LeftRight_Gain"
      label="Breast Physics LeftRight Gain"
      wearable="physics"
@@ -17400,6 +17446,7 @@ render_pass="bump">
     <param
      id="10032"
      group="0"
+     sex="female"
      name="Breast_Physics_LeftRight_Damping"
      label="Breast Physics LeftRight Damping"
      wearable="physics"
diff --git a/indra/newview/skins/default/xui/da/strings.xml b/indra/newview/skins/default/xui/da/strings.xml
index 2e351cbc65..e4f99d14e9 100644
--- a/indra/newview/skins/default/xui/da/strings.xml
+++ b/indra/newview/skins/default/xui/da/strings.xml
@@ -2688,9 +2688,6 @@ Hvis du bliver ved med at modtage denne besked, kontakt venligst [SUPPORT_SITE].
 	<string name="Full Sides">
 		Meget hår
 	</string>
-	<string name="Gender">
-		Køn
-	</string>
 	<string name="Glossy">
 		Skinnende
 	</string>
diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml
index 4a4a34911d..a9e7626dc5 100644
--- a/indra/newview/skins/default/xui/de/strings.xml
+++ b/indra/newview/skins/default/xui/de/strings.xml
@@ -1248,7 +1248,6 @@ Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_
 	<string name="Full Front">Vorne volles Haar</string>
 	<string name="Full Hair Sides">Seitlich volles Haar</string>
 	<string name="Full Sides">Volle Seiten</string>
-	<string name="Gender">Geschlecht</string>
 	<string name="Glossy">Glänzend</string>
 	<string name="Glove Fingers">Handschuhfinger</string>
 	<string name="Glove Length">Handschuhlänge</string>
diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
index b3aadb8ea1..85d73ece48 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
@@ -202,6 +202,57 @@
          top="10"
          value="Shape:"
          width="150" />
+        <radio_group
+         control_name="AvatarSex"
+         follows="top|right"
+         height="20"
+         layout="topleft"
+         left="210"
+         name="sex_radio"
+         top="5"
+         width="110">
+            <radio_item
+             follows="all"
+             height="16"
+             label=""
+             layout="topleft"
+             left="0"
+             name="sex_male"
+             tool_tip="Male"
+             value="1"
+             width="40" />
+            <radio_item
+             follows="all"
+             height="16"
+             label=""
+             layout="topleft"
+             left_pad="10"
+             name="sex_female"
+             tool_tip="Female"
+             value="0"
+             width="40"/>
+        </radio_group>
+        <!--  graphical labels for the radio buttons above -->
+        <icon
+         follows="top|right"
+         height="16"
+         image_name="icons/Male.png"
+         layout="topleft"
+         left="230"
+         name="male_icon"
+         tool_tip="Male"
+         top="7"
+         width="16" />
+        <icon
+         follows="top|right"
+         height="16"
+         image_name="icons/Female.png"
+         layout="topleft"
+         left="280"
+         name="female_icon"
+         tool_tip="Female"
+         top="7"
+         width="16" />
         <line_editor
          follows="all"
          height="23"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 87f866881d..7360c06f86 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3242,7 +3242,6 @@ Please reinstall viewer from  https://secondlife.com/support/downloads/ and cont
 <string name="Full Front">Full Front</string>
 <string name="Full Hair Sides">Full Hair Sides</string>
 <string name="Full Sides">Full Sides</string>
-<string name="Gender">Gender</string>
 <string name="Glossy">Glossy</string>
 <string name="Glove Fingers">Glove Fingers</string>
 
diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml
index fd85cdc252..cd8e7687ae 100644
--- a/indra/newview/skins/default/xui/es/strings.xml
+++ b/indra/newview/skins/default/xui/es/strings.xml
@@ -1227,7 +1227,6 @@ Si sigues recibiendo este mensaje, contacta con [SUPPORT_SITE].</string>
 	<string name="Full Front">Sin cortar</string>
 	<string name="Full Hair Sides">Pelo: volumen a los lados</string>
 	<string name="Full Sides">Volumen total</string>
-	<string name="Gender">Sexo</string>
 	<string name="Glossy">Con brillo</string>
 	<string name="Glove Fingers">Guantes: dedos</string>
 	<string name="Glove Length">Guantes: largo</string>
diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml
index 5969856086..0a3fbeb603 100644
--- a/indra/newview/skins/default/xui/fr/strings.xml
+++ b/indra/newview/skins/default/xui/fr/strings.xml
@@ -1249,7 +1249,6 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].</string>
 	<string name="Full Front">Devant touffu</string>
 	<string name="Full Hair Sides">Côtés touffus</string>
 	<string name="Full Sides">Côtés touffus</string>
-	<string name="Gender">Sexe</string>
 	<string name="Glossy">Brillant</string>
 	<string name="Glove Fingers">Gants avec doigts</string>
 	<string name="Glove Length">Longueur</string>
diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml
index e12203c6b7..178bb90ca6 100644
--- a/indra/newview/skins/default/xui/it/strings.xml
+++ b/indra/newview/skins/default/xui/it/strings.xml
@@ -1229,7 +1229,6 @@ Se il messaggio persiste, contatta [SUPPORT_SITE].</string>
 	<string name="Full Front">Anteriore gonfio</string>
 	<string name="Full Hair Sides">Lati capelli gonfi</string>
 	<string name="Full Sides">Lati gonfi</string>
-	<string name="Gender">Sesso</string>
 	<string name="Glossy">Lucido</string>
 	<string name="Glove Fingers">Dita con guanti</string>
 	<string name="Glove Length">Lunghezza guanti</string>
diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml
index 8fe69162c5..fa6c329fe7 100644
--- a/indra/newview/skins/default/xui/ja/strings.xml
+++ b/indra/newview/skins/default/xui/ja/strings.xml
@@ -5052,9 +5052,6 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
 	<string name="Full Sides">
 		生え揃ったサイド
 	</string>
-	<string name="Gender">
-		性別
-	</string>
 	<string name="Glossy">
 		あり
 	</string>
diff --git a/indra/newview/skins/default/xui/pl/strings.xml b/indra/newview/skins/default/xui/pl/strings.xml
index a2d386e8ac..26ec6cc9dc 100644
--- a/indra/newview/skins/default/xui/pl/strings.xml
+++ b/indra/newview/skins/default/xui/pl/strings.xml
@@ -3318,9 +3318,6 @@ Jeżeli nadal otrzymujesz ten komunikat, skontaktuj się z [SUPPORT_SITE].
 	<string name="Full Sides">
 		Gęste boki
 	</string>
-	<string name="Gender">
-		Płeć
-	</string>
 	<string name="Glossy">
 		Błyszcząca
 	</string>
diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml
index 5076e21198..6db5da2e89 100644
--- a/indra/newview/skins/default/xui/pt/strings.xml
+++ b/indra/newview/skins/default/xui/pt/strings.xml
@@ -1192,7 +1192,6 @@ If you continue to receive this message, contact the [SUPPORT_SITE].</string>
 	<string name="Full Front">Frente cheia</string>
 	<string name="Full Hair Sides">Cabelos laterais cheios</string>
 	<string name="Full Sides">Lados cheios</string>
-	<string name="Gender">Sexo</string>
 	<string name="Glossy">Brilhante</string>
 	<string name="Glove Fingers">Dedos da luva</string>
 	<string name="Glove Length">Comprimento das luvas</string>
diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml
index 8fc9641624..61d836a2d1 100644
--- a/indra/newview/skins/default/xui/ru/strings.xml
+++ b/indra/newview/skins/default/xui/ru/strings.xml
@@ -3479,9 +3479,6 @@ support@secondlife.com.
 	<string name="Full Sides">
 		По бокам
 	</string>
-	<string name="Gender">
-		Пол
-	</string>
 	<string name="Glossy">
 		Блестящие
 	</string>
diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml
index 687de84401..e709a4c5d6 100644
--- a/indra/newview/skins/default/xui/tr/strings.xml
+++ b/indra/newview/skins/default/xui/tr/strings.xml
@@ -3482,9 +3482,6 @@ Bu iletiyi almaya devam ederseniz, lütfen [SUPPORT_SITE] bölümüne başvurun.
 	<string name="Full Sides">
 		Saçlar Yanda
 	</string>
-	<string name="Gender">
-		Cinsiyet
-	</string>
 	<string name="Glossy">
 		Parlak
 	</string>
diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml
index cf94391aa4..bdb16c9bf1 100644
--- a/indra/newview/skins/default/xui/zh/strings.xml
+++ b/indra/newview/skins/default/xui/zh/strings.xml
@@ -3475,9 +3475,6 @@ http://secondlife.com/support 求助解決問題。
 	<string name="Full Sides">
 		兩側飽滿
 	</string>
-	<string name="Gender">
-		性别
-	</string>
 	<string name="Glossy">
 		光亮
 	</string>
-- 
cgit v1.2.3


From cc8d71c18c124138e76e85e663498d2ee9776b3c Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 2 Apr 2024 23:11:29 +0300
Subject: viewer#1114 Expose max impostors setting in basic graphics
 preferences

---
 indra/newview/llfloaterpreference.cpp              | 44 ++++++++++++++++++++++
 indra/newview/llfloaterpreference.h                |  4 ++
 .../llfloaterpreferencesgraphicsadvanced.cpp       |  5 ++-
 .../newview/llfloaterpreferencesgraphicsadvanced.h |  1 +
 .../en/floater_preferences_graphics_advanced.xml   |  2 +-
 .../default/xui/en/panel_preferences_graphics1.xml | 40 ++++++++++++++++++--
 6 files changed, 90 insertions(+), 6 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index aa723eb3a8..a5d3a34322 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -328,6 +328,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
 	mCommitCallbackRegistrar.add("Pref.AutoAdjustments",         boost::bind(&LLFloaterPreference::onClickAutoAdjustments, this));
 	mCommitCallbackRegistrar.add("Pref.HardwareDefaults",		boost::bind(&LLFloaterPreference::setHardwareDefaults, this));
 	mCommitCallbackRegistrar.add("Pref.AvatarImpostorsEnable",	boost::bind(&LLFloaterPreference::onAvatarImpostorsEnable, this));
+    mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxNonImpostors", boost::bind(&LLFloaterPreference::updateMaxNonImpostors, this));
 	mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxComplexity",	boost::bind(&LLFloaterPreference::updateMaxComplexity, this));
     mCommitCallbackRegistrar.add("Pref.RenderOptionUpdate",     boost::bind(&LLFloaterPreference::onRenderOptionEnable, this));
 	mCommitCallbackRegistrar.add("Pref.WindowedMod",			boost::bind(&LLFloaterPreference::onCommitWindowedMode, this));
@@ -359,6 +360,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
 	LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this );
 
     mComplexityChangedSignal = gSavedSettings.getControl("RenderAvatarMaxComplexity")->getCommitSignal()->connect(boost::bind(&LLFloaterPreference::updateComplexityText, this));
+    mImpostorsChangedSignal = gSavedSettings.getControl("RenderAvatarMaxNonImpostors")->getSignal()->connect(boost::bind(&LLFloaterPreference::updateIndirectMaxNonImpostors, this, _2));
 
 	mCommitCallbackRegistrar.add("Pref.ClearLog",				boost::bind(&LLConversationLog::onClearLog, &LLConversationLog::instance()));
 	mCommitCallbackRegistrar.add("Pref.DeleteTranscripts",      boost::bind(&LLFloaterPreference::onDeleteTranscripts, this));
@@ -528,6 +530,7 @@ LLFloaterPreference::~LLFloaterPreference()
 {
 	LLConversationLog::instance().removeObserver(this);
     mComplexityChangedSignal.disconnect();
+    mImpostorsChangedSignal.disconnect();
 }
 
 void LLFloaterPreference::draw()
@@ -1283,6 +1286,9 @@ void LLAvatarComplexityControls::setIndirectMaxArc()
 void LLFloaterPreference::refresh()
 {
 	LLPanel::refresh();
+    setMaxNonImpostorsText(
+        gSavedSettings.getU32("RenderAvatarMaxNonImpostors"),
+        getChild<LLTextBox>("IndirectMaxNonImpostorsText", true));
     LLAvatarComplexityControls::setText(
         gSavedSettings.getU32("RenderAvatarMaxComplexity"),
         getChild<LLTextBox>("IndirectMaxComplexityText", true));
@@ -1561,6 +1567,44 @@ void LLAvatarComplexityControls::setRenderTimeText(F32 value, LLTextBox* text_bo
     }
 }
 
+void LLFloaterPreference::updateMaxNonImpostors()
+{
+    // Called when the IndirectMaxNonImpostors control changes
+    // Responsible for fixing the slider label (IndirectMaxNonImpostorsText) and setting RenderAvatarMaxNonImpostors
+    LLSliderCtrl* ctrl = getChild<LLSliderCtrl>("IndirectMaxNonImpostors", true);
+    U32 value = ctrl->getValue().asInteger();
+
+    if (0 == value || LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER <= value)
+    {
+        value = 0;
+    }
+    gSavedSettings.setU32("RenderAvatarMaxNonImpostors", value);
+    LLVOAvatar::updateImpostorRendering(value); // make it effective immediately
+    setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText"));
+}
+
+void LLFloaterPreference::updateIndirectMaxNonImpostors(const LLSD& newvalue)
+{
+    U32 value = newvalue.asInteger();
+    if ((value != 0) && (value != gSavedSettings.getU32("IndirectMaxNonImpostors")))
+    {
+        gSavedSettings.setU32("IndirectMaxNonImpostors", value);
+    }
+    setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText"));
+}
+
+void LLFloaterPreference::setMaxNonImpostorsText(U32 value, LLTextBox* text_box)
+{
+    if (0 == value)
+    {
+        text_box->setText(LLTrans::getString("no_limit"));
+    }
+    else
+    {
+        text_box->setText(llformat("%d", value));
+    }
+}
+
 void LLFloaterPreference::updateMaxComplexity()
 {
 	// Called when the IndirectMaxComplexity control changes
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 04ac87364d..936808d58e 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -210,6 +210,9 @@ private:
 	void onDeleteTranscripts();
 	void onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response);
 	void updateDeleteTranscriptsButton();
+    void updateMaxNonImpostors();
+    void updateIndirectMaxNonImpostors(const LLSD& newvalue);
+    void setMaxNonImpostorsText(U32 value, LLTextBox* text_box);
 	void updateMaxComplexity();
     void updateComplexityText();
 	static bool loadFromFilename(const std::string& filename, std::map<std::string, std::string> &label_map);
@@ -233,6 +236,7 @@ private:
 	std::unique_ptr< ll::prefs::SearchData > mSearchData;
 	bool mSearchDataDirty;
 
+    boost::signals2::connection	mImpostorsChangedSignal;
     boost::signals2::connection	mComplexityChangedSignal;
 
 	void onUpdateFilterTerm( bool force = false );
diff --git a/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp b/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp
index a91f0ec060..d59113144e 100644
--- a/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp
+++ b/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp
@@ -52,13 +52,14 @@ LLFloaterPreferenceGraphicsAdvanced::LLFloaterPreferenceGraphicsAdvanced(const L
     mCommitCallbackRegistrar.add("Pref.Cancel", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::onBtnCancel, this, _2));
     mCommitCallbackRegistrar.add("Pref.OK",     boost::bind(&LLFloaterPreferenceGraphicsAdvanced::onBtnOK, this, _2));
 
-    gSavedSettings.getControl("RenderAvatarMaxNonImpostors")->getSignal()->connect(boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateIndirectMaxNonImpostors, this, _2));
+    mImpostorsChangedSignal = gSavedSettings.getControl("RenderAvatarMaxNonImpostors")->getSignal()->connect(boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateIndirectMaxNonImpostors, this, _2));
 }
 
 LLFloaterPreferenceGraphicsAdvanced::~LLFloaterPreferenceGraphicsAdvanced()
 {
     mComplexityChangedSignal.disconnect();
     mLODFactorChangedSignal.disconnect();
+    mImpostorsChangedSignal.disconnect();
 }
 
 BOOL LLFloaterPreferenceGraphicsAdvanced::postBuild()
@@ -221,8 +222,8 @@ void LLFloaterPreferenceGraphicsAdvanced::updateIndirectMaxNonImpostors(const LL
     if ((value != 0) && (value != gSavedSettings.getU32("IndirectMaxNonImpostors")))
     {
         gSavedSettings.setU32("IndirectMaxNonImpostors", value);
-        setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText"));
     }
+    setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText"));
 }
 
 void LLFloaterPreferenceGraphicsAdvanced::setMaxNonImpostorsText(U32 value, LLTextBox* text_box)
diff --git a/indra/newview/llfloaterpreferencesgraphicsadvanced.h b/indra/newview/llfloaterpreferencesgraphicsadvanced.h
index 2c92f3dbf1..80e35368eb 100644
--- a/indra/newview/llfloaterpreferencesgraphicsadvanced.h
+++ b/indra/newview/llfloaterpreferencesgraphicsadvanced.h
@@ -60,6 +60,7 @@ protected:
     void		onBtnOK(const LLSD& userdata);
     void		onBtnCancel(const LLSD& userdata);
 
+    boost::signals2::connection	mImpostorsChangedSignal;
     boost::signals2::connection	mComplexityChangedSignal;
     boost::signals2::connection	mLODFactorChangedSignal;
 };
diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
index bc237322af..d993b1f990 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
@@ -170,7 +170,7 @@
     height="16"
     increment="1"
     initial_value="12"
-    label="Max. # of non-impostors:"
+    label="Max. # animated avatars:"
     label_width="185"
     layout="topleft"
     left="30"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
index 8a9d3b755e..5d1ddc2e69 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -210,26 +210,60 @@
     increment="8"
     initial_value="160"
     label="Draw distance:"
-    label_width="90"
+    label_width="187"
     layout="topleft"
     left="30"
     min_val="64"
     max_val="512"
     name="DrawDistance"
     top_delta="40"
-    width="330" />
+    width="427" />
   <text
     type="string"
     length="1"
     follows="left|top"
     height="12"
     layout="topleft"
-    left_delta="330"
+    left_delta="427"
     name="DrawDistanceMeterText2"
     top_delta="0"
     width="128">
      m
   </text>
+  <slider
+    control_name="IndirectMaxNonImpostors"
+    name="IndirectMaxNonImpostors"
+    decimal_digits="0"
+    increment="1"
+    initial_value="12"
+    show_text="false"
+    min_val="1"
+    max_val="66"
+    label="Maximum number of animated avatars:"
+    follows="left|top"
+    layout="topleft"
+    height="16"
+    label_width="240"
+    left="30"
+    top_delta="40"
+    width="393">
+      <slider.commit_callback
+        function="Pref.UpdateIndirectMaxNonImpostors"
+        parameter="IndirectNonImpostorsText" />
+  </slider>
+  <text
+    type="string"
+    length="1"
+    follows="left|top"
+    height="16"
+    layout="topleft"
+    top_delta="0"
+    left_delta="397"
+    text_readonly_color="LabelDisabledColor"
+    name="IndirectMaxNonImpostorsText"
+    width="65">
+      0
+  </text>
 
   <button
   height="23"
-- 
cgit v1.2.3


From 57d423745fd1d3d0ea6a0c69b869a20c27e27fc5 Mon Sep 17 00:00:00 2001
From: Nicky Dasmijn <nicky.dasmijn@posteo.nl>
Date: Fri, 5 Apr 2024 19:25:02 +0200
Subject: Linux viewer (ReleaseOS) resurrection (#1099)

Co-authored-by: AiraYumi <aira.youme@airanyumi.net>
---
 indra/cmake/00-Common.cmake                        |   38 +-
 indra/cmake/Audio.cmake                            |    2 +-
 indra/cmake/Boost.cmake                            |    6 +-
 indra/cmake/CMakeLists.txt                         |    1 -
 indra/cmake/ConfigurePkgConfig.cmake               |   74 -
 indra/cmake/Copy3rdPartyLibs.cmake                 |   10 -
 indra/cmake/FreeType.cmake                         |   13 +-
 indra/cmake/GLIB.cmake                             |   22 +
 indra/cmake/GStreamer10Plugin.cmake                |   27 +
 indra/cmake/ICU4C.cmake                            |    2 +-
 indra/cmake/JsonCpp.cmake                          |    2 +-
 indra/cmake/LLAddBuildTest.cmake                   |    7 +
 indra/cmake/LLWindow.cmake                         |   14 +-
 indra/cmake/Meshoptimizer.cmake                    |    2 +-
 indra/cmake/UI.cmake                               |   45 +-
 indra/cmake/Variables.cmake                        |    2 -
 indra/cmake/ViewerMiscLibs.cmake                   |    9 +-
 indra/llcommon/llprocessor.cpp                     |    2 +-
 indra/llcommon/llsdutil.cpp                        |    1 +
 indra/llcommon/llsys.cpp                           |  133 +-
 indra/llcorehttp/CMakeLists.txt                    |    2 -
 indra/llimage/llimageworker.cpp                    |    2 +-
 indra/llmath/llcalcparser.h                        |    6 +-
 indra/llmessage/CMakeLists.txt                     |    3 -
 indra/llmessage/llnamevalue.cpp                    |    4 +
 indra/llprimitive/llprimtexturelist.cpp            |    9 +-
 indra/llrender/llfontfreetype.cpp                  |   36 +-
 indra/llrender/llfontfreetypesvg.cpp               |    4 +
 indra/llrender/llfontfreetypesvg.h                 |    6 +-
 indra/llrender/llgl.cpp                            |  111 +-
 indra/llrender/llglheaders.h                       |   16 +
 indra/llrender/llglslshader.cpp                    |    2 +-
 indra/llwindow/CMakeLists.txt                      |    8 +-
 indra/llwindow/llkeyboard.cpp                      |   40 +-
 indra/llwindow/llkeyboard.h                        |   36 +-
 indra/llwindow/llkeyboardheadless.cpp              |    4 -
 indra/llwindow/llkeyboardheadless.h                |    9 +-
 indra/llwindow/llkeyboardsdl.cpp                   |  837 +++--
 indra/llwindow/llkeyboardsdl.h                     |   50 +-
 indra/llwindow/llwindowsdl.cpp                     | 3866 ++++++++++----------
 indra/llwindow/llwindowsdl.h                       |  433 ++-
 indra/media_plugins/CMakeLists.txt                 |    2 +-
 indra/media_plugins/gstreamer10/CMakeLists.txt     |   46 +
 .../gstreamer10/llmediaimplgstreamer.h             |   53 +
 .../gstreamer10/llmediaimplgstreamer_syms.cpp      |  197 +
 .../gstreamer10/llmediaimplgstreamer_syms.h        |   68 +
 .../gstreamer10/llmediaimplgstreamer_syms_raw.inc  |   68 +
 .../gstreamer10/media_plugin_gstreamer10.cpp       |  982 +++++
 indra/newview/CMakeLists.txt                       |    1 -
 indra/newview/llappviewerlinux.cpp                 |  359 +-
 indra/newview/llappviewerlinux.h                   |   28 -
 indra/newview/llappviewerlinux_api.h               |  143 -
 indra/newview/llappviewerlinux_api.xml             |   14 -
 indra/newview/llappviewerlinux_api_dbus.cpp        |  126 -
 indra/newview/llappviewerlinux_api_dbus.h          |   44 -
 .../newview/llappviewerlinux_api_dbus_syms_raw.inc |    9 -
 indra/newview/llchathistory.cpp                    |    2 +-
 indra/newview/llconversationloglist.cpp            |    7 +-
 indra/newview/lldirpicker.cpp                      |   36 +
 indra/newview/lldirpicker.h                        |    2 +
 indra/newview/llface.cpp                           |    1 -
 indra/newview/llfasttimerview.cpp                  |   14 +-
 indra/newview/llfilepicker.h                       |   14 +
 indra/newview/llfloaterregioninfo.cpp              |    9 +-
 indra/newview/llhttpretrypolicy.cpp                |    5 +-
 indra/newview/llinventoryfilter.cpp                |   10 +-
 indra/newview/llinventorygallerymenu.cpp           |    2 +-
 indra/newview/llmanip.cpp                          |    3 -
 indra/newview/llmediadataclient.cpp                |    4 +-
 indra/newview/llpanelface.cpp                      |    3 +-
 indra/newview/llpanelface.h                        |    5 +-
 indra/newview/lltoastalertpanel.h                  |   10 +-
 indra/newview/llviewerstats.cpp                    |    7 +
 indra/newview/llviewerstatsrecorder.cpp            |   22 +-
 indra/newview/llvoicevivox.cpp                     |    2 +-
 indra/newview/llvovolume.cpp                       |    3 +-
 indra/newview/llxmlrpctransaction.cpp              |    2 +-
 indra/newview/viewer_manifest.py                   |  206 +-
 78 files changed, 4990 insertions(+), 3415 deletions(-)
 delete mode 100644 indra/cmake/ConfigurePkgConfig.cmake
 create mode 100644 indra/cmake/GLIB.cmake
 create mode 100644 indra/cmake/GStreamer10Plugin.cmake
 create mode 100644 indra/media_plugins/gstreamer10/CMakeLists.txt
 create mode 100644 indra/media_plugins/gstreamer10/llmediaimplgstreamer.h
 create mode 100644 indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms.cpp
 create mode 100644 indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms.h
 create mode 100644 indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms_raw.inc
 create mode 100644 indra/media_plugins/gstreamer10/media_plugin_gstreamer10.cpp
 delete mode 100644 indra/newview/llappviewerlinux_api.h
 delete mode 100644 indra/newview/llappviewerlinux_api.xml
 delete mode 100644 indra/newview/llappviewerlinux_api_dbus.cpp
 delete mode 100644 indra/newview/llappviewerlinux_api_dbus.h
 delete mode 100644 indra/newview/llappviewerlinux_api_dbus_syms_raw.inc

(limited to 'indra')

diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 24534c98d9..486071a2df 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -87,7 +87,7 @@ if (WINDOWS)
   if( ADDRESS_SIZE EQUAL 32 )
     add_compile_options( /arch:SSE2 )
   endif()
-     
+
   # Are we using the crummy Visual Studio KDU build workaround?
   if (NOT VS_DISABLE_FATAL_WARNINGS)
     add_compile_options(/WX)
@@ -107,7 +107,15 @@ endif (WINDOWS)
 
 
 if (LINUX)
-  set(CMAKE_SKIP_RPATH TRUE)
+  set( CMAKE_BUILD_WITH_INSTALL_RPATH TRUE )
+  set( CMAKE_INSTALL_RPATH $ORIGIN $ORIGIN/../lib )
+  set(CMAKE_EXE_LINKER_FLAGS "-Wl,--exclude-libs,ALL")
+
+  find_program(CCACHE_EXE ccache)
+  if(CCACHE_EXE AND NOT DISABLE_CCACHE)
+    set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_EXE} )
+    set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_EXE} )
+  endif()
 
    # EXTERNAL_TOS
    # force this platform to accept TOS via external browser
@@ -134,21 +142,28 @@ if (LINUX)
           -pthread
           -Wno-parentheses
           -Wno-deprecated
+          -Wno-c++20-compat
+          -Wno-pessimizing-move
+          -Wno-stringop-overflow
+          -Wno-stringop-truncation
           -fvisibility=hidden
   )
-
-  if (ADDRESS_SIZE EQUAL 32)
-    add_compile_options(-march=pentium4)
-  endif (ADDRESS_SIZE EQUAL 32)
+  add_link_options(
+    -Wl,--no-keep-memory
+    -Wl,--build-id
+  )
 
   # this stops us requiring a really recent glibc at runtime
   add_compile_options(-fno-stack-protector)
   # linking can be very memory-hungry, especially the final viewer link
   set(CMAKE_CXX_LINK_FLAGS "-Wl,--no-keep-memory")
-
   set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG}")
-endif (LINUX)
 
+  # ND: clang is a bit more picky than GCC, the latter seems to auto include -lstdc++ and -lm. The former not so and thus fails to link
+  if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+    set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -lstdc++ -lm")
+  endif()
+endif (LINUX)
 
 if (DARWIN)
   # Warnings should be fatal -- thanks, Nicky Perian, for spotting reversed default
@@ -182,9 +197,10 @@ if (LINUX OR DARWIN)
 
   list(APPEND GCC_WARNINGS -Wno-reorder -Wno-non-virtual-dtor )
 
+  if(LINUX)
+    list(APPEND GCC_WARNINGS -Wno-maybe-uninitialized -Wno-misleading-indentation -Wno-stringop-truncation -Wno-unused-value )
+  endif()
+
   add_compile_options(${GCC_WARNINGS})
   add_compile_options(-m${ADDRESS_SIZE})
 endif (LINUX OR DARWIN)
-
-
-
diff --git a/indra/cmake/Audio.cmake b/indra/cmake/Audio.cmake
index 38547bb017..5efaff07c7 100644
--- a/indra/cmake/Audio.cmake
+++ b/indra/cmake/Audio.cmake
@@ -11,6 +11,6 @@ target_include_directories( ll::vorbis SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/inc
 if (WINDOWS)
   target_link_libraries(ll::vorbis INTERFACE ogg_static vorbis_static vorbisenc_static vorbisfile_static )
 else (WINDOWS)
-  target_link_libraries(ll::vorbis INTERFACE ogg vorbis vorbisenc vorbisfile )
+  target_link_libraries(ll::vorbis INTERFACE vorbisfile vorbis ogg vorbisenc )
 endif (WINDOWS)
 
diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake
index 601a23a86d..293d8931cb 100644
--- a/indra/cmake/Boost.cmake
+++ b/indra/cmake/Boost.cmake
@@ -27,14 +27,14 @@ if (WINDOWS)
           libboost_thread-mt${addrsfx})
 elseif (LINUX)
   target_link_libraries( ll::boost INTERFACE
-          boost_context-mt${addrsfx}
           boost_fiber-mt${addrsfx}
+          boost_context-mt${addrsfx}
           boost_filesystem-mt${addrsfx}
           boost_program_options-mt${addrsfx}
           boost_regex-mt${addrsfx}
-          boost_signals-mt${addrsfx}
+          boost_thread-mt${addrsfx}
           boost_system-mt${addrsfx}
-          boost_thread-mt${addrsfx})
+  )
 elseif (DARWIN)
   target_link_libraries( ll::boost INTERFACE
           boost_context-mt${addrsfx}
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 05c51c018d..3a7fe7302e 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -15,7 +15,6 @@ set(cmake_SOURCE_FILES
         CEFPlugin.cmake
         CEFPlugin.cmake
         CMakeCopyIfDifferent.cmake
-        ConfigurePkgConfig.cmake
         CURL.cmake
         Copy3rdPartyLibs.cmake
         DBusGlib.cmake
diff --git a/indra/cmake/ConfigurePkgConfig.cmake b/indra/cmake/ConfigurePkgConfig.cmake
deleted file mode 100644
index 55d865392e..0000000000
--- a/indra/cmake/ConfigurePkgConfig.cmake
+++ /dev/null
@@ -1,74 +0,0 @@
-# -*- cmake -*-
-
-SET(DEBUG_PKG_CONFIG "YES")
-
-# Don't change this if manually set by user.
-IF("$ENV{PKG_CONFIG_LIBDIR}" STREQUAL "")
-
-  # Guess at architecture-specific system library paths.
-  if (ADDRESS_SIZE EQUAL 32)
-    SET(PKG_CONFIG_NO_MULTI_GUESS /usr/lib32 /usr/lib)
-    SET(PKG_CONFIG_NO_MULTI_LOCAL_GUESS /usr/local/lib32 /usr/local/lib)
-    SET(PKG_CONFIG_MULTI_GUESS /usr/lib/i386-linux-gnu)
-    SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usr/local/lib/i386-linux-gnu)
-  else (ADDRESS_SIZE EQUAL 32)
-    SET(PKG_CONFIG_NO_MULTI_GUESS /usr/lib64 /usr/lib)
-    SET(PKG_CONFIG_NO_MULTI_LOCAL_GUESS /usr/local/lib64 /usr/local/lib)
-    SET(PKG_CONFIG_MULTI_GUESS /usr/local/lib/x86_64-linux-gnu)
-    SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usr/local/lib/x86_64-linux-gnu)
-  endif (ADDRESS_SIZE EQUAL 32)
-  
-  # Use DPKG architecture, if available.
-  IF (${DPKG_ARCH})
-    SET(PKG_CONFIG_MULTI_GUESS /usr/lib/${DPKG_ARCH})
-    SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usrlocal/lib/${DPKG_ARCH})
-  ENDIF (${DPKG_ARCH})
-  
-  # Explicitly include anything listed in PKG_CONFIG_PATH
-  string(REPLACE ":" ";" PKG_CONFIG_PATH_LIST "$ENV{PKG_CONFIG_PATH}")
-  FOREACH(PKG_CONFIG_DIR ${PKG_CONFIG_PATH_LIST})
-    SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_DIR}/pkgconfig")
-  ENDFOREACH(PKG_CONFIG_DIR)
-
-  # Look for valid pkgconfig directories.
-  FIND_PATH(PKG_CONFIG_ENV pkgconfig ENV LD_LIBRARY_PATH)
-  FIND_PATH(PKG_CONFIG_MULTI pkgconfig HINT ${PKG_CONFIG_MULTI_GUESS})
-  FIND_PATH(PKG_CONFIG_MULTI_LOCAL pkgconfig HINT ${PKG_CONFIG_MULTI_LOCAL_GUESS})
-  FIND_PATH(PKG_CONFIG_NO_MULTI pkgconfig HINT ${PKG_CONFIG_NO_MULTI_GUESS})
-  FIND_PATH(PKG_CONFIG_NO_MULTI_LOCAL pkgconfig HINT ${PKG_CONFIG_NO_MULTI_LOCAL_GUESS})
-
-  # Add anything we found to our list.
-  IF(NOT PKG_CONFIG_ENV STREQUAL PKG_CONFIG_ENV-NOTFOUND) 
-    SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_ENV}/pkgconfig")
-  ENDIF(NOT PKG_CONFIG_ENV STREQUAL PKG_CONFIG_ENV-NOTFOUND) 
-
-  IF(NOT PKG_CONFIG_MULTI STREQUAL PKG_CONFIG_MULTI-NOTFOUND) 
-    SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_MULTI}/pkgconfig")
-  ENDIF(NOT PKG_CONFIG_MULTI STREQUAL PKG_CONFIG_MULTI-NOTFOUND) 
-
-  IF(NOT PKG_CONFIG_MULTI_LOCAL STREQUAL PKG_CONFIG_MULTI_LOCAL-NOTFOUND) 
-    SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_MULTI_LOCAL}/pkgconfig")
-  ENDIF(NOT PKG_CONFIG_MULTI_LOCAL STREQUAL PKG_CONFIG_MULTI_LOCAL-NOTFOUND) 
-
-  IF(NOT PKG_CONFIG_NO_MULTI STREQUAL PKG_CONFIG_NO_MULTI-NOTFOUND) 
-    SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_NO_MULTI}/pkgconfig")
-  ENDIF(NOT PKG_CONFIG_NO_MULTI STREQUAL PKG_CONFIG_NO_MULTI-NOTFOUND) 
-
-  IF(NOT PKG_CONFIG_NO_MULTI_LOCAL STREQUAL PKG_CONFIG_NO_MULTI_LOCAL-NOTFOUND) 
-    SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_NO_MULTI_LOCAL}/pkgconfig")
-  ENDIF(NOT PKG_CONFIG_NO_MULTI_LOCAL STREQUAL PKG_CONFIG_NO_MULTI_LOCAL-NOTFOUND) 
-
-  # Also add some non-architecture specific package locations.
-  SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:/usr/share/pkgconfig:/usr/local/share/pkgconfig")
-
-  # Remove first unwanted ':'
-  string(SUBSTRING ${VALID_PKG_LIBDIRS} 1 -1 VALID_PKG_LIBDIRS)
-
-  # Set PKG_CONFIG_LIBDIR environment.
-  SET(ENV{PKG_CONFIG_LIBDIR} ${VALID_PKG_LIBDIRS})
-ENDIF("$ENV{PKG_CONFIG_LIBDIR}" STREQUAL "")
-
-IF(DEBUG_PKG_CONFIG)
-  MESSAGE(STATUS "Using PKG_CONFIG_LIBDIR=$ENV{PKG_CONFIG_LIBDIR}")
-ENDIF(DEBUG_PKG_CONFIG)
-
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index 48930c1c19..9f577bc9bc 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -224,17 +224,7 @@ elseif(LINUX)
          list( APPEND release_files
                  libapr-1.so.0
                  libaprutil-1.so.0
-                 libatk-1.0.so
-                 #libfreetype.so.6.6.2
-                 #libfreetype.so.6
                  libhunspell-1.3.so.0.0.0
-                 #libopenjp2.so
-                 #libuuid.so.16
-                 #libuuid.so.16.0.22
-                 #libfontconfig.so.1.8.0
-                 #libfontconfig.so.1
-                 libgmodule-2.0.so
-                 libgobject-2.0.so
                  )
      endif()
 
diff --git a/indra/cmake/FreeType.cmake b/indra/cmake/FreeType.cmake
index 77140af641..e7e28a44d0 100644
--- a/indra/cmake/FreeType.cmake
+++ b/indra/cmake/FreeType.cmake
@@ -4,8 +4,11 @@ include(Prebuilt)
 include_guard()
 add_library( ll::freetype INTERFACE IMPORTED )
 
-use_system_binary(freetype)
-use_prebuilt_binary(freetype)
-target_include_directories( ll::freetype SYSTEM INTERFACE  ${LIBS_PREBUILT_DIR}/include/freetype2/)
-target_link_libraries( ll::freetype INTERFACE freetype )
-
+    use_system_binary(freetype)
+    use_prebuilt_binary(freetype)
+    target_include_directories( ll::freetype SYSTEM INTERFACE  ${LIBS_PREBUILT_DIR}/include/freetype2/)
+if( LINUX )
+    target_link_libraries( ll::freetype INTERFACE ${LIBS_PREBUILT_DIR}/lib/release/libfreetype.a ${LIBS_PREBUILT_DIR}/lib/release/libpng16.a)
+else()
+    target_link_libraries( ll::freetype INTERFACE freetype )
+endif()
diff --git a/indra/cmake/GLIB.cmake b/indra/cmake/GLIB.cmake
new file mode 100644
index 0000000000..f52cbb7f87
--- /dev/null
+++ b/indra/cmake/GLIB.cmake
@@ -0,0 +1,22 @@
+include_guard()
+
+include(Prebuilt)
+
+add_library( ll::glib INTERFACE IMPORTED )
+add_library( ll::glib_headers INTERFACE IMPORTED )
+add_library( ll::gio INTERFACE IMPORTED )
+
+if( LINUX )
+  find_package(PkgConfig REQUIRED)
+  pkg_search_module(GLIB REQUIRED glib-2.0)
+  pkg_search_module(GIO REQUIRED gio-2.0)
+
+  target_include_directories( ll::glib SYSTEM INTERFACE ${GLIB_INCLUDE_DIRS}  )
+  target_link_libraries( ll::glib INTERFACE ${GLIB_LDFLAGS} )
+  target_compile_definitions( ll::glib INTERFACE -DLL_GLIB=1)
+
+  target_include_directories( ll::glib_headers SYSTEM INTERFACE ${GLIB_INCLUDE_DIRS}  )
+  target_compile_definitions( ll::glib_headers INTERFACE -DLL_GLIB=1)
+
+  target_link_libraries( ll::gio INTERFACE ${GIO_LDFLAGS} )
+endif()
diff --git a/indra/cmake/GStreamer10Plugin.cmake b/indra/cmake/GStreamer10Plugin.cmake
new file mode 100644
index 0000000000..da2e33d04d
--- /dev/null
+++ b/indra/cmake/GStreamer10Plugin.cmake
@@ -0,0 +1,27 @@
+# -*- cmake -*-
+
+include_guard()
+
+include(Prebuilt)
+include(GLIB)
+
+add_library( ll::gstreamer10 INTERFACE IMPORTED )
+
+if (LINUX)
+  include(FindPkgConfig)
+
+  pkg_check_modules(GSTREAMER10 REQUIRED gstreamer-1.0)
+  pkg_check_modules(GSTREAMER10_PLUGINS_BASE REQUIRED gstreamer-plugins-base-1.0)
+
+  target_include_directories( ll::gstreamer10 SYSTEM INTERFACE ${GSTREAMER10_INCLUDE_DIRS})
+  target_link_libraries( ll::gstreamer10 INTERFACE  ll::glib_headers)
+
+endif ()
+
+if (GSTREAMER10_FOUND AND GSTREAMER10_PLUGINS_BASE_FOUND)
+  set(GSTREAMER10 ON CACHE BOOL "Build with GStreamer-1.0 streaming media support.")
+endif (GSTREAMER10_FOUND AND GSTREAMER10_PLUGINS_BASE_FOUND)
+
+if (GSTREAMER10)
+  add_definitions(-DLL_GSTREAMER10_ENABLED=1)
+endif (GSTREAMER10)
diff --git a/indra/cmake/ICU4C.cmake b/indra/cmake/ICU4C.cmake
index a9714696b4..8382ceef1e 100644
--- a/indra/cmake/ICU4C.cmake
+++ b/indra/cmake/ICU4C.cmake
@@ -13,7 +13,7 @@ if (WINDOWS)
 elseif(DARWIN)
   target_link_libraries( ll::icu4c INTERFACE  icuuc)
 elseif(LINUX)
-  target_link_libraries( ll::icu4c INTERFACE  icuuc)
+  target_link_libraries( ll::icu4c INTERFACE  ${LIBS_PREBUILT_DIR}/lib/libicuuc.a)
 else()
   message(FATAL_ERROR "Invalid platform")
 endif()
diff --git a/indra/cmake/JsonCpp.cmake b/indra/cmake/JsonCpp.cmake
index 17f8e47a97..a9b992ab20 100644
--- a/indra/cmake/JsonCpp.cmake
+++ b/indra/cmake/JsonCpp.cmake
@@ -12,6 +12,6 @@ if (WINDOWS)
 elseif (DARWIN)
   target_link_libraries( ll::jsoncpp INTERFACE libjson_darwin_libmt.a )
 elseif (LINUX)
-  target_link_libraries( ll::jsoncpp INTERFACE libjson_linux-gcc-4.1.3_libmt.a )
+  target_link_libraries( ll::jsoncpp INTERFACE libjson_linux-gcc-11_libmt.a )
 endif (WINDOWS)
 target_include_directories( ll::jsoncpp SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include)
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 2172b56da2..6e948c2186 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -1,4 +1,11 @@
 # -*- cmake -*-
+
+include_guard()
+
+if( NOT LL_TESTS )
+  return()
+endif()
+
 include(00-Common)
 include(LLTestCommand)
 include(GoogleMock)
diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake
index b36e970560..23f4115aeb 100644
--- a/indra/cmake/LLWindow.cmake
+++ b/indra/cmake/LLWindow.cmake
@@ -10,13 +10,11 @@ add_library( ll::SDL INTERFACE IMPORTED )
 
 if (LINUX)
   #Must come first as use_system_binary can exit this file early
-  target_compile_definitions( ll::SDL INTERFACE LL_SDL=1)
-
-  use_system_binary(SDL)
-  use_prebuilt_binary(SDL)
-  
-  target_include_directories( ll::SDL SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include)
-  target_link_libraries( ll::SDL INTERFACE SDL directfb fusion direct X11)
-endif (LINUX)
+  target_compile_definitions( ll::SDL INTERFACE LL_SDL_VERSION=2 LL_SDL)
 
+  #find_package(SDL2 REQUIRED)
+  #target_link_libraries( ll::SDL INTERFACE SDL2::SDL2 SDL2::SDL2main X11)
 
+  use_prebuilt_binary(SDL2)
+  target_link_libraries( ll::SDL INTERFACE SDL2 X11)
+endif (LINUX)
diff --git a/indra/cmake/Meshoptimizer.cmake b/indra/cmake/Meshoptimizer.cmake
index fd144d2b97..6983a5895a 100644
--- a/indra/cmake/Meshoptimizer.cmake
+++ b/indra/cmake/Meshoptimizer.cmake
@@ -12,7 +12,7 @@ use_prebuilt_binary(meshoptimizer)
 if (WINDOWS)
   target_link_libraries( ll::meshoptimizer INTERFACE meshoptimizer.lib)
 elseif (LINUX)
-  target_link_libraries( ll::meshoptimizer INTERFACE meshoptimizer.o)
+  target_link_libraries( ll::meshoptimizer INTERFACE libmeshoptimizer.a)
 elseif (DARWIN)
   target_link_libraries( ll::meshoptimizer INTERFACE libmeshoptimizer.a)
 endif (WINDOWS)
diff --git a/indra/cmake/UI.cmake b/indra/cmake/UI.cmake
index 8b70192efc..0eb9af6dcf 100644
--- a/indra/cmake/UI.cmake
+++ b/indra/cmake/UI.cmake
@@ -1,35 +1,43 @@
 # -*- cmake -*-
 include(Prebuilt)
 include(FreeType)
+include(GLIB)
 
 add_library( ll::uilibraries INTERFACE IMPORTED )
 
 if (LINUX)
-  target_compile_definitions(ll::uilibraries INTERFACE LL_GTK=1 LL_X11=1 )
+  target_compile_definitions(ll::uilibraries INTERFACE LL_X11=1 )
 
   if( USE_CONAN )
-    target_link_libraries( ll::uilibraries INTERFACE CONAN_PKG::gtk )
     return()
   endif()
-  use_prebuilt_binary(gtk-atk-pango-glib)
-  
+
+  find_package(FLTK REQUIRED )
+  find_library(ND_FLTK_STATIC_LIBRARY libfltk.a PATH_SUFFIXES fltk )
+
+  if( NOT ND_FLTK_STATIC_LIBRARY )
+    message(FATAL_ERROR "libfltk.a not found")
+  else()
+    message("libfltk.a found ${ND_FLTK_STATIC_LIBRARY}")
+  endif()
+
+  target_include_directories( ll::uilibraries SYSTEM INTERFACE   ${FLTK_INCLUDE_DIR})
+  target_compile_definitions( ll::uilibraries INTERFACE LL_FLTK=1 )
   target_link_libraries( ll::uilibraries INTERFACE
-          atk-1.0
-          gdk-x11-2.0
-          gdk_pixbuf-2.0
-          Xinerama
-          glib-2.0
-          gmodule-2.0
-          gobject-2.0
-          gthread-2.0
-          gtk-x11-2.0
-          pango-1.0
-          pangoft2-1.0
-          pangox-1.0
-          pangoxft-1.0
+          ${ND_FLTK_STATIC_LIBRARY}
+          Xrender
+          Xcursor
+          Xfixes
+          Xext
+          Xft
           Xinerama
+          ll::fontconfig
           ll::freetype
-          )
+          ll::SDL
+          ll::glib
+          ll::gio
+  )
+
 endif (LINUX)
 if( WINDOWS )
   target_link_libraries( ll::uilibraries INTERFACE
@@ -51,4 +59,3 @@ endif()
 target_include_directories( ll::uilibraries SYSTEM INTERFACE
         ${LIBS_PREBUILT_DIR}/include
         )
-
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index af1f16d04d..c037d657eb 100644
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -127,8 +127,6 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
     set(CMAKE_SYSTEM_LIBRARY_PATH /usr/lib/${DPKG_ARCH} /usr/local/lib/${DPKG_ARCH} ${CMAKE_SYSTEM_LIBRARY_PATH})
   endif (DPKG_RESULT EQUAL 0)
 
-  include(ConfigurePkgConfig)
-
   if (INSTALL_PROPRIETARY)
     # Only turn on headless if we can find osmesa libraries.
     include(FindPkgConfig)
diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake
index 3e5a37b277..2cb11994fc 100644
--- a/indra/cmake/ViewerMiscLibs.cmake
+++ b/indra/cmake/ViewerMiscLibs.cmake
@@ -2,15 +2,10 @@
 include(Prebuilt)
 
 if (LINUX)
-  #use_prebuilt_binary(libuuid)
   add_library( ll::fontconfig INTERFACE IMPORTED )
 
-  if( NOT USE_CONAN )
-    find_package(Fontconfig REQUIRED)
-    target_link_libraries( ll::fontconfig INTERFACE Fontconfig::Fontconfig )
-  else()
-    target_link_libraries( ll::fontconfig INTERFACE CONAN_PKG::fontconfig )
-  endif()
+  find_package(Fontconfig REQUIRED)
+  target_link_libraries( ll::fontconfig INTERFACE  Fontconfig::Fontconfig )
 endif (LINUX)
 
 if( NOT USE_CONAN )
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index 7bca86119c..ce3b1160c0 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -867,7 +867,7 @@ private:
 		LLPI_SET_INFO_INT(eModel, "model");
 
 		
-		S32 family = 0;							 
+		S32 family{};
 		if (!cpuinfo["cpu family"].empty() 
 			&& LLStringUtil::convertToS32(cpuinfo["cpu family"], family))	
 		{ 
diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index c3e7c544ec..7438524272 100644
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -36,6 +36,7 @@
 #	include <winsock2.h>	// for htonl
 #elif LL_LINUX
 #	include <netinet/in.h>
+#pragma GCC diagnostic ignored "-Wstringop-truncation" // It's actually okay what happens here
 #elif LL_DARWIN
 #	include <arpa/inet.h>
 #endif
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 938685bae6..988c74229c 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -1,25 +1,25 @@
-/** 
+/**
  * @file llsys.cpp
  * @brief Implementation of the basic system query functions.
  *
  * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -97,7 +97,7 @@ static const F32 MEM_INFO_THROTTLE = 20;
 static const F32 MEM_INFO_WINDOW = 10*60;
 
 LLOSInfo::LLOSInfo() :
-	mMajorVer(0), mMinorVer(0), mBuild(0), mOSVersionString("")	 
+	mMajorVer(0), mMinorVer(0), mBuild(0), mOSVersionString("")
 {
 
 #if LL_WINDOWS
@@ -187,7 +187,7 @@ LLOSInfo::LLOSInfo() :
 	if (NULL != pGNSI) //check if it has failed
 		pGNSI(&si); //success
 	else
-		GetSystemInfo(&si); //if it fails get regular system info 
+		GetSystemInfo(&si); //if it fails get regular system info
 	//(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load)
 
 	// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
@@ -267,12 +267,12 @@ LLOSInfo::LLOSInfo() :
 	LLStringUtil::trim(mOSString);
 
 #elif LL_DARWIN
-	
+
 	// Initialize mOSStringSimple to something like:
 	// "Mac OS X 10.6.7"
 	{
 		const char * DARWIN_PRODUCT_NAME = "Mac OS X";
-		
+
 		int64_t major_version, minor_version, bugfix_version = 0;
 
 		if (LLGetDarwinOSInfo(major_version, minor_version, bugfix_version))
@@ -283,7 +283,7 @@ LLOSInfo::LLOSInfo() :
 
 			std::stringstream os_version_string;
 			os_version_string << DARWIN_PRODUCT_NAME << " " << mMajorVer << "." << mMinorVer << "." << mBuild;
-			
+
 			// Put it in the OS string we are compiling
 			mOSStringSimple.append(os_version_string.str());
 		}
@@ -292,12 +292,12 @@ LLOSInfo::LLOSInfo() :
 			mOSStringSimple.append("Unable to collect OS info");
 		}
 	}
-	
+
 	// Initialize mOSString to something like:
 	// "Mac OS X 10.6.7 Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 i386"
 	struct utsname un;
 	if(uname(&un) != -1)
-	{		
+	{
 		mOSString = mOSStringSimple;
 		mOSString.append(" ");
 		mOSString.append(un.sysname);
@@ -312,9 +312,9 @@ LLOSInfo::LLOSInfo() :
 	{
 		mOSString = mOSStringSimple;
 	}
-	
+
 #elif LL_LINUX
-	
+
 	struct utsname un;
 	if(uname(&un) != -1)
 	{
@@ -354,7 +354,7 @@ LLOSInfo::LLOSInfo() :
 	if ( ll_regex_match(glibc_version, matched, os_version_parse) )
 	{
 		LL_INFOS("AppInit") << "Using glibc version '" << glibc_version << "' as OS version" << LL_ENDL;
-	
+
 		std::string version_value;
 
 		if ( matched[1].matched ) // Major version
@@ -368,7 +368,7 @@ LLOSInfo::LLOSInfo() :
 		else
 		{
 			LL_ERRS("AppInit")
-				<< "OS version regex '" << OS_VERSION_MATCH_EXPRESSION 
+				<< "OS version regex '" << OS_VERSION_MATCH_EXPRESSION
 				<< "' returned true, but major version [1] did not match"
 				<< LL_ENDL;
 		}
@@ -384,7 +384,7 @@ LLOSInfo::LLOSInfo() :
 		else
 		{
 			LL_ERRS("AppInit")
-				<< "OS version regex '" << OS_VERSION_MATCH_EXPRESSION 
+				<< "OS version regex '" << OS_VERSION_MATCH_EXPRESSION
 				<< "' returned true, but minor version [1] did not match"
 				<< LL_ENDL;
 		}
@@ -410,7 +410,7 @@ LLOSInfo::LLOSInfo() :
 	}
 
 #else
-	
+
 	struct utsname un;
 	if(uname(&un) != -1)
 	{
@@ -510,57 +510,46 @@ const S32 LLOSInfo::getOSBitness() const
 	return mOSBitness;
 }
 
-//static
-U32 LLOSInfo::getProcessVirtualSizeKB()
-{
-	U32 virtual_size = 0;
+namespace {
+
+    U32 readFromProcStat( std::string entryName )
+    {
+        U32 val{};
 #if LL_LINUX
-#   define STATUS_SIZE 2048	
-	LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb");
-	if (status_filep)
-	{
-		S32 numRead = 0;		
-		char buff[STATUS_SIZE];		/* Flawfinder: ignore */
+        constexpr U32 STATUS_SIZE  = 2048;
 
-		size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep);
-		buff[nbytes] = '\0';
+        LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb");
+        if (status_filep)
+        {
+            char buff[STATUS_SIZE];		/* Flawfinder: ignore */
 
-		// All these guys return numbers in KB
-		char *memp = strstr(buff, "VmSize:");
-		if (memp)
-		{
-			numRead += sscanf(memp, "%*s %u", &virtual_size);
-		}
-		fclose(status_filep);
-	}
+            size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep);
+            buff[nbytes] = '\0';
+
+            // All these guys return numbers in KB
+            char *memp = strstr(buff, entryName.c_str());
+            if (memp)
+            {
+                (void) sscanf(memp, "%*s %u", &val);
+            }
+            fclose(status_filep);
+        }
 #endif
-	return virtual_size;
+        return val;
+    }
+
 }
 
 //static
-U32 LLOSInfo::getProcessResidentSizeKB()
+U32 LLOSInfo::getProcessVirtualSizeKB()
 {
-	U32 resident_size = 0;
-#if LL_LINUX
-	LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb");
-	if (status_filep != NULL)
-	{
-		S32 numRead = 0;
-		char buff[STATUS_SIZE];		/* Flawfinder: ignore */
-
-		size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep);
-		buff[nbytes] = '\0';
+    return readFromProcStat( "VmSize:" );
+}
 
-		// All these guys return numbers in KB
-		char *memp = strstr(buff, "VmRSS:");
-		if (memp)
-		{
-			numRead += sscanf(memp, "%*s %u", &resident_size);
-		}
-		fclose(status_filep);
-	}
-#endif
-	return resident_size;
+//static
+U32 LLOSInfo::getProcessResidentSizeKB()
+{
+    return readFromProcStat( "VmRSS:" );
 }
 
 //static
@@ -578,7 +567,7 @@ bool LLOSInfo::is64Bit()
 #endif
 #else // ! LL_WINDOWS
     // we only build a 64-bit mac viewer and currently we don't build for linux at all
-    return true; 
+    return true;
 #endif
 }
 
@@ -1003,11 +992,11 @@ LLSD LLMemoryInfo::loadStatsMap()
 #elif LL_DARWIN
 
 	const vm_size_t pagekb(vm_page_size / 1024);
-	
+
 	//
 	// Collect the vm_stat's
 	//
-	
+
 	{
 		vm_statistics64_data_t vmstat;
 		mach_msg_type_number_t vmstatCount = HOST_VM_INFO64_COUNT;
@@ -1027,16 +1016,16 @@ LLSD LLMemoryInfo::loadStatsMap()
 			stats.add("Page reactivations",		vmstat.reactivations);
 			stats.add("Page-ins",				vmstat.pageins);
 			stats.add("Page-outs",				vmstat.pageouts);
-			
+
 			stats.add("Faults",					vmstat.faults);
 			stats.add("Faults copy-on-write",	vmstat.cow_faults);
-			
+
 			stats.add("Cache lookups",			vmstat.lookups);
 			stats.add("Cache hits",				vmstat.hits);
-			
+
 			stats.add("Page purgeable count",	vmstat.purgeable_count);
 			stats.add("Page purges",			vmstat.purges);
-			
+
 			stats.add("Page speculative reads",	vmstat.speculative_count);
 		}
 	}
@@ -1048,7 +1037,7 @@ LLSD LLMemoryInfo::loadStatsMap()
 		{
 		task_events_info_data_t taskinfo;
 		unsigned taskinfoSize = sizeof(taskinfo);
-		
+
 		if (task_info(mach_task_self(), TASK_EVENTS_INFO, (task_info_t) &taskinfo, &taskinfoSize) != KERN_SUCCESS)
 					{
 			LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL;
@@ -1063,8 +1052,8 @@ LLSD LLMemoryInfo::loadStatsMap()
 			stats.add("Task unix system call count",	taskinfo.syscalls_unix);
 			stats.add("Task context switch count",		taskinfo.csw);
 			}
-	}	
-	
+	}
+
 	//
 	// Collect the basic task info
 	//
@@ -1350,8 +1339,8 @@ BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile)
 			goto err;
 		}
 	} while(gzeof(src) == 0);
-	fclose(dst); 
-	dst = NULL;	
+	fclose(dst);
+	dst = NULL;
 	if (LLFile::rename(tmpfile, dstfile) == -1) goto err;		/* Flawfinder: ignore */
 	retval = TRUE;
 err:
diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt
index 87796abd3c..8b0f8c2e4c 100644
--- a/indra/llcorehttp/CMakeLists.txt
+++ b/indra/llcorehttp/CMakeLists.txt
@@ -3,7 +3,6 @@
 project(llcorehttp)
 
 include(00-Common)
-include(GoogleMock)
 include(CURL)
 include(OpenSSL)
 include(NGHTTP2)
@@ -11,7 +10,6 @@ include(ZLIBNG)
 include(LLCoreHttp)
 include(LLAddBuildTest)
 include(LLCommon)
-include(Tut)
 include(bugsplat)
 
 set(llcorehttp_SOURCE_FILES
diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp
index c1ee052997..369d55defe 100644
--- a/indra/llimage/llimageworker.cpp
+++ b/indra/llimage/llimageworker.cpp
@@ -161,7 +161,7 @@ bool ImageRequest::processRequest()
 			{
 				return true; // done (failed)
 			}
-			if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()))
+			if (0 == (mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()))
 			{
 				return true; // done (failed)
 			}
diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h
index dff5bf3af3..663764ce04 100644
--- a/indra/llmath/llcalcparser.h
+++ b/indra/llmath/llcalcparser.h
@@ -131,14 +131,14 @@ struct LLCalcParser : grammar<LLCalcParser>
 			
 			power =
 				unary_expr[power.value = arg1] >>
-				*('^' >> assert_syntax(unary_expr[power.value = phoenix::bind(&powf)(power.value, arg1)]))
+				*('^' >> assert_syntax(unary_expr[power.value = phoenix::bind(&LLCalcParser::_pow)(self, power.value, arg1)]))
 			;
 			
 			term =
 				power[term.value = arg1] >>
 				*(('*' >> assert_syntax(power[term.value *= arg1])) |
 				  ('/' >> assert_syntax(power[term.value /= arg1])) |
-				  ('%' >> assert_syntax(power[term.value = phoenix::bind(&fmodf)(term.value, arg1)]))
+				  ('%' >> assert_syntax(power[term.value = phoenix::bind(&LLCalcParser::_fmod)(self, term.value, arg1)]))
 				)
 			;
 			
@@ -177,6 +177,8 @@ private:
 	F32 _floor(const F32& a) const { return (F32)llfloor(a); }
 	F32 _ceil(const F32& a) const { return llceil(a); }
 	F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); }
+	F32 _pow(const F32& a, const F32& b) const { return powf(a, b); }
+	F32 _fmod(const F32&a, const F32& b) const { return fmodf(a, b); }
 
 	LLCalc::calc_map_t* mConstants;
 	LLCalc::calc_map_t* mVariables;
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index e44309476b..88ab29ec67 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -3,14 +3,11 @@
 project(llmessage)
 
 include(00-Common)
-include(GoogleMock)
 include(LLAddBuildTest)
 include(LLCommon)
 include(LLCoreHttp)
 include(LLAddBuildTest)
 include(Python)
-include(Tut)
-include(Python)
 include(JsonCpp)
 
 set(llmessage_SOURCE_FILES
diff --git a/indra/llmessage/llnamevalue.cpp b/indra/llmessage/llnamevalue.cpp
index c51883ee3d..15de4046ac 100644
--- a/indra/llmessage/llnamevalue.cpp
+++ b/indra/llmessage/llnamevalue.cpp
@@ -35,6 +35,10 @@
 #include "llstring.h"
 #include "llstringtable.h"
 
+#if LL_LINUX
+#pragma GCC diagnostic ignored "-Wstringop-truncation" // It's actually okay what happens here
+#endif
+
 // Anonymous enumeration to provide constants in this file.
 // *NOTE: These values may be used in sscanf statements below as their
 // value-1, so search for '2047' if you cange NV_BUFFER_LEN or '63' if
diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp
index f4f08248b8..35da0794e2 100644
--- a/indra/llprimitive/llprimtexturelist.cpp
+++ b/indra/llprimitive/llprimtexturelist.cpp
@@ -137,14 +137,7 @@ S32 LLPrimTextureList::copyTexture(const U8 index, const LLTextureEntry& te)
 		// we're changing an existing entry
 	llassert(mEntryList[index]);
 	delete (mEntryList[index]);
-	if  (&te)
-	{
-		mEntryList[index] = te.newCopy();
-	}
-	else
-	{
-		mEntryList[index] = LLPrimTextureList::newTextureEntry();
-	}
+	mEntryList[index] = te.newCopy();
 	return TEM_CHANGE_TEXTURE;
 }
 
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index d87fb5245c..f9363fe5a8 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -1,25 +1,25 @@
-/** 
+/**
  * @file llfontfreetype.cpp
  * @brief Freetype font library wrapper
  *
  * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -52,7 +52,9 @@
 #include "llfontbitmapcache.h"
 #include "llgl.h"
 
-#define ENABLE_OT_SVG_SUPPORT
+#if !defined(LL_NO_OTSVG)
+	#define ENABLE_OT_SVG_SUPPORT
+#endif
 
 FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL;
 
@@ -63,7 +65,7 @@ FT_Library gFTLibrary = NULL;
 //static
 void LLFontManager::initClass()
 {
-	if (!gFontManagerp) 
+	if (!gFontManagerp)
 	{
 		gFontManagerp = new LLFontManager;
 	}
@@ -87,7 +89,7 @@ LLFontManager::LLFontManager()
 		FT_Done_FreeType(gFTLibrary);
 	}
 
-#ifdef ENABLE_OT_SVG_SUPPORT
+#if defined(ENABLE_OT_SVG_SUPPORT)
 	SVG_RendererHooks hooks = {
 		LLFontFreeTypeSvgRenderer::OnInit,
 		LLFontFreeTypeSvgRenderer::OnFree,
@@ -196,7 +198,7 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
 		FT_Done_Face(mFTFace);
 		mFTFace = NULL;
 	}
-	
+
 	int error;
 #ifdef LL_WINDOWS
 	error = ftOpenFace(filename, face_n);
@@ -294,7 +296,7 @@ S32 LLFontFreetype::getNumFaces(const std::string& filename)
 
 #ifdef LL_WINDOWS
 	int error = ftOpenFace(filename, 0);
-		
+
 	if (error)
 	{
 		return 0;
@@ -303,7 +305,7 @@ S32 LLFontFreetype::getNumFaces(const std::string& filename)
 	{
 		num_faces = mFTFace->num_faces;
 	}
-	
+
 	FT_Done_Face(mFTFace);
 	clearFontStreams();
 	mFTFace = NULL;
@@ -490,9 +492,9 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type
 			}
 		}
 	}
-	
+
 	std::pair<char_glyph_info_map_t::iterator, char_glyph_info_map_t::iterator> range_it = mCharGlyphInfoMap.equal_range(wch);
-	char_glyph_info_map_t::iterator iter = 
+	char_glyph_info_map_t::iterator iter =
 		std::find_if(range_it.first, range_it.second, [&glyph_type](const char_glyph_info_map_t::value_type& entry) { return entry.second->mGlyphType == glyph_type; });
 	if (iter == range_it.second)
 	{
@@ -609,7 +611,7 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l
 	} else {
 		llassert(false);
 	}
-	
+
 	LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_glyph_type, bitmap_num);
 	LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_glyph_type, bitmap_num);
 	image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight());
@@ -683,7 +685,7 @@ void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) co
 
 void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
 {
-	resetBitmapCache(); 
+	resetBitmapCache();
 	loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mIsFallback, 0);
 	if (!mIsFallback)
 	{
@@ -713,7 +715,7 @@ void LLFontFreetype::resetBitmapCache()
 	mCharGlyphInfoMap.clear();
 	mFontBitmapCachep->reset();
 
-	// Adding default glyph is skipped for fallback fonts here as well as in loadFace(). 
+	// Adding default glyph is skipped for fallback fonts here as well as in loadFace().
 	// This if was added as fix for EXT-4971.
 	if(!mIsFallback)
 	{
@@ -810,7 +812,7 @@ void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32
 
 	llassert(!mIsFallback);
 	llassert(image_raw && (image_raw->getComponents() == 2));
-	
+
 	U8 *target = image_raw->getData();
     llassert(target);
 
diff --git a/indra/llrender/llfontfreetypesvg.cpp b/indra/llrender/llfontfreetypesvg.cpp
index 19d327a4c9..6c44fdd150 100644
--- a/indra/llrender/llfontfreetypesvg.cpp
+++ b/indra/llrender/llfontfreetypesvg.cpp
@@ -80,6 +80,7 @@ void LLFontFreeTypeSvgRenderer::OnDataFinalizer(void* objectp)
 //static
 FT_Error LLFontFreeTypeSvgRenderer::OnPresetGlypthSlot(FT_GlyphSlot glyph_slot, FT_Bool cache, FT_Pointer*)
 {
+#ifndef LL_NO_OTSVG
 	FT_SVG_Document document = static_cast<FT_SVG_Document>(glyph_slot->other);
 
 	llassert(!glyph_slot->generic.data || !cache || glyph_slot->glyph_index == ((LLSvgRenderData*)glyph_slot->generic.data)->GlyphIndex);
@@ -166,6 +167,9 @@ FT_Error LLFontFreeTypeSvgRenderer::OnPresetGlypthSlot(FT_GlyphSlot glyph_slot,
 	}
 
 	return FT_Err_Ok;
+#else
+	return FT_Err_Unimplemented_Feature;
+#endif
 }
 
 // static
diff --git a/indra/llrender/llfontfreetypesvg.h b/indra/llrender/llfontfreetypesvg.h
index b5f541991a..26a533682e 100644
--- a/indra/llrender/llfontfreetypesvg.h
+++ b/indra/llrender/llfontfreetypesvg.h
@@ -29,7 +29,11 @@
 #include <ft2build.h>
 #include FT_TYPES_H
 #include FT_MODULE_H
-#include FT_OTSVG_H
+#ifdef FT_OTSVG_H
+	#include FT_OTSVG_H
+#else
+   #define LL_NO_OTSVG
+#endif
 
  // See https://freetype.org/freetype2/docs/reference/ft2-svg_fonts.html
 class LLFontFreeTypeSvgRenderer
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 9d3abf32bb..0850fe3e05 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -1,30 +1,30 @@
-/** 
+/**
  * @file llgl.cpp
  * @brief LLGL implementation
  *
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
 
-// This file sets some global GL parameters, and implements some 
+// This file sets some global GL parameters, and implements some
 // useful functions for GL operations.
 
 #define GLH_EXT_SINGLE_FILE
@@ -148,7 +148,7 @@ void APIENTRY gl_debug_callback(GLenum source,
         glGetBufferParameteriv(GL_UNIFORM_BUFFER, GL_BUFFER_SIZE, &ubo_size);
         glGetBufferParameteriv(GL_UNIFORM_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE, &ubo_immutable);
     }
-    
+
     if (severity == GL_DEBUG_SEVERITY_HIGH)
     {
         LL_ERRS() << "Halting on GL Error" << LL_ENDL;
@@ -166,7 +166,7 @@ void ll_init_fail_log(std::string filename)
 
 void ll_fail(std::string msg)
 {
-	
+
 	if (gDebugSession)
 	{
 		std::vector<std::string> lines;
@@ -176,7 +176,7 @@ void ll_fail(std::string msg)
 		gFailLog << "Stack Trace:" << std::endl;
 
 		ll_get_stack_trace(lines);
-		
+
 		for(size_t i = 0; i < lines.size(); ++i)
 		{
 			gFailLog << lines[i] << std::endl;
@@ -199,8 +199,6 @@ LLMatrix4 gGLObliqueProjectionInverse;
 
 std::list<LLGLUpdate*> LLGLUpdate::sGLQ;
 
-#if (LL_WINDOWS || LL_LINUX)  && !LL_MESA_HEADLESS
-
 #if LL_WINDOWS
 // WGL_ARB_create_context
 PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = nullptr;
@@ -220,8 +218,6 @@ PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC             wglBlitContextFramebufferAMD = n
 PFNWGLSWAPINTERVALEXTPROC    wglSwapIntervalEXT = nullptr;
 PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT = nullptr;
 
-#endif
-
 // GL_VERSION_1_2
 //PFNGLDRAWRANGEELEMENTSPROC  glDrawRangeElements = nullptr;
 //PFNGLTEXIMAGE3DPROC         glTexImage3D = nullptr;
@@ -991,7 +987,7 @@ LLGLManager::LLGLManager() :
 	mDriverVersionRelease(0),
 	mGLVersion(1.0f),
 	mGLSLVersionMajor(0),
-	mGLSLVersionMinor(0),		
+	mGLSLVersionMinor(0),
 	mVRAM(0),
 	mGLMaxVertexRange(0),
 	mGLMaxIndexRange(0)
@@ -1018,7 +1014,7 @@ void LLGLManager::initWGL()
 		LL_WARNS("RenderInit") << "No ARB create context extensions" << LL_ENDL;
 	}
 
-	// For retreiving information per AMD adapter, 
+	// For retreiving information per AMD adapter,
 	// because we can't trust curently selected/default one when there are multiple
 	mHasAMDAssociations = ExtensionExists("WGL_AMD_gpu_association", gGLHExts.mSysExts);
 	if (mHasAMDAssociations)
@@ -1071,7 +1067,7 @@ bool LLGLManager::initGL()
 			str << ext << " ";
 			LL_DEBUGS("GLExtensions") << ext << LL_ENDL;
 		}
-		
+
 		{
 			PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = 0;
 			wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
@@ -1086,7 +1082,7 @@ bool LLGLManager::initGL()
 		gGLHExts.mSysExts = strdup(extensions.c_str());
 	}
 #endif
-	
+
 	// Extract video card strings and convert to upper case to
 	// work around driver-to-driver variation in capitalization.
 	mGLVendor = ll_safe_string((const char *)glGetString(GL_VENDOR));
@@ -1095,9 +1091,9 @@ bool LLGLManager::initGL()
 	mGLRenderer = ll_safe_string((const char *)glGetString(GL_RENDERER));
 	LLStringUtil::toUpper(mGLRenderer);
 
-	parse_gl_version( &mDriverVersionMajor, 
-		&mDriverVersionMinor, 
-		&mDriverVersionRelease, 
+	parse_gl_version( &mDriverVersionMajor,
+		&mDriverVersionMinor,
+		&mDriverVersionRelease,
 		&mDriverVersionVendorString,
 		&mGLVersionString);
 
@@ -1127,7 +1123,7 @@ bool LLGLManager::initGL()
 	{ //GL version is < 3.0, always disable texture compression
 		LLImageGL::sCompressTextures = false;
 	}
-	
+
 	// Trailing space necessary to keep "nVidia Corpor_ati_on" cards
 	// from being recognized as ATI.
     // NOTE: AMD has been pretty good about not breaking this check, do not rename without good reason
@@ -1157,7 +1153,7 @@ bool LLGLManager::initGL()
 	{
 		mGLVendorShort = "MISC";
 	}
-	
+
 	// This is called here because it depends on the setting of mIsGF2or4MX, and sets up mHasMultitexture.
 	initExtensions();
 
@@ -1281,12 +1277,12 @@ std::string LLGLManager::getGLInfoString()
 		info_str += std::string("GL_VERSION     ") + ll_safe_string((const char *)glGetString(GL_VERSION)) + std::string("\n");
 	}
 
-#if !LL_MESA_HEADLESS 
+#if !LL_MESA_HEADLESS
 	std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts));
 	LLStringUtil::replaceChar(all_exts, ' ', '\n');
 	info_str += std::string("GL_EXTENSIONS:\n") + all_exts + std::string("\n");
 #endif
-	
+
 	return info_str;
 }
 
@@ -1369,6 +1365,9 @@ void LLGLManager::shutdownGL()
 
 void LLGLManager::initExtensions()
 {
+#if LL_LINUX
+	glh_init_extensions("");
+#endif
 #if LL_DARWIN
     GLint num_extensions = 0;
     std::string all_extensions{""};
@@ -1386,9 +1385,9 @@ void LLGLManager::initExtensions()
 #endif
 
     // NOTE: version checks against mGLVersion should bias down by 0.01 because of F32 errors
-    
+
     // OpenGL 4.x capabilities
-    mHasCubeMapArray = mGLVersion >= 3.99f; 
+    mHasCubeMapArray = mGLVersion >= 3.99f;
     mHasTransformFeedback = mGLVersion >= 3.99f;
     mHasDebugOutput = mGLVersion >= 4.29f;
 
@@ -1399,10 +1398,9 @@ void LLGLManager::initExtensions()
 
     mInited = TRUE;
 
-#if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS
-	LL_DEBUGS("RenderInit") << "GL Probe: Getting symbols" << LL_ENDL;
-	
 #if LL_WINDOWS
+	LL_DEBUGS("RenderInit") << "GL Probe: Getting symbols" << LL_ENDL;
+
     // WGL_AMD_gpu_association
     wglGetGPUIDsAMD = (PFNWGLGETGPUIDSAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUIDsAMD");
     wglGetGPUInfoAMD = (PFNWGLGETGPUINFOAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUInfoAMD");
@@ -1420,8 +1418,6 @@ void LLGLManager::initExtensions()
 
     // WGL_ARB_create_context
     wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglCreateContextAttribsARB");
-#endif
-
 
     // Load entire OpenGL API through GetProcAddress, leaving sections beyond mGLVersion unloaded
 
@@ -2237,7 +2233,7 @@ void LLGLManager::initExtensions()
     glMultiDrawArraysIndirectCount = (PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiDrawArraysIndirectCount");
     glMultiDrawElementsIndirectCount = (PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiDrawElementsIndirectCount");
     glPolygonOffsetClamp = (PFNGLPOLYGONOFFSETCLAMPPROC)GLH_EXT_GET_PROC_ADDRESS("glPolygonOffsetClamp");
-    
+
 #endif
 }
 
@@ -2260,7 +2256,7 @@ void log_glerror()
 	{
 		return ;
 	}
-	//  Create or update texture to be used with this data 
+	//  Create or update texture to be used with this data
 	GLenum error;
 	error = glGetError();
 	while (LL_UNLIKELY(error))
@@ -2268,7 +2264,7 @@ void log_glerror()
 		GLubyte const * gl_error_msg = gluErrorString(error);
 		if (NULL != gl_error_msg)
 		{
-			LL_WARNS() << "GL Error: " << error << " GL Error String: " << gl_error_msg << LL_ENDL ;			
+			LL_WARNS() << "GL Error: " << error << " GL Error String: " << gl_error_msg << LL_ENDL ;
 		}
 		else
 		{
@@ -2282,7 +2278,7 @@ void log_glerror()
 
 void do_assert_glerror()
 {
-	//  Create or update texture to be used with this data 
+	//  Create or update texture to be used with this data
 	GLenum error;
 	error = glGetError();
 	BOOL quit = FALSE;
@@ -2339,7 +2335,7 @@ void assert_glerror()
 	}
 */
 
-	if (!gDebugGL) 
+	if (!gDebugGL)
 	{
 		//funny looking if for branch prediction -- gDebugGL is almost always false and assert_glerror is called often
 	}
@@ -2348,7 +2344,7 @@ void assert_glerror()
 		do_assert_glerror();
 	}
 }
-	
+
 
 void clear_glerror()
 {
@@ -2369,11 +2365,11 @@ GLenum LLGLDepthTest::sDepthFunc = GL_LESS; // OpenGL default
 GLboolean LLGLDepthTest::sWriteEnabled = GL_TRUE; // OpenGL default
 
 //static
-void LLGLState::initClass() 
+void LLGLState::initClass()
 {
 	sStateMap[GL_DITHER] = GL_TRUE;
 	// sStateMap[GL_TEXTURE_2D] = GL_TRUE;
-	
+
 	//make sure multisample defaults to disabled
 	sStateMap[GL_MULTISAMPLE] = GL_FALSE;
 	glDisable(GL_MULTISAMPLE);
@@ -2392,7 +2388,7 @@ void LLGLState::resetTextureStates()
 {
 	gGL.flush();
 	GLint maxTextureUnits;
-	
+
 	glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits);
 	for (S32 j = maxTextureUnits-1; j >=0; j--)
 	{
@@ -2402,7 +2398,7 @@ void LLGLState::resetTextureStates()
 	}
 }
 
-void LLGLState::dumpStates() 
+void LLGLState::dumpStates()
 {
 	LL_INFOS("RenderState") << "GL States:" << LL_ENDL;
 	for (boost::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
@@ -2425,15 +2421,15 @@ void LLGLState::checkStates(GLboolean writeAlpha)
 	glGetIntegerv(GL_BLEND_DST, &dst);
     llassert_always(src == GL_SRC_ALPHA);
     llassert_always(dst == GL_ONE_MINUS_SRC_ALPHA);
-  
+
     // disable for now until usage is consistent
     //GLboolean colorMask[4];
     //glGetBooleanv(GL_COLOR_WRITEMASK, colorMask);
     //llassert_always(colorMask[0]);
     //llassert_always(colorMask[1]);
     //llassert_always(colorMask[2]);
-    // llassert_always(colorMask[3] == writeAlpha);  
-	
+    // llassert_always(colorMask[3] == writeAlpha);
+
 	for (boost::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
 		 iter != sStateMap.end(); ++iter)
 	{
@@ -2487,7 +2483,7 @@ void LLGLState::setEnabled(S32 enabled)
 	mIsEnabled = enabled;
 }
 
-LLGLState::~LLGLState() 
+LLGLState::~LLGLState()
 {
     LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
 	if (mState)
@@ -2536,7 +2532,7 @@ void LLGLManager::initGLStates()
 
 void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string )
 {
-	// GL_VERSION returns a null-terminated string with the format: 
+	// GL_VERSION returns a null-terminated string with the format:
 	// <major>.<minor>[.<release>] [<vendor specific>]
 
 	const char* version = (const char*) glGetString(GL_VERSION);
@@ -2549,6 +2545,7 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor
 	{
 		return;
 	}
+    LL_INFOS() << "GL: "  << version << LL_ENDL;
 
 	version_string->assign(version);
 
@@ -2619,13 +2616,13 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor
 
 void parse_glsl_version(S32& major, S32& minor)
 {
-	// GL_SHADING_LANGUAGE_VERSION returns a null-terminated string with the format: 
+	// GL_SHADING_LANGUAGE_VERSION returns a null-terminated string with the format:
 	// <major>.<minor>[.<release>] [<vendor specific>]
 
 	const char* version = (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION);
 	major = 0;
 	minor = 0;
-	
+
 	if( !version )
 	{
 		return;
@@ -2694,7 +2691,7 @@ void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d)
 {
 	glh::matrix4f& P = mProjection;
 	glh::matrix4f& M = mModelview;
-    
+
 	glh::matrix4f invtrans_MVP = (P * M).inverse().transpose();
     glh::vec4f oplane(a,b,c,d);
     glh::vec4f cplane;
@@ -2725,7 +2722,7 @@ LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, G
 : mPrevDepthEnabled(sDepthEnabled), mPrevDepthFunc(sDepthFunc), mPrevWriteEnabled(sWriteEnabled)
 {
 	stop_glerror();
-	
+
 	checkState();
 
 	if (!depth_enabled)
@@ -2848,7 +2845,7 @@ LLGLSquashToFarClip::~LLGLSquashToFarClip()
 }
 
 
-	
+
 LLGLSyncFence::LLGLSyncFence()
 {
 	mSync = 0;
@@ -2898,7 +2895,7 @@ void LLGLSyncFence::wait()
 LLGLSPipelineSkyBox::LLGLSPipelineSkyBox()
 : mCullFace(GL_CULL_FACE)
 , mSquashClip()
-{ 
+{
 }
 
 LLGLSPipelineSkyBox::~LLGLSPipelineSkyBox()
@@ -2913,20 +2910,18 @@ LLGLSPipelineDepthTestSkyBox::LLGLSPipelineDepthTestSkyBox(bool depth_test, bool
 }
 
 LLGLSPipelineBlendSkyBox::LLGLSPipelineBlendSkyBox(bool depth_test, bool depth_write)
-: LLGLSPipelineDepthTestSkyBox(depth_test, depth_write)    
+: LLGLSPipelineDepthTestSkyBox(depth_test, depth_write)
 , mBlend(GL_BLEND)
-{ 
+{
     gGL.setSceneBlendType(LLRender::BT_ALPHA);
 }
 
 #if LL_WINDOWS
 // Expose desired use of high-performance graphics processor to Optimus driver and to AMD driver
 // https://docs.nvidia.com/gameworks/content/technologies/desktop/optimus.htm
-extern "C" 
-{ 
+extern "C"
+{
     __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
     __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
 }
 #endif
-
-
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index c1238ac6b9..fe7625236d 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -41,6 +41,22 @@
 # include "GL/glh_extensions.h"
 # undef __APPLE__
 
+#elif LL_LINUX
+#define GL_GLEXT_PROTOTYPES
+#define GLX_GLEXT_PROTOTYPES
+
+#include "GL/gl.h"
+#include "GL/glext.h"
+#include "GL/glu.h"
+
+// The __APPLE__ kludge is to make glh_extensions.h not symbol-clash horribly
+# define __APPLE__
+# include "GL/glh_extensions.h"
+# undef __APPLE__
+
+# include "GL/glx.h"
+# include "GL/glxext.h"
+
 #elif LL_WINDOWS
 //----------------------------------------------------------------------------
 // LL_WINDOWS
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index ccfb8f69be..8749976921 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -279,7 +279,7 @@ bool LLGLSLShader::readProfileQuery(bool for_runtime, bool force_read)
             GLuint64 samples_passed = 0;
             glGetQueryObjectui64v(mSamplesQuery, GL_QUERY_RESULT, &samples_passed);
 
-            U64 primitives_generated = 0;
+            GLuint64 primitives_generated = 0;
             glGetQueryObjectui64v(mPrimitivesQuery, GL_QUERY_RESULT, &primitives_generated);
             sTotalTimeElapsed += time_elapsed;
 
diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt
index 7b1430c67c..9ebd6ef0b0 100644
--- a/indra/llwindow/CMakeLists.txt
+++ b/indra/llwindow/CMakeLists.txt
@@ -59,11 +59,12 @@ set(llwindow_LINK_LIBRARIES
         ll::uilibraries
         ll::SDL
         )
+
 # Libraries on which this library depends, needed for Linux builds
 # Sort by high-level to low-level
 if (LINUX)
-  list(APPEND viewer_SOURCE_FILES 
-       llkeyboardsdl.cpp 
+  list(APPEND viewer_SOURCE_FILES
+       llkeyboardsdl.cpp
        llwindowsdl.cpp
        )
   list(APPEND viewer_HEADER_FILES
@@ -83,7 +84,6 @@ if (LINUX)
         fontconfig          # For FCInit and other FC* functions.
         )
   endif (BUILD_HEADLESS)
-
 endif (LINUX)
 
 if (DARWIN)
@@ -179,7 +179,7 @@ endif (SDL_FOUND)
 
   target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES})
   target_include_directories(llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
-  
+
 if (DARWIN)
   include(CMakeFindFrameworks)
   find_library(CARBON_LIBRARY Carbon)
diff --git a/indra/llwindow/llkeyboard.cpp b/indra/llwindow/llkeyboard.cpp
index 34720ff64e..f55e0a0819 100644
--- a/indra/llwindow/llkeyboard.cpp
+++ b/indra/llwindow/llkeyboard.cpp
@@ -1,25 +1,25 @@
-/** 
+/**
  * @file llkeyboard.cpp
  * @brief Handler for assignable key bindings
  *
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -41,7 +41,6 @@ std::map<KEY,std::string> LLKeyboard::sKeysToNames;
 std::map<std::string,KEY> LLKeyboard::sNamesToKeys;
 LLKeyStringTranslatorFunc*	LLKeyboard::mStringTranslator = NULL;	// Used for l10n + PC/Mac/Linux accelerator labeling
 
-
 //
 // Class Implementation
 //
@@ -122,7 +121,7 @@ LLKeyboard::LLKeyboard() : mCallbacks(NULL)
 	addKeyName(KEY_BUTTON13, "PAD_BUTTON13" );
 	addKeyName(KEY_BUTTON14, "PAD_BUTTON14" );
 	addKeyName(KEY_BUTTON15, "PAD_BUTTON15" );
-	
+
 	addKeyName(KEY_BACKSPACE, "Backsp" );
 	addKeyName(KEY_DELETE, "Del" );
 	addKeyName(KEY_SHIFT, "Shift" );
@@ -195,12 +194,11 @@ void LLKeyboard::resetKeys()
 }
 
 
-BOOL LLKeyboard::translateKey(const U16 os_key, KEY *out_key)
+BOOL LLKeyboard::translateKey(const NATIVE_KEY_TYPE os_key, KEY *out_key)
 {
-	std::map<U16, KEY>::iterator iter;
 
 	// Only translate keys in the map, ignore all other keys for now
-	iter = mTranslateKeyMap.find(os_key);
+	auto iter = mTranslateKeyMap.find(os_key);
 	if (iter == mTranslateKeyMap.end())
 	{
 		//LL_WARNS() << "Unknown virtual key " << os_key << LL_ENDL;
@@ -214,11 +212,9 @@ BOOL LLKeyboard::translateKey(const U16 os_key, KEY *out_key)
 	}
 }
 
-
-U16 LLKeyboard::inverseTranslateKey(const KEY translated_key)
+LLKeyboard::NATIVE_KEY_TYPE LLKeyboard::inverseTranslateKey(const KEY translated_key)
 {
-	std::map<KEY, U16>::iterator iter;
-	iter = mInvTranslateKeyMap.find(translated_key);
+	auto iter = mInvTranslateKeyMap.find(translated_key);
 	if (iter == mInvTranslateKeyMap.end())
 	{
 		return 0;
@@ -250,7 +246,7 @@ BOOL LLKeyboard::handleTranslatedKeyDown(KEY translated_key, U32 translated_mask
 		repeated = TRUE;
 		mKeyRepeated[translated_key] = TRUE;
 	}
-	
+
 	mKeyDown[translated_key] = TRUE;
 	mCurTranslatedKey = (KEY)translated_key;
 	handled = mCallbacks->handleTranslatedKeyDown(translated_key, translated_mask, repeated);
@@ -259,12 +255,12 @@ BOOL LLKeyboard::handleTranslatedKeyDown(KEY translated_key, U32 translated_mask
 
 
 BOOL LLKeyboard::handleTranslatedKeyUp(KEY translated_key, U32 translated_mask)
-{	
+{
 	BOOL handled = FALSE;
 	if( mKeyLevel[translated_key] )
 	{
 		mKeyLevel[translated_key] = FALSE;
-		
+
 		// Only generate key up events if the key is thought to
 		// be down.  This allows you to call resetKeys() in the
 		// middle of a frame and ignore subsequent KEY_UP
@@ -273,7 +269,7 @@ BOOL LLKeyboard::handleTranslatedKeyUp(KEY translated_key, U32 translated_mask)
 		mKeyUp[translated_key] = TRUE;
 		handled = mCallbacks->handleTranslatedKeyUp(translated_key, translated_mask);
 	}
-	
+
 	LL_DEBUGS("UserInput") << "keyup -" << translated_key << "-" << LL_ENDL;
 
 	return handled;
@@ -451,13 +447,13 @@ std::string LLKeyboard::stringFromAccelerator(MASK accel_mask)
 std::string LLKeyboard::stringFromAccelerator( MASK accel_mask, KEY key )
 {
 	std::string res;
-	
+
 	// break early if this is a silly thing to do.
 	if( KEY_NONE == key )
 	{
 		return res;
 	}
-	
+
 	res.append(stringFromAccelerator(accel_mask));
 	std::string key_string = LLKeyboard::stringFromKey(key);
 	if ((accel_mask & MASK_NORMALKEYS) &&
@@ -468,7 +464,7 @@ std::string LLKeyboard::stringFromAccelerator( MASK accel_mask, KEY key )
 
 	std::string keystr = stringFromKey( key );
 	res.append( keystr );
-	
+
 	return res;
 }
 
@@ -529,7 +525,7 @@ BOOL LLKeyboard::maskFromString(const std::string& str, MASK *mask)
 		*mask = MASK_CONTROL | MASK_ALT | MASK_SHIFT;
 		return TRUE;
 	}
-	else 
+	else
 	{
 		return FALSE;
 	}
diff --git a/indra/llwindow/llkeyboard.h b/indra/llwindow/llkeyboard.h
index dad150e3c1..2c96df3b5b 100644
--- a/indra/llwindow/llkeyboard.h
+++ b/indra/llwindow/llkeyboard.h
@@ -1,25 +1,25 @@
-/** 
+/**
  * @file llkeyboard.h
  * @brief Handler for assignable key bindings
  *
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -34,7 +34,7 @@
 #include "lltimer.h"
 #include "indra_constants.h"
 
-enum EKeystate 
+enum EKeystate
 {
 	KEYSTATE_DOWN,
 	KEYSTATE_LEVEL,
@@ -43,7 +43,7 @@ enum EKeystate
 
 typedef boost::function<bool(EKeystate keystate)> LLKeyFunc;
 typedef std::string (LLKeyStringTranslatorFunc)(const char *label);
-	
+
 enum EKeyboardInsertMode
 {
 	LL_KIM_INSERT,
@@ -55,6 +55,11 @@ class LLWindowCallbacks;
 class LLKeyboard
 {
 public:
+#ifndef LL_SDL
+    typedef U16 NATIVE_KEY_TYPE;
+#else
+    typedef U32 NATIVE_KEY_TYPE;
+#endif
 	LLKeyboard();
 	virtual ~LLKeyboard();
 
@@ -67,15 +72,14 @@ public:
 	BOOL			getKeyDown(const KEY key) { return mKeyLevel[key]; }
 	BOOL			getKeyRepeated(const KEY key) { return mKeyRepeated[key]; }
 
-	BOOL			translateKey(const U16 os_key, KEY *translated_key);
-	U16				inverseTranslateKey(const KEY translated_key);
+	BOOL			translateKey(const NATIVE_KEY_TYPE os_key, KEY *translated_key);
+    NATIVE_KEY_TYPE		inverseTranslateKey(const KEY translated_key);
 	BOOL			handleTranslatedKeyUp(KEY translated_key, U32 translated_mask);		// Translated into "Linden" keycodes
 	BOOL			handleTranslatedKeyDown(KEY translated_key, U32 translated_mask);	// Translated into "Linden" keycodes
 
+	virtual BOOL	handleKeyUp(const NATIVE_KEY_TYPE key, MASK mask) = 0;
+	virtual BOOL	handleKeyDown(const NATIVE_KEY_TYPE key, MASK mask) = 0;
 
-	virtual BOOL	handleKeyUp(const U16 key, MASK mask) = 0;
-	virtual BOOL	handleKeyDown(const U16 key, MASK mask) = 0;
-	
 #ifdef LL_DARWIN
 	// We only actually use this for OS X.
 	virtual void	handleModifier(MASK mask) = 0;
@@ -106,13 +110,13 @@ public:
 	S32				getKeyElapsedFrameCount( KEY key );  // Returns time in frames since key was pressed.
 
 	static void		setStringTranslatorFunc( LLKeyStringTranslatorFunc *trans_func );
-	
+
 protected:
 	void 			addKeyName(KEY key, const std::string& name);
 
 protected:
-	std::map<U16, KEY>	mTranslateKeyMap;		// Map of translations from OS keys to Linden KEYs
-	std::map<KEY, U16>	mInvTranslateKeyMap;	// Map of translations from Linden KEYs to OS keys
+	std::map<NATIVE_KEY_TYPE, KEY>	mTranslateKeyMap;		// Map of translations from OS keys to Linden KEYs
+	std::map<KEY, NATIVE_KEY_TYPE>	mInvTranslateKeyMap;	// Map of translations from Linden KEYs to OS keys
 	LLWindowCallbacks *mCallbacks;
 
 	LLTimer			mKeyLevelTimer[KEY_COUNT];	// Time since level was set
@@ -125,7 +129,7 @@ protected:
 	KEY				mCurScanKey;		// Used during the scanKeyboard()
 
 	static LLKeyStringTranslatorFunc*	mStringTranslator;	// Used for l10n + PC/Mac/Linux accelerator labeling
-	
+
 	EKeyboardInsertMode mInsertMode;
 
 	static std::map<KEY,std::string> sKeysToNames;
diff --git a/indra/llwindow/llkeyboardheadless.cpp b/indra/llwindow/llkeyboardheadless.cpp
index a1b6b294e0..0785410357 100644
--- a/indra/llwindow/llkeyboardheadless.cpp
+++ b/indra/llwindow/llkeyboardheadless.cpp
@@ -35,12 +35,8 @@ void LLKeyboardHeadless::resetMaskKeys()
 { }
 
 
-BOOL LLKeyboardHeadless::handleKeyDown(const U16 key, const U32 mask)
-{ return FALSE; }
 
 
-BOOL LLKeyboardHeadless::handleKeyUp(const U16 key, const U32 mask)
-{ return FALSE; }
 
 MASK LLKeyboardHeadless::currentMask(BOOL for_mouse_event)
 { return MASK_NONE; }
diff --git a/indra/llwindow/llkeyboardheadless.h b/indra/llwindow/llkeyboardheadless.h
index 8ed28ace90..79c276fdbb 100644
--- a/indra/llwindow/llkeyboardheadless.h
+++ b/indra/llwindow/llkeyboardheadless.h
@@ -35,8 +35,13 @@ public:
 	LLKeyboardHeadless();
 	/*virtual*/ ~LLKeyboardHeadless() {};
 
-	/*virtual*/ BOOL	handleKeyUp(const U16 key, MASK mask);
-	/*virtual*/ BOOL	handleKeyDown(const U16 key, MASK mask);
+#ifndef LL_SDL
+	/*virtual*/ BOOL	handleKeyUp(const U16 key, MASK mask) { return FALSE; }
+	/*virtual*/ BOOL	handleKeyDown(const U16 key, MASK mask) { return FALSE; }
+#else
+    /*virtual*/ BOOL	handleKeyUp(const U32 key, MASK mask) { return FALSE; }
+    /*virtual*/ BOOL	handleKeyDown(const U32 key, MASK mask) { return FALSE; }
+#endif
 	/*virtual*/ void	resetMaskKeys();
 	/*virtual*/ MASK	currentMask(BOOL for_mouse_event);
 	/*virtual*/ void	scanKeyboard();
diff --git a/indra/llwindow/llkeyboardsdl.cpp b/indra/llwindow/llkeyboardsdl.cpp
index 7c9aa1d340..b29b832011 100644
--- a/indra/llwindow/llkeyboardsdl.cpp
+++ b/indra/llwindow/llkeyboardsdl.cpp
@@ -1,324 +1,661 @@
-/** 
- * @file llkeyboardsdl.cpp
- * @brief Handler for assignable key bindings
+/**
+ * @author This module has many fathers, and it shows.
  *
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
 
-#if LL_SDL
-
 #include "linden_common.h"
 #include "llkeyboardsdl.h"
 #include "llwindowcallbacks.h"
-#include "SDL/SDL.h"
+#include "SDL2/SDL.h"
+#include "SDL2/SDL_keycode.h"
 
 LLKeyboardSDL::LLKeyboardSDL()
 {
-	// Set up key mapping for SDL - eventually can read this from a file?
-	// Anything not in the key map gets dropped
-	// Add default A-Z
-
-	// Virtual key mappings from SDL_keysym.h ...
-
-	// SDL maps the letter keys to the ASCII you'd expect, but it's lowercase...
-	U16 cur_char;
-	for (cur_char = 'A'; cur_char <= 'Z'; cur_char++)
-	{
-		mTranslateKeyMap[cur_char] = cur_char;
-	}
-	for (cur_char = 'a'; cur_char <= 'z'; cur_char++)
-	{
-		mTranslateKeyMap[cur_char] = (cur_char - 'a') + 'A';
-	}
-
-	for (cur_char = '0'; cur_char <= '9'; cur_char++)
-	{
-		mTranslateKeyMap[cur_char] = cur_char;
-	}
-
-	// These ones are translated manually upon keydown/keyup because
-	// SDL doesn't handle their numlock transition.
-	//mTranslateKeyMap[SDLK_KP4] = KEY_PAD_LEFT;
-	//mTranslateKeyMap[SDLK_KP6] = KEY_PAD_RIGHT;
-	//mTranslateKeyMap[SDLK_KP8] = KEY_PAD_UP;
-	//mTranslateKeyMap[SDLK_KP2] = KEY_PAD_DOWN;
-	//mTranslateKeyMap[SDLK_KP_PERIOD] = KEY_DELETE;
-	//mTranslateKeyMap[SDLK_KP7] = KEY_HOME;
-	//mTranslateKeyMap[SDLK_KP1] = KEY_END;
-	//mTranslateKeyMap[SDLK_KP9] = KEY_PAGE_UP;
-	//mTranslateKeyMap[SDLK_KP3] = KEY_PAGE_DOWN;
-	//mTranslateKeyMap[SDLK_KP0] = KEY_INSERT;
-
-	mTranslateKeyMap[SDLK_SPACE] = ' ';
-	mTranslateKeyMap[SDLK_RETURN] = KEY_RETURN;
-	mTranslateKeyMap[SDLK_LEFT] = KEY_LEFT;
-	mTranslateKeyMap[SDLK_RIGHT] = KEY_RIGHT;
-	mTranslateKeyMap[SDLK_UP] = KEY_UP;
-	mTranslateKeyMap[SDLK_DOWN] = KEY_DOWN;
-	mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
-	mTranslateKeyMap[SDLK_KP_ENTER] = KEY_RETURN;
-	mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
-	mTranslateKeyMap[SDLK_BACKSPACE] = KEY_BACKSPACE;
-	mTranslateKeyMap[SDLK_DELETE] = KEY_DELETE;
-	mTranslateKeyMap[SDLK_LSHIFT] = KEY_SHIFT;
-	mTranslateKeyMap[SDLK_RSHIFT] = KEY_SHIFT;
-	mTranslateKeyMap[SDLK_LCTRL] = KEY_CONTROL;
-	mTranslateKeyMap[SDLK_RCTRL] = KEY_CONTROL;
-	mTranslateKeyMap[SDLK_LALT] = KEY_ALT;
-	mTranslateKeyMap[SDLK_RALT] = KEY_ALT;
-	mTranslateKeyMap[SDLK_HOME] = KEY_HOME;
-	mTranslateKeyMap[SDLK_END] = KEY_END;
-	mTranslateKeyMap[SDLK_PAGEUP] = KEY_PAGE_UP;
-	mTranslateKeyMap[SDLK_PAGEDOWN] = KEY_PAGE_DOWN;
-	mTranslateKeyMap[SDLK_MINUS] = KEY_HYPHEN;
-	mTranslateKeyMap[SDLK_EQUALS] = KEY_EQUALS;
-	mTranslateKeyMap[SDLK_KP_EQUALS] = KEY_EQUALS;
-	mTranslateKeyMap[SDLK_INSERT] = KEY_INSERT;
-	mTranslateKeyMap[SDLK_CAPSLOCK] = KEY_CAPSLOCK;
-	mTranslateKeyMap[SDLK_TAB] = KEY_TAB;
-	mTranslateKeyMap[SDLK_KP_PLUS] = KEY_ADD;
-	mTranslateKeyMap[SDLK_KP_MINUS] = KEY_SUBTRACT;
-	mTranslateKeyMap[SDLK_KP_MULTIPLY] = KEY_MULTIPLY;
-	mTranslateKeyMap[SDLK_KP_DIVIDE] = KEY_PAD_DIVIDE;
-	mTranslateKeyMap[SDLK_F1] = KEY_F1;
-	mTranslateKeyMap[SDLK_F2] = KEY_F2;
-	mTranslateKeyMap[SDLK_F3] = KEY_F3;
-	mTranslateKeyMap[SDLK_F4] = KEY_F4;
-	mTranslateKeyMap[SDLK_F5] = KEY_F5;
-	mTranslateKeyMap[SDLK_F6] = KEY_F6;
-	mTranslateKeyMap[SDLK_F7] = KEY_F7;
-	mTranslateKeyMap[SDLK_F8] = KEY_F8;
-	mTranslateKeyMap[SDLK_F9] = KEY_F9;
-	mTranslateKeyMap[SDLK_F10] = KEY_F10;
-	mTranslateKeyMap[SDLK_F11] = KEY_F11;
-	mTranslateKeyMap[SDLK_F12] = KEY_F12;
-	mTranslateKeyMap[SDLK_PLUS]   = '=';
-	mTranslateKeyMap[SDLK_COMMA]  = ',';
-	mTranslateKeyMap[SDLK_MINUS]  = '-';
-	mTranslateKeyMap[SDLK_PERIOD] = '.';
-	mTranslateKeyMap[SDLK_BACKQUOTE] = '`';
-	mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE;
-	mTranslateKeyMap[SDLK_SEMICOLON] = ';';
-	mTranslateKeyMap[SDLK_LEFTBRACKET] = '[';
-	mTranslateKeyMap[SDLK_BACKSLASH] = '\\';
-	mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']';
-	mTranslateKeyMap[SDLK_QUOTE] = '\'';
-
-	// Build inverse map
-	std::map<U16, KEY>::iterator iter;
-	for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
-	{
-		mInvTranslateKeyMap[iter->second] = iter->first;
-	}
-
-	// numpad map
-	mTranslateNumpadMap[SDLK_KP0] = KEY_PAD_INS;
-	mTranslateNumpadMap[SDLK_KP1] = KEY_PAD_END;
-	mTranslateNumpadMap[SDLK_KP2] = KEY_PAD_DOWN;
-	mTranslateNumpadMap[SDLK_KP3] = KEY_PAD_PGDN;
-	mTranslateNumpadMap[SDLK_KP4] = KEY_PAD_LEFT;
-	mTranslateNumpadMap[SDLK_KP5] = KEY_PAD_CENTER;
-	mTranslateNumpadMap[SDLK_KP6] = KEY_PAD_RIGHT;
-	mTranslateNumpadMap[SDLK_KP7] = KEY_PAD_HOME;
-	mTranslateNumpadMap[SDLK_KP8] = KEY_PAD_UP;
-	mTranslateNumpadMap[SDLK_KP9] = KEY_PAD_PGUP;
-	mTranslateNumpadMap[SDLK_KP_PERIOD] = KEY_PAD_DEL;
-
-	// build inverse numpad map
-	for (iter = mTranslateNumpadMap.begin();
-	     iter != mTranslateNumpadMap.end();
-	     iter++)
-	{
-		mInvTranslateNumpadMap[iter->second] = iter->first;
-	}
+    // Set up key mapping for SDL - eventually can read this from a file?
+    // Anything not in the key map gets dropped
+    // Add default A-Z
+
+    // Virtual key mappings from SDL_keysym.h ...
+
+    // SDL maps the letter keys to the ASCII you'd expect, but it's lowercase...
+
+    // <FS:ND> Looks like we need to map those despite of SDL_TEXTINPUT handling most of this, but without
+    // the translation lower->upper here accelerators will not work.
+
+    U16 cur_char;
+    for (cur_char = 'A'; cur_char <= 'Z'; cur_char++)
+    {
+        mTranslateKeyMap[cur_char] = cur_char;
+    }
+    for (cur_char = 'a'; cur_char <= 'z'; cur_char++)
+    {
+        mTranslateKeyMap[cur_char] = (cur_char - 'a') + 'A';
+    }
+
+    for (cur_char = '0'; cur_char <= '9'; cur_char++)
+    {
+        mTranslateKeyMap[cur_char] = cur_char;
+    }
+
+    // These ones are translated manually upon keydown/keyup because
+    // SDL doesn't handle their numlock transition.
+    //mTranslateKeyMap[SDLK_KP4] = KEY_PAD_LEFT;
+    //mTranslateKeyMap[SDLK_KP6] = KEY_PAD_RIGHT;
+    //mTranslateKeyMap[SDLK_KP8] = KEY_PAD_UP;
+    //mTranslateKeyMap[SDLK_KP2] = KEY_PAD_DOWN;
+    //mTranslateKeyMap[SDLK_KP_PERIOD] = KEY_DELETE;
+    //mTranslateKeyMap[SDLK_KP7] = KEY_HOME;
+    //mTranslateKeyMap[SDLK_KP1] = KEY_END;
+    //mTranslateKeyMap[SDLK_KP9] = KEY_PAGE_UP;
+    //mTranslateKeyMap[SDLK_KP3] = KEY_PAGE_DOWN;
+    //mTranslateKeyMap[SDLK_KP0] = KEY_INSERT;
+
+    mTranslateKeyMap[SDLK_SPACE] = ' '; 	// <FS:ND/> Those are handled by SDL2 via text input, do not map them
+    mTranslateKeyMap[SDLK_RETURN] = KEY_RETURN;
+    mTranslateKeyMap[SDLK_LEFT] = KEY_LEFT;
+    mTranslateKeyMap[SDLK_RIGHT] = KEY_RIGHT;
+    mTranslateKeyMap[SDLK_UP] = KEY_UP;
+    mTranslateKeyMap[SDLK_DOWN] = KEY_DOWN;
+    mTranslateKeyMap[SDLK_KP_ENTER] = KEY_RETURN;
+    mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
+    mTranslateKeyMap[SDLK_BACKSPACE] = KEY_BACKSPACE;
+    mTranslateKeyMap[SDLK_DELETE] = KEY_DELETE;
+    mTranslateKeyMap[SDLK_LSHIFT] = KEY_SHIFT;
+    mTranslateKeyMap[SDLK_RSHIFT] = KEY_SHIFT;
+    mTranslateKeyMap[SDLK_LCTRL] = KEY_CONTROL;
+    mTranslateKeyMap[SDLK_RCTRL] = KEY_CONTROL;
+    mTranslateKeyMap[SDLK_LALT] = KEY_ALT;
+    mTranslateKeyMap[SDLK_RALT] = KEY_ALT;
+    mTranslateKeyMap[SDLK_HOME] = KEY_HOME;
+    mTranslateKeyMap[SDLK_END] = KEY_END;
+    mTranslateKeyMap[SDLK_PAGEUP] = KEY_PAGE_UP;
+    mTranslateKeyMap[SDLK_PAGEDOWN] = KEY_PAGE_DOWN;
+    mTranslateKeyMap[SDLK_MINUS] = KEY_HYPHEN;
+    mTranslateKeyMap[SDLK_EQUALS] = KEY_EQUALS;
+    mTranslateKeyMap[SDLK_KP_EQUALS] = KEY_EQUALS;
+    mTranslateKeyMap[SDLK_INSERT] = KEY_INSERT;
+    mTranslateKeyMap[SDLK_CAPSLOCK] = KEY_CAPSLOCK;
+    mTranslateKeyMap[SDLK_TAB] = KEY_TAB;
+    mTranslateKeyMap[SDLK_KP_PLUS] = KEY_ADD;
+    mTranslateKeyMap[SDLK_KP_MINUS] = KEY_SUBTRACT;
+    mTranslateKeyMap[SDLK_KP_MULTIPLY] = KEY_MULTIPLY;
+    mTranslateKeyMap[SDLK_KP_DIVIDE] = KEY_PAD_DIVIDE;
+    mTranslateKeyMap[SDLK_F1] = KEY_F1;
+    mTranslateKeyMap[SDLK_F2] = KEY_F2;
+    mTranslateKeyMap[SDLK_F3] = KEY_F3;
+    mTranslateKeyMap[SDLK_F4] = KEY_F4;
+    mTranslateKeyMap[SDLK_F5] = KEY_F5;
+    mTranslateKeyMap[SDLK_F6] = KEY_F6;
+    mTranslateKeyMap[SDLK_F7] = KEY_F7;
+    mTranslateKeyMap[SDLK_F8] = KEY_F8;
+    mTranslateKeyMap[SDLK_F9] = KEY_F9;
+    mTranslateKeyMap[SDLK_F10] = KEY_F10;
+    mTranslateKeyMap[SDLK_F11] = KEY_F11;
+    mTranslateKeyMap[SDLK_F12] = KEY_F12;
+    mTranslateKeyMap[SDLK_PLUS]   = '='; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+    mTranslateKeyMap[SDLK_COMMA]  = ','; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+    mTranslateKeyMap[SDLK_MINUS]  = '-'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+    mTranslateKeyMap[SDLK_PERIOD] = '.'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+    mTranslateKeyMap[SDLK_BACKQUOTE] = '`'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+    mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+    mTranslateKeyMap[SDLK_SEMICOLON] = ';'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+    mTranslateKeyMap[SDLK_LEFTBRACKET] = '['; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+    mTranslateKeyMap[SDLK_BACKSLASH] = '\\'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+    mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+    mTranslateKeyMap[SDLK_QUOTE] = '\''; // <FS:ND/> Those are handled by SDL2 via text input, do not map them
+
+    // Build inverse map
+    for (auto iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
+    {
+        mInvTranslateKeyMap[iter->second] = iter->first;
+    }
+
+    // numpad map
+    mTranslateNumpadMap[SDLK_KP_0] = KEY_PAD_INS;
+    mTranslateNumpadMap[SDLK_KP_1] = KEY_PAD_END;
+    mTranslateNumpadMap[SDLK_KP_2] = KEY_PAD_DOWN;
+    mTranslateNumpadMap[SDLK_KP_3] = KEY_PAD_PGDN;
+    mTranslateNumpadMap[SDLK_KP_4] = KEY_PAD_LEFT;
+    mTranslateNumpadMap[SDLK_KP_5] = KEY_PAD_CENTER;
+    mTranslateNumpadMap[SDLK_KP_6] = KEY_PAD_RIGHT;
+    mTranslateNumpadMap[SDLK_KP_7] = KEY_PAD_HOME;
+    mTranslateNumpadMap[SDLK_KP_8] = KEY_PAD_UP;
+    mTranslateNumpadMap[SDLK_KP_9] = KEY_PAD_PGUP;
+    mTranslateNumpadMap[SDLK_KP_PERIOD] = KEY_PAD_DEL;
+
+    // build inverse numpad map
+    for (auto iter = mTranslateNumpadMap.begin();
+         iter != mTranslateNumpadMap.end();
+         iter++)
+    {
+        mInvTranslateNumpadMap[iter->second] = iter->first;
+    }
 }
 
 void LLKeyboardSDL::resetMaskKeys()
 {
-	SDLMod mask = SDL_GetModState();
-
-	// MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys().
-	//    It looks a bit suspicious, as it won't correct for keys that have been released.
-	//    Is this the way it's supposed to work?
-
-	if(mask & KMOD_SHIFT)
-	{
-		mKeyLevel[KEY_SHIFT] = TRUE;
-	}
-
-	if(mask & KMOD_CTRL)
-	{
-		mKeyLevel[KEY_CONTROL] = TRUE;
-	}
-
-	if(mask & KMOD_ALT)
-	{
-		mKeyLevel[KEY_ALT] = TRUE;
-	}
+    SDL_Keymod mask = SDL_GetModState();
+
+    // MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys().
+    //    It looks a bit suspicious, as it won't correct for keys that have been released.
+    //    Is this the way it's supposed to work?
+
+    if(mask & KMOD_SHIFT)
+    {
+        mKeyLevel[KEY_SHIFT] = TRUE;
+    }
+
+    if(mask & KMOD_CTRL)
+    {
+        mKeyLevel[KEY_CONTROL] = TRUE;
+    }
+
+    if(mask & KMOD_ALT)
+    {
+        mKeyLevel[KEY_ALT] = TRUE;
+    }
 }
 
 
 MASK LLKeyboardSDL::updateModifiers(const U32 mask)
 {
-	// translate the mask
-	MASK out_mask = MASK_NONE;
+    // translate the mask
+    MASK out_mask = MASK_NONE;
 
-	if(mask & KMOD_SHIFT)
-	{
-		out_mask |= MASK_SHIFT;
-	}
+    if(mask & KMOD_SHIFT)
+    {
+        out_mask |= MASK_SHIFT;
+    }
 
-	if(mask & KMOD_CTRL)
-	{
-		out_mask |= MASK_CONTROL;
-	}
+    if(mask & KMOD_CTRL)
+    {
+        out_mask |= MASK_CONTROL;
+    }
 
-	if(mask & KMOD_ALT)
-	{
-		out_mask |= MASK_ALT;
-	}
+    if(mask & KMOD_ALT)
+    {
+        out_mask |= MASK_ALT;
+    }
 
-	return out_mask;
+    return out_mask;
 }
 
 
-static U16 adjustNativekeyFromUnhandledMask(const U16 key, const U32 mask)
+static U32 adjustNativekeyFromUnhandledMask(const U32 key, const U32 mask)
 {
-	// SDL doesn't automatically adjust the keysym according to
-	// whether NUMLOCK is engaged, so we massage the keysym manually.
-	U16 rtn = key;
-	if (!(mask & KMOD_NUM))
-	{
-		switch (key)
-		{
-		case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break;
-		case SDLK_KP0: rtn = SDLK_INSERT; break;
-		case SDLK_KP1: rtn = SDLK_END; break;
-		case SDLK_KP2: rtn = SDLK_DOWN; break;
-		case SDLK_KP3: rtn = SDLK_PAGEDOWN; break;
-		case SDLK_KP4: rtn = SDLK_LEFT; break;
-		case SDLK_KP6: rtn = SDLK_RIGHT; break;
-		case SDLK_KP7: rtn = SDLK_HOME; break;
-		case SDLK_KP8: rtn = SDLK_UP; break;
-		case SDLK_KP9: rtn = SDLK_PAGEUP; break;
-		}
-	}
-	return rtn;
+    // SDL doesn't automatically adjust the keysym according to
+    // whether NUMLOCK is engaged, so we massage the keysym manually.
+    U32 rtn = key;
+    if (!(mask & KMOD_NUM))
+    {
+        switch (key)
+        {
+            case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break;
+            case SDLK_KP_0: rtn = SDLK_INSERT; break;
+            case SDLK_KP_1: rtn = SDLK_END; break;
+            case SDLK_KP_2: rtn = SDLK_DOWN; break;
+            case SDLK_KP_3: rtn = SDLK_PAGEDOWN; break;
+            case SDLK_KP_4: rtn = SDLK_LEFT; break;
+            case SDLK_KP_6: rtn = SDLK_RIGHT; break;
+            case SDLK_KP_7: rtn = SDLK_HOME; break;
+            case SDLK_KP_8: rtn = SDLK_UP; break;
+            case SDLK_KP_9: rtn = SDLK_PAGEUP; break;
+        }
+    }
+    return rtn;
 }
 
 
-BOOL LLKeyboardSDL::handleKeyDown(const U16 key, const U32 mask)
+BOOL LLKeyboardSDL::handleKeyDown(const U32 key, const U32 mask)
 {
-	U16     adjusted_nativekey;
-	KEY	translated_key = 0;
-	U32	translated_mask = MASK_NONE;
-	BOOL	handled = FALSE;
+    U32 adjusted_nativekey;
+    KEY	translated_key = 0;
+    U32	translated_mask = MASK_NONE;
+    BOOL handled = FALSE;
+
+    adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
 
-	adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
+    translated_mask = updateModifiers(mask);
 
-	translated_mask = updateModifiers(mask);
-	
-	if(translateNumpadKey(adjusted_nativekey, &translated_key))
-	{
-		handled = handleTranslatedKeyDown(translated_key, translated_mask);
-	}
+    if(translateNumpadKey(adjusted_nativekey, &translated_key))
+    {
+        handled = handleTranslatedKeyDown(translated_key, translated_mask);
+    }
 
-	return handled;
+    return handled;
 }
 
 
-BOOL LLKeyboardSDL::handleKeyUp(const U16 key, const U32 mask)
+BOOL LLKeyboardSDL::handleKeyUp(const U32 key, const U32 mask)
 {
-	U16     adjusted_nativekey;
-	KEY	translated_key = 0;
-	U32	translated_mask = MASK_NONE;
-	BOOL	handled = FALSE;
+    U32 adjusted_nativekey;
+    KEY	translated_key = 0;
+    U32	translated_mask = MASK_NONE;
+    BOOL handled = FALSE;
 
-	adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
+    adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
 
-	translated_mask = updateModifiers(mask);
+    translated_mask = updateModifiers(mask);
 
-	if(translateNumpadKey(adjusted_nativekey, &translated_key))
-	{
-		handled = handleTranslatedKeyUp(translated_key, translated_mask);
-	}
+    if(translateNumpadKey(adjusted_nativekey, &translated_key))
+    {
+        handled = handleTranslatedKeyUp(translated_key, translated_mask);
+    }
 
-	return handled;
+    return handled;
 }
 
 MASK LLKeyboardSDL::currentMask(BOOL for_mouse_event)
 {
-	MASK result = MASK_NONE;
-	SDLMod mask = SDL_GetModState();
-
-	if (mask & KMOD_SHIFT)			result |= MASK_SHIFT;
-	if (mask & KMOD_CTRL)			result |= MASK_CONTROL;
-	if (mask & KMOD_ALT)			result |= MASK_ALT;
-
-	// For keyboard events, consider Meta keys equivalent to Control
-	if (!for_mouse_event)
-	{
-		if (mask & KMOD_META) result |= MASK_CONTROL;
-	}
-
-	return result;
+    MASK result = MASK_NONE;
+    SDL_Keymod mask = SDL_GetModState();
+
+    if (mask & KMOD_SHIFT)
+        result |= MASK_SHIFT;
+    if (mask & KMOD_CTRL)
+        result |= MASK_CONTROL;
+    if (mask & KMOD_ALT)
+        result |= MASK_ALT;
+
+    // For keyboard events, consider Meta keys equivalent to Control
+    if (!for_mouse_event)
+    {
+        if (mask & KMOD_GUI)
+            result |= MASK_CONTROL;
+    }
+
+    return result;
 }
 
 void LLKeyboardSDL::scanKeyboard()
 {
-	for (S32 key = 0; key < KEY_COUNT; key++)
-	{
-		// Generate callback if any event has occurred on this key this frame.
-		// Can't just test mKeyLevel, because this could be a slow frame and
-		// key might have gone down then up. JC
-		if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key])
-		{
-			mCurScanKey = key;
-			mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]);
-		}
-	}
-
-	// Reset edges for next frame
-	for (S32 key = 0; key < KEY_COUNT; key++)
-	{
-		mKeyUp[key] = FALSE;
-		mKeyDown[key] = FALSE;
-		if (mKeyLevel[key])
-		{
-			mKeyLevelFrameCount[key]++;
-		}
-	}
+    for (S32 key = 0; key < KEY_COUNT; key++)
+    {
+        // Generate callback if any event has occurred on this key this frame.
+        // Can't just test mKeyLevel, because this could be a slow frame and
+        // key might have gone down then up. JC
+        if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key])
+        {
+            mCurScanKey = key;
+            mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]);
+        }
+    }
+
+    // Reset edges for next frame
+    for (S32 key = 0; key < KEY_COUNT; key++)
+    {
+        mKeyUp[key] = FALSE;
+        mKeyDown[key] = FALSE;
+        if (mKeyLevel[key])
+        {
+            mKeyLevelFrameCount[key]++;
+        }
+    }
 }
 
- 
-BOOL LLKeyboardSDL::translateNumpadKey( const U16 os_key, KEY *translated_key)
+
+BOOL LLKeyboardSDL::translateNumpadKey( const U32 os_key, KEY *translated_key)
 {
-	return translateKey(os_key, translated_key);	
+    return translateKey(os_key, translated_key);
 }
 
 U16 LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key)
 {
-	return inverseTranslateKey(translated_key);
+    return inverseTranslateKey(translated_key);
 }
 
-#endif
-
+enum class WindowsVK : U32
+{
+    VK_UNKNOWN = 0,
+    VK_CANCEL = 0x03,
+    VK_BACK = 0x08,
+    VK_TAB = 0x09,
+    VK_CLEAR = 0x0C,
+    VK_RETURN = 0x0D,
+    VK_SHIFT = 0x10,
+    VK_CONTROL = 0x11,
+    VK_MENU = 0x12,
+    VK_PAUSE = 0x13,
+    VK_CAPITAL = 0x14,
+    VK_KANA = 0x15,
+    VK_HANGUL = 0x15,
+    VK_JUNJA = 0x17,
+    VK_FINAL = 0x18,
+    VK_HANJA = 0x19,
+    VK_KANJI = 0x19,
+    VK_ESCAPE = 0x1B,
+    VK_CONVERT = 0x1C,
+    VK_NONCONVERT = 0x1D,
+    VK_ACCEPT = 0x1E,
+    VK_MODECHANGE = 0x1F,
+    VK_SPACE = 0x20,
+    VK_PRIOR = 0x21,
+    VK_NEXT = 0x22,
+    VK_END = 0x23,
+    VK_HOME = 0x24,
+    VK_LEFT = 0x25,
+    VK_UP = 0x26,
+    VK_RIGHT = 0x27,
+    VK_DOWN = 0x28,
+    VK_SELECT = 0x29,
+    VK_PRINT = 0x2A,
+    VK_EXECUTE = 0x2B,
+    VK_SNAPSHOT = 0x2C,
+    VK_INSERT = 0x2D,
+    VK_DELETE = 0x2E,
+    VK_HELP = 0x2F,
+    VK_0 = 0x30,
+    VK_1 = 0x31,
+    VK_2 = 0x32,
+    VK_3 = 0x33,
+    VK_4 = 0x34,
+    VK_5 = 0x35,
+    VK_6 = 0x36,
+    VK_7 = 0x37,
+    VK_8 = 0x38,
+    VK_9 = 0x39,
+    VK_A = 0x41,
+    VK_B = 0x42,
+    VK_C = 0x43,
+    VK_D = 0x44,
+    VK_E = 0x45,
+    VK_F = 0x46,
+    VK_G = 0x47,
+    VK_H = 0x48,
+    VK_I = 0x49,
+    VK_J = 0x4A,
+    VK_K = 0x4B,
+    VK_L = 0x4C,
+    VK_M = 0x4D,
+    VK_N = 0x4E,
+    VK_O = 0x4F,
+    VK_P = 0x50,
+    VK_Q = 0x51,
+    VK_R = 0x52,
+    VK_S = 0x53,
+    VK_T = 0x54,
+    VK_U = 0x55,
+    VK_V = 0x56,
+    VK_W = 0x57,
+    VK_X = 0x58,
+    VK_Y = 0x59,
+    VK_Z = 0x5A,
+    VK_LWIN = 0x5B,
+    VK_RWIN = 0x5C,
+    VK_APPS = 0x5D,
+    VK_SLEEP = 0x5F,
+    VK_NUMPAD0 = 0x60,
+    VK_NUMPAD1 = 0x61,
+    VK_NUMPAD2 = 0x62,
+    VK_NUMPAD3 = 0x63,
+    VK_NUMPAD4 = 0x64,
+    VK_NUMPAD5 = 0x65,
+    VK_NUMPAD6 = 0x66,
+    VK_NUMPAD7 = 0x67,
+    VK_NUMPAD8 = 0x68,
+    VK_NUMPAD9 = 0x69,
+    VK_MULTIPLY = 0x6A,
+    VK_ADD = 0x6B,
+    VK_SEPARATOR = 0x6C,
+    VK_SUBTRACT = 0x6D,
+    VK_DECIMAL = 0x6E,
+    VK_DIVIDE = 0x6F,
+    VK_F1 = 0x70,
+    VK_F2 = 0x71,
+    VK_F3 = 0x72,
+    VK_F4 = 0x73,
+    VK_F5 = 0x74,
+    VK_F6 = 0x75,
+    VK_F7 = 0x76,
+    VK_F8 = 0x77,
+    VK_F9 = 0x78,
+    VK_F10 = 0x79,
+    VK_F11 = 0x7A,
+    VK_F12 = 0x7B,
+    VK_F13 = 0x7C,
+    VK_F14 = 0x7D,
+    VK_F15 = 0x7E,
+    VK_F16 = 0x7F,
+    VK_F17 = 0x80,
+    VK_F18 = 0x81,
+    VK_F19 = 0x82,
+    VK_F20 = 0x83,
+    VK_F21 = 0x84,
+    VK_F22 = 0x85,
+    VK_F23 = 0x86,
+    VK_F24 = 0x87,
+    VK_NUMLOCK = 0x90,
+    VK_SCROLL = 0x91,
+    VK_LSHIFT = 0xA0,
+    VK_RSHIFT = 0xA1,
+    VK_LCONTROL = 0xA2,
+    VK_RCONTROL = 0xA3,
+    VK_LMENU = 0xA4,
+    VK_RMENU = 0xA5,
+    VK_BROWSER_BACK = 0xA6,
+    VK_BROWSER_FORWARD = 0xA7,
+    VK_BROWSER_REFRESH = 0xA8,
+    VK_BROWSER_STOP = 0xA9,
+    VK_BROWSER_SEARCH = 0xAA,
+    VK_BROWSER_FAVORITES = 0xAB,
+    VK_BROWSER_HOME = 0xAC,
+    VK_VOLUME_MUTE = 0xAD,
+    VK_VOLUME_DOWN = 0xAE,
+    VK_VOLUME_UP = 0xAF,
+    VK_MEDIA_NEXT_TRACK = 0xB0,
+    VK_MEDIA_PREV_TRACK = 0xB1,
+    VK_MEDIA_STOP = 0xB2,
+    VK_MEDIA_PLAY_PAUSE = 0xB3,
+    VK_MEDIA_LAUNCH_MAIL = 0xB4,
+    VK_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5,
+    VK_MEDIA_LAUNCH_APP1 = 0xB6,
+    VK_MEDIA_LAUNCH_APP2 = 0xB7,
+    VK_OEM_1 = 0xBA,
+    VK_OEM_PLUS = 0xBB,
+    VK_OEM_COMMA = 0xBC,
+    VK_OEM_MINUS = 0xBD,
+    VK_OEM_PERIOD = 0xBE,
+    VK_OEM_2 = 0xBF,
+    VK_OEM_3 = 0xC0,
+    VK_OEM_4 = 0xDB,
+    VK_OEM_5 = 0xDC,
+    VK_OEM_6 = 0xDD,
+    VK_OEM_7 = 0xDE,
+    VK_OEM_8 = 0xDF,
+    VK_OEM_102 = 0xE2,
+    VK_PROCESSKEY = 0xE5,
+    VK_PACKET = 0xE7,
+    VK_ATTN = 0xF6,
+    VK_CRSEL = 0xF7,
+    VK_EXSEL = 0xF8,
+    VK_EREOF = 0xF9,
+    VK_PLAY = 0xFA,
+    VK_ZOOM = 0xFB,
+    VK_NONAME = 0xFC,
+    VK_PA1 = 0xFD,
+    VK_OEM_CLEAR = 0xFE,
+};
+
+std::map< U32, U32 > mSDL2_to_Win;
+std::set< U32 > mIgnoreSDL2Keys;
+
+U32 LLKeyboardSDL::mapSDL2toWin( U32 aSymbol )
+{
+    // <FS:ND> Map SDLK_ virtual keys to Windows VK_ virtual keys.
+    // Text is handled via unicode input (SDL_TEXTINPUT event) and does not need to be translated into VK_ values as those match already.
+    if( mSDL2_to_Win.empty() )
+    {
+
+        mSDL2_to_Win[ SDLK_BACKSPACE ] = (U32)WindowsVK::VK_BACK;
+        mSDL2_to_Win[ SDLK_TAB ] = (U32)WindowsVK::VK_TAB;
+        mSDL2_to_Win[ 12 ] = (U32)WindowsVK::VK_CLEAR;
+        mSDL2_to_Win[ SDLK_RETURN ] = (U32)WindowsVK::VK_RETURN;
+        mSDL2_to_Win[ 19 ] = (U32)WindowsVK::VK_PAUSE;
+        mSDL2_to_Win[ SDLK_ESCAPE ] = (U32)WindowsVK::VK_ESCAPE;
+        mSDL2_to_Win[ SDLK_SPACE ] = (U32)WindowsVK::VK_SPACE;
+        mSDL2_to_Win[ SDLK_QUOTE ] = (U32)WindowsVK::VK_OEM_7;
+        mSDL2_to_Win[ SDLK_COMMA ] = (U32)WindowsVK::VK_OEM_COMMA;
+        mSDL2_to_Win[ SDLK_MINUS ] = (U32)WindowsVK::VK_OEM_MINUS;
+        mSDL2_to_Win[ SDLK_PERIOD ] = (U32)WindowsVK::VK_OEM_PERIOD;
+        mSDL2_to_Win[ SDLK_SLASH ] = (U32)WindowsVK::VK_OEM_2;
+
+        mSDL2_to_Win[ SDLK_0 ] = (U32)WindowsVK::VK_0;
+        mSDL2_to_Win[ SDLK_1 ] = (U32)WindowsVK::VK_1;
+        mSDL2_to_Win[ SDLK_2 ] = (U32)WindowsVK::VK_2;
+        mSDL2_to_Win[ SDLK_3 ] = (U32)WindowsVK::VK_3;
+        mSDL2_to_Win[ SDLK_4 ] = (U32)WindowsVK::VK_4;
+        mSDL2_to_Win[ SDLK_5 ] = (U32)WindowsVK::VK_5;
+        mSDL2_to_Win[ SDLK_6 ] = (U32)WindowsVK::VK_6;
+        mSDL2_to_Win[ SDLK_7 ] = (U32)WindowsVK::VK_7;
+        mSDL2_to_Win[ SDLK_8 ] = (U32)WindowsVK::VK_8;
+        mSDL2_to_Win[ SDLK_9 ] = (U32)WindowsVK::VK_9;
+
+        mSDL2_to_Win[ SDLK_SEMICOLON ] = (U32)WindowsVK::VK_OEM_1;
+        mSDL2_to_Win[ SDLK_LESS ] = (U32)WindowsVK::VK_OEM_102;
+        mSDL2_to_Win[ SDLK_EQUALS ] = (U32)WindowsVK::VK_OEM_PLUS;
+        mSDL2_to_Win[ SDLK_KP_EQUALS ] = (U32)WindowsVK::VK_OEM_PLUS;
+
+        mSDL2_to_Win[ SDLK_LEFTBRACKET ] = (U32)WindowsVK::VK_OEM_4;
+        mSDL2_to_Win[ SDLK_BACKSLASH ] = (U32)WindowsVK::VK_OEM_5;
+        mSDL2_to_Win[ SDLK_RIGHTBRACKET ] = (U32)WindowsVK::VK_OEM_6;
+        mSDL2_to_Win[ SDLK_BACKQUOTE ] = (U32)WindowsVK::VK_OEM_8;
+
+        mSDL2_to_Win[ SDLK_a ] = (U32)WindowsVK::VK_A;
+        mSDL2_to_Win[ SDLK_b ] = (U32)WindowsVK::VK_B;
+        mSDL2_to_Win[ SDLK_c ] = (U32)WindowsVK::VK_C;
+        mSDL2_to_Win[ SDLK_d ] = (U32)WindowsVK::VK_D;
+        mSDL2_to_Win[ SDLK_e ] = (U32)WindowsVK::VK_E;
+        mSDL2_to_Win[ SDLK_f ] = (U32)WindowsVK::VK_F;
+        mSDL2_to_Win[ SDLK_g ] = (U32)WindowsVK::VK_G;
+        mSDL2_to_Win[ SDLK_h ] = (U32)WindowsVK::VK_H;
+        mSDL2_to_Win[ SDLK_i ] = (U32)WindowsVK::VK_I;
+        mSDL2_to_Win[ SDLK_j ] = (U32)WindowsVK::VK_J;
+        mSDL2_to_Win[ SDLK_k ] = (U32)WindowsVK::VK_K;
+        mSDL2_to_Win[ SDLK_l ] = (U32)WindowsVK::VK_L;
+        mSDL2_to_Win[ SDLK_m ] = (U32)WindowsVK::VK_M;
+        mSDL2_to_Win[ SDLK_n ] = (U32)WindowsVK::VK_N;
+        mSDL2_to_Win[ SDLK_o ] = (U32)WindowsVK::VK_O;
+        mSDL2_to_Win[ SDLK_p ] = (U32)WindowsVK::VK_P;
+        mSDL2_to_Win[ SDLK_q ] = (U32)WindowsVK::VK_Q;
+        mSDL2_to_Win[ SDLK_r ] = (U32)WindowsVK::VK_R;
+        mSDL2_to_Win[ SDLK_s ] = (U32)WindowsVK::VK_S;
+        mSDL2_to_Win[ SDLK_t ] = (U32)WindowsVK::VK_T;
+        mSDL2_to_Win[ SDLK_u ] = (U32)WindowsVK::VK_U;
+        mSDL2_to_Win[ SDLK_v ] = (U32)WindowsVK::VK_V;
+        mSDL2_to_Win[ SDLK_w ] = (U32)WindowsVK::VK_W;
+        mSDL2_to_Win[ SDLK_x ] = (U32)WindowsVK::VK_X;
+        mSDL2_to_Win[ SDLK_y ] = (U32)WindowsVK::VK_Y;
+        mSDL2_to_Win[ SDLK_z ] = (U32)WindowsVK::VK_Z;
+
+        mSDL2_to_Win[ SDLK_DELETE ] = (U32)WindowsVK::VK_DELETE;
+
+
+        mSDL2_to_Win[ SDLK_NUMLOCKCLEAR ] = (U32)WindowsVK::VK_NUMLOCK;
+        mSDL2_to_Win[ SDLK_SCROLLLOCK ] = (U32)WindowsVK::VK_SCROLL;
+
+        mSDL2_to_Win[ SDLK_HELP ] = (U32)WindowsVK::VK_HELP;
+        mSDL2_to_Win[ SDLK_PRINTSCREEN ] = (U32)WindowsVK::VK_SNAPSHOT;
+        mSDL2_to_Win[ SDLK_CANCEL ] = (U32)WindowsVK::VK_CANCEL;
+        mSDL2_to_Win[ SDLK_APPLICATION ] = (U32)WindowsVK::VK_APPS;
+
+        mSDL2_to_Win[ SDLK_UNKNOWN    ] = (U32)WindowsVK::VK_UNKNOWN;
+        mSDL2_to_Win[ SDLK_BACKSPACE  ] = (U32)WindowsVK::VK_BACK;
+        mSDL2_to_Win[ SDLK_TAB        ] = (U32)WindowsVK::VK_TAB;
+        mSDL2_to_Win[ SDLK_CLEAR      ] = (U32)WindowsVK::VK_CLEAR;
+        mSDL2_to_Win[ SDLK_RETURN     ] = (U32)WindowsVK::VK_RETURN;
+        mSDL2_to_Win[ SDLK_PAUSE      ] = (U32)WindowsVK::VK_PAUSE;
+        mSDL2_to_Win[ SDLK_ESCAPE     ] = (U32)WindowsVK::VK_ESCAPE;
+        mSDL2_to_Win[ SDLK_DELETE     ] = (U32)WindowsVK::VK_DELETE;
+
+        mSDL2_to_Win[ SDLK_KP_PERIOD  ] = (U32)WindowsVK::VK_OEM_PERIOD; // VK_DECIMAL?
+        mSDL2_to_Win[ SDLK_KP_DIVIDE  ] = (U32)WindowsVK::VK_DIVIDE;
+        mSDL2_to_Win[ SDLK_KP_MULTIPLY] = (U32)WindowsVK::VK_MULTIPLY;
+        mSDL2_to_Win[ SDLK_KP_MINUS   ] = (U32)WindowsVK::VK_OEM_MINUS; // VK_SUBSTRACT?
+        mSDL2_to_Win[ SDLK_KP_PLUS    ] = (U32)WindowsVK::VK_OEM_PLUS;  // VK_ADD?
+        mSDL2_to_Win[ SDLK_KP_ENTER   ] = (U32)WindowsVK::VK_RETURN;
+        mSDL2_to_Win[ SDLK_KP_0 ] = (U32)WindowsVK::VK_NUMPAD0;
+        mSDL2_to_Win[ SDLK_KP_1 ] = (U32)WindowsVK::VK_NUMPAD1;
+        mSDL2_to_Win[ SDLK_KP_2 ] = (U32)WindowsVK::VK_NUMPAD2;
+        mSDL2_to_Win[ SDLK_KP_3 ] = (U32)WindowsVK::VK_NUMPAD3;
+        mSDL2_to_Win[ SDLK_KP_4 ] = (U32)WindowsVK::VK_NUMPAD4;
+        mSDL2_to_Win[ SDLK_KP_5 ] = (U32)WindowsVK::VK_NUMPAD5;
+        mSDL2_to_Win[ SDLK_KP_6 ] = (U32)WindowsVK::VK_NUMPAD6;
+        mSDL2_to_Win[ SDLK_KP_7 ] = (U32)WindowsVK::VK_NUMPAD7;
+        mSDL2_to_Win[ SDLK_KP_8 ] = (U32)WindowsVK::VK_NUMPAD8;
+        mSDL2_to_Win[ SDLK_KP_9 ] = (U32)WindowsVK::VK_NUMPAD9;
+
+        // ?
+
+        mSDL2_to_Win[ SDLK_UP         ] = (U32)WindowsVK::VK_UP;
+        mSDL2_to_Win[ SDLK_DOWN       ] = (U32)WindowsVK::VK_DOWN;
+        mSDL2_to_Win[ SDLK_RIGHT      ] = (U32)WindowsVK::VK_RIGHT;
+        mSDL2_to_Win[ SDLK_LEFT       ] = (U32)WindowsVK::VK_LEFT;
+        mSDL2_to_Win[ SDLK_INSERT     ] = (U32)WindowsVK::VK_INSERT;
+        mSDL2_to_Win[ SDLK_HOME       ] = (U32)WindowsVK::VK_HOME;
+        mSDL2_to_Win[ SDLK_END        ] = (U32)WindowsVK::VK_END;
+        mSDL2_to_Win[ SDLK_PAGEUP     ] = (U32)WindowsVK::VK_PRIOR;
+        mSDL2_to_Win[ SDLK_PAGEDOWN   ] = (U32)WindowsVK::VK_NEXT;
+        mSDL2_to_Win[ SDLK_F1         ] = (U32)WindowsVK::VK_F1;
+        mSDL2_to_Win[ SDLK_F2         ] = (U32)WindowsVK::VK_F2;
+        mSDL2_to_Win[ SDLK_F3         ] = (U32)WindowsVK::VK_F3;
+        mSDL2_to_Win[ SDLK_F4         ] = (U32)WindowsVK::VK_F4;
+        mSDL2_to_Win[ SDLK_F5         ] = (U32)WindowsVK::VK_F5;
+        mSDL2_to_Win[ SDLK_F6         ] = (U32)WindowsVK::VK_F6;
+        mSDL2_to_Win[ SDLK_F7         ] = (U32)WindowsVK::VK_F7;
+        mSDL2_to_Win[ SDLK_F8         ] = (U32)WindowsVK::VK_F8;
+        mSDL2_to_Win[ SDLK_F9         ] = (U32)WindowsVK::VK_F9;
+        mSDL2_to_Win[ SDLK_F10        ] = (U32)WindowsVK::VK_F10;
+        mSDL2_to_Win[ SDLK_F11        ] = (U32)WindowsVK::VK_F11;
+        mSDL2_to_Win[ SDLK_F12        ] = (U32)WindowsVK::VK_F12;
+        mSDL2_to_Win[ SDLK_F13        ] = (U32)WindowsVK::VK_F13;
+        mSDL2_to_Win[ SDLK_F14        ] = (U32)WindowsVK::VK_F14;
+        mSDL2_to_Win[ SDLK_F15        ] = (U32)WindowsVK::VK_F15;
+        mSDL2_to_Win[ SDLK_CAPSLOCK   ] = (U32)WindowsVK::VK_CAPITAL;
+        mSDL2_to_Win[ SDLK_RSHIFT     ] = (U32)WindowsVK::VK_SHIFT;
+        mSDL2_to_Win[ SDLK_LSHIFT     ] = (U32)WindowsVK::VK_SHIFT;
+        mSDL2_to_Win[ SDLK_RCTRL      ] = (U32)WindowsVK::VK_CONTROL;
+        mSDL2_to_Win[ SDLK_LCTRL      ] = (U32)WindowsVK::VK_CONTROL;
+        mSDL2_to_Win[ SDLK_RALT       ] = (U32)WindowsVK::VK_MENU;
+        mSDL2_to_Win[ SDLK_LALT       ] = (U32)WindowsVK::VK_MENU;
+
+        mSDL2_to_Win[ SDLK_MENU       ] = (U32)WindowsVK::VK_MENU;
+
+        // VK_MODECHANGE ?
+        // mSDL2_to_Win[ SDLK_MODE       ] = (U32)WindowsVK::VK_MODE;
+
+        // ?
+        // mSDL2_to_Win[ SDLK_SYSREQ     ] = (U32)WindowsVK::VK_SYSREQ;
+        // mSDL2_to_Win[ SDLK_POWER      ] = (U32)WindowsVK::VK_POWER;
+        // mSDL2_to_Win[ SDLK_UNDO       ] = (U32)WindowsVK::VK_UNDO;
+        // mSDL2_to_Win[ SDLK_KP_EQUALS  ] = (U32)WindowsVK::VK_EQUALS;
+        // mSDL2_to_Win[ 311 ] = (U32)WindowsVK::VK_LWIN;
+        // mSDL2_to_Win[ 312 ] = (U32)WindowsVK::VK_RWIN;
+        // mSDL2_to_Win[ SDLK_COLON ] = ?
+    }
+
+    auto itr = mSDL2_to_Win.find( aSymbol );
+    if( itr != mSDL2_to_Win.end() )
+        return itr->second;
+
+    return aSymbol;
+}
diff --git a/indra/llwindow/llkeyboardsdl.h b/indra/llwindow/llkeyboardsdl.h
index 02a71425f1..4453e15adc 100644
--- a/indra/llwindow/llkeyboardsdl.h
+++ b/indra/llwindow/llkeyboardsdl.h
@@ -1,55 +1,57 @@
-/** 
- * @file llkeyboardsdl.h
- * @brief Handler for assignable key bindings
+/**
+ * @author This module has many fathers, and it shows.
  *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
 
-#ifndef LL_LLKEYBOARDSDL_H
-#define LL_LLKEYBOARDSDL_H
+#ifndef LL_LLKEYBOARDSDL2_H
+#define LL_LLKEYBOARDSDL2_H
 
 #include "llkeyboard.h"
-#include "SDL/SDL.h"
+#include "SDL2/SDL.h"
 
 class LLKeyboardSDL : public LLKeyboard
 {
 public:
-	LLKeyboardSDL();
-	/*virtual*/ ~LLKeyboardSDL() {};
+    LLKeyboardSDL();
+    /*virtual*/ ~LLKeyboardSDL() {};
 
-	/*virtual*/ BOOL	handleKeyUp(const U16 key, MASK mask);
-	/*virtual*/ BOOL	handleKeyDown(const U16 key, MASK mask);
-	/*virtual*/ void	resetMaskKeys();
-	/*virtual*/ MASK	currentMask(BOOL for_mouse_event);
-	/*virtual*/ void	scanKeyboard();
+    /*virtual*/ BOOL	handleKeyUp(const U32 key, MASK mask);
+    /*virtual*/ BOOL	handleKeyDown(const U32 key, MASK mask);
+    /*virtual*/ void	resetMaskKeys();
+    /*virtual*/ MASK	currentMask(BOOL for_mouse_event);
+    /*virtual*/ void	scanKeyboard();
 
 protected:
-	MASK	updateModifiers(const U32 mask);
-	void	setModifierKeyLevel( KEY key, BOOL new_state );
-	BOOL	translateNumpadKey( const U16 os_key, KEY *translated_key );
-	U16	inverseTranslateNumpadKey(const KEY translated_key);
+    MASK	updateModifiers(const U32 mask);
+    void	setModifierKeyLevel( KEY key, BOOL new_state );
+    BOOL	translateNumpadKey( const U32 os_key, KEY *translated_key );
+    U16	inverseTranslateNumpadKey(const KEY translated_key);
 private:
-	std::map<U16, KEY> mTranslateNumpadMap;  // special map for translating OS keys to numpad keys
-	std::map<KEY, U16> mInvTranslateNumpadMap; // inverse of the above
+    std::map<U32, KEY> mTranslateNumpadMap;  // special map for translating OS keys to numpad keys
+    std::map<KEY, U32> mInvTranslateNumpadMap; // inverse of the above
+
+public:
+    static U32 mapSDL2toWin( U32 );
 };
 
 #endif
diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index 7ea87f5884..b8b502508b 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -1,4 +1,4 @@
-/** 
+/**
  * @file llwindowsdl.cpp
  * @brief SDL implementation of LLWindow class
  * @author This module has many fathers, and it shows.
@@ -6,27 +6,25 @@
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
 
-#if LL_SDL
-
 #include "linden_common.h"
 
 #include "llwindowsdl.h"
@@ -40,12 +38,9 @@
 #include "lldir.h"
 #include "llfindlocale.h"
 
-#if LL_GTK
-extern "C" {
-# include "gtk/gtk.h"
-}
-#include <locale.h>
-#endif // LL_GTK
+#ifdef LL_GLIB
+#include <glib.h>
+#endif
 
 extern "C" {
 # include "fontconfig/fontconfig.h"
@@ -57,6 +52,7 @@ extern "C" {
 # include <unistd.h>
 # include <sys/types.h>
 # include <sys/wait.h>
+# include <stdio.h>
 #endif // LL_LINUX
 
 extern BOOL gDebugWindowProc;
@@ -64,7 +60,7 @@ extern BOOL gDebugWindowProc;
 const S32 MAX_NUM_RESOLUTIONS = 200;
 
 // static variable for ATI mouse cursor crash work-around:
-static bool ATIbug = false; 
+static bool ATIbug = false;
 
 //
 // LLWindowSDL
@@ -83,188 +79,360 @@ static LLWindowSDL *gWindowImplementation = NULL;
 
 void maybe_lock_display(void)
 {
-	if (gWindowImplementation && gWindowImplementation->Lock_Display) {
-		gWindowImplementation->Lock_Display();
-	}
+    if (gWindowImplementation && gWindowImplementation->Lock_Display) {
+        gWindowImplementation->Lock_Display();
+    }
 }
 
 
 void maybe_unlock_display(void)
 {
-	if (gWindowImplementation && gWindowImplementation->Unlock_Display) {
-		gWindowImplementation->Unlock_Display();
-	}
+    if (gWindowImplementation && gWindowImplementation->Unlock_Display) {
+        gWindowImplementation->Unlock_Display();
+    }
 }
 
 
-#if LL_GTK
-// Lazily initialize and check the runtime GTK version for goodness.
-// static
-bool LLWindowSDL::ll_try_gtk_init(void)
-{
-	static BOOL done_gtk_diag = FALSE;
-	static BOOL gtk_is_good = FALSE;
-	static BOOL done_setlocale = FALSE;
-	static BOOL tried_gtk_init = FALSE;
-
-	if (!done_setlocale)
-	{
-		LL_INFOS() << "Starting GTK Initialization." << LL_ENDL;
-		maybe_lock_display();
-		gtk_disable_setlocale();
-		maybe_unlock_display();
-		done_setlocale = TRUE;
-	}
-	
-	if (!tried_gtk_init)
-	{
-		tried_gtk_init = TRUE;
-		if (!g_thread_supported ()) g_thread_init (NULL);
-		maybe_lock_display();
-		gtk_is_good = gtk_init_check(NULL, NULL);
-		maybe_unlock_display();
-		if (!gtk_is_good)
-			LL_WARNS() << "GTK Initialization failed." << LL_ENDL;
-	}
-
-	if (gtk_is_good && !done_gtk_diag)
-	{
-		LL_INFOS() << "GTK Initialized." << LL_ENDL;
-		LL_INFOS() << "- Compiled against GTK version "
-			<< GTK_MAJOR_VERSION << "."
-			<< GTK_MINOR_VERSION << "."
-			<< GTK_MICRO_VERSION << LL_ENDL;
-		LL_INFOS() << "- Running against GTK version "
-			<< gtk_major_version << "."
-			<< gtk_minor_version << "."
-			<< gtk_micro_version << LL_ENDL;
-		maybe_lock_display();
-		const gchar* gtk_warning = gtk_check_version(
-			GTK_MAJOR_VERSION,
-			GTK_MINOR_VERSION,
-			GTK_MICRO_VERSION);
-		maybe_unlock_display();
-		if (gtk_warning)
-		{
-			LL_WARNS() << "- GTK COMPATIBILITY WARNING: " <<
-				gtk_warning << LL_ENDL;
-			gtk_is_good = FALSE;
-		} else {
-			LL_INFOS() << "- GTK version is good." << LL_ENDL;
-		}
-
-		done_gtk_diag = TRUE;
-	}
-
-	return gtk_is_good;
-}
-#endif // LL_GTK
-
-
 #if LL_X11
 // static
 Window LLWindowSDL::get_SDL_XWindowID(void)
 {
-	if (gWindowImplementation) {
-		return gWindowImplementation->mSDL_XWindowID;
-	}
-	return None;
+    if (gWindowImplementation) {
+        return gWindowImplementation->mSDL_XWindowID;
+    }
+    return None;
 }
 
 //static
 Display* LLWindowSDL::get_SDL_Display(void)
 {
-	if (gWindowImplementation) {
-		return gWindowImplementation->mSDL_Display;
-	}
-	return NULL;
+    if (gWindowImplementation) {
+        return gWindowImplementation->mSDL_Display;
+    }
+    return NULL;
 }
 #endif // LL_X11
 
+#if LL_X11
+
+// Clipboard handing via native X11, base on the implementation in Cool VL by Henri Beauchamp
+
+namespace
+{
+    std::array<Atom, 3> gSupportedAtoms;
+
+    Atom XA_CLIPBOARD;
+    Atom XA_TARGETS;
+    Atom PVT_PASTE_BUFFER;
+    long const MAX_PASTE_BUFFER_SIZE = 16383;
+
+    void filterSelectionRequest( XEvent aEvent )
+    {
+        auto *display = LLWindowSDL::getSDLDisplay();
+        auto &request = aEvent.xselectionrequest;
+
+        XSelectionEvent reply { SelectionNotify, aEvent.xany.serial, aEvent.xany.send_event, display,
+                                request.requestor, request.selection, request.target,
+                                request.property,request.time };
+
+        if (request.target == XA_TARGETS)
+        {
+            XChangeProperty(display, request.requestor, request.property,
+                            XA_ATOM, 32, PropModeReplace,
+                            (unsigned char *) &gSupportedAtoms.front(), gSupportedAtoms.size());
+        }
+        else if (std::find(gSupportedAtoms.begin(), gSupportedAtoms.end(), request.target) !=
+                 gSupportedAtoms.end())
+        {
+            std::string utf8;
+            if (request.selection == XA_PRIMARY)
+                utf8 = wstring_to_utf8str(gWindowImplementation->getPrimaryText());
+            else
+                utf8 = wstring_to_utf8str(gWindowImplementation->getSecondaryText());
+
+            XChangeProperty(display, request.requestor, request.property,
+                            request.target, 8, PropModeReplace,
+                            (unsigned char *) utf8.c_str(), utf8.length());
+        }
+        else if (request.selection == XA_CLIPBOARD)
+        {
+            // Did not have what they wanted, so no property set
+            reply.property = None;
+        }
+        else
+            return;
+
+        XSendEvent(request.display, request.requestor, False, NoEventMask, (XEvent *) &reply);
+        XSync(display, False);
+    }
+
+    void filterSelectionClearRequest( XEvent aEvent )
+    {
+        auto &request = aEvent.xselectionrequest;
+        if (request.selection == XA_PRIMARY)
+            gWindowImplementation->clearPrimaryText();
+        else if (request.selection == XA_CLIPBOARD)
+            gWindowImplementation->clearSecondaryText();
+    }
+
+    int x11_clipboard_filter(void*, SDL_Event *evt)
+    {
+        Display *display = LLWindowSDL::getSDLDisplay();
+        if (!display)
+            return 1;
+
+        if (evt->type != SDL_SYSWMEVENT)
+            return 1;
+
+        auto xevent = evt->syswm.msg->msg.x11.event;
+
+        if (xevent.type == SelectionRequest)
+            filterSelectionRequest( xevent );
+        else if (xevent.type == SelectionClear)
+            filterSelectionClearRequest( xevent );
+        return 1;
+    }
+
+    bool grab_property(Display* display, Window window, Atom selection, Atom target)
+    {
+        if( !display )
+            return false;
+
+        maybe_lock_display();
+
+        XDeleteProperty(display, window, PVT_PASTE_BUFFER);
+        XFlush(display);
+
+        XConvertSelection(display, selection, target, PVT_PASTE_BUFFER, window,  CurrentTime);
+
+        // Unlock the connection so that the SDL event loop may function
+        maybe_unlock_display();
+
+        const auto start{ SDL_GetTicks() };
+        const auto end{ start + 1000 };
+
+        XEvent xevent {};
+        bool response = false;
+
+        do
+        {
+            SDL_Event event {};
+
+            // Wait for an event
+            SDL_WaitEvent(&event);
+
+            // If the event is a window manager event
+            if (event.type == SDL_SYSWMEVENT)
+            {
+                xevent = event.syswm.msg->msg.x11.event;
+
+                if (xevent.type == SelectionNotify && xevent.xselection.requestor == window)
+                    response = true;
+            }
+        } while (!response && SDL_GetTicks() < end );
+
+        return response && xevent.xselection.property != None;
+    }
+}
+
+void LLWindowSDL::initialiseX11Clipboard()
+{
+    if (!mSDL_Display)
+        return;
+
+    SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
+    SDL_SetEventFilter(x11_clipboard_filter, nullptr);
+
+    maybe_lock_display();
+
+    XA_CLIPBOARD = XInternAtom(mSDL_Display, "CLIPBOARD", False);
+
+    gSupportedAtoms[0] = XInternAtom(mSDL_Display, "UTF8_STRING", False);
+    gSupportedAtoms[1] = XInternAtom(mSDL_Display, "COMPOUND_TEXT", False);
+    gSupportedAtoms[2] = XA_STRING;
+
+    // TARGETS atom
+    XA_TARGETS = XInternAtom(mSDL_Display, "TARGETS", False);
+
+    // SL_PASTE_BUFFER atom
+    PVT_PASTE_BUFFER = XInternAtom(mSDL_Display, "FS_PASTE_BUFFER", False);
+
+    maybe_unlock_display();
+}
+
+bool LLWindowSDL::getSelectionText( Atom aSelection, Atom aType, LLWString &text )
+{
+    if( !mSDL_Display )
+        return false;
+
+    if( !grab_property(mSDL_Display, mSDL_XWindowID, aSelection,aType ) )
+        return false;
+
+    maybe_lock_display();
+
+    Atom type;
+    int format{};
+    unsigned long len{},remaining {};
+    unsigned char* data = nullptr;
+    int res = XGetWindowProperty(mSDL_Display, mSDL_XWindowID,
+                                 PVT_PASTE_BUFFER, 0, MAX_PASTE_BUFFER_SIZE, False,
+                                 AnyPropertyType, &type, &format, &len,
+                                 &remaining, &data);
+    if (data && len)
+    {
+        text = LLWString(
+                utf8str_to_wstring(reinterpret_cast< char const *>( data ) )
+        );
+        XFree(data);
+    }
+
+    maybe_unlock_display();
+    return res == Success;
+}
+
+bool LLWindowSDL::getSelectionText(Atom selection, LLWString& text)
+{
+    if (!mSDL_Display)
+        return false;
+
+    maybe_lock_display();
+
+    Window owner = XGetSelectionOwner(mSDL_Display, selection);
+    if (owner == None)
+    {
+        if (selection == XA_PRIMARY)
+        {
+            owner = DefaultRootWindow(mSDL_Display);
+            selection = XA_CUT_BUFFER0;
+        }
+        else
+        {
+            maybe_unlock_display();
+            return false;
+        }
+    }
+
+    maybe_unlock_display();
+
+    for( Atom atom : gSupportedAtoms )
+    {
+        if(getSelectionText(selection, atom, text ) )
+            return true;
+    }
+
+    return false;
+}
+
+bool LLWindowSDL::setSelectionText(Atom selection, const LLWString& text)
+{
+    maybe_lock_display();
+
+    if (selection == XA_PRIMARY)
+    {
+        std::string utf8 = wstring_to_utf8str(text);
+        XStoreBytes(mSDL_Display, utf8.c_str(), utf8.length() + 1);
+        mPrimaryClipboard = text;
+    }
+    else
+        mSecondaryClipboard = text;
+
+    XSetSelectionOwner(mSDL_Display, selection, mSDL_XWindowID, CurrentTime);
+
+    auto owner = XGetSelectionOwner(mSDL_Display, selection);
+
+    maybe_unlock_display();
+
+    return owner == mSDL_XWindowID;
+}
+
+Display* LLWindowSDL::getSDLDisplay()
+{
+    if (gWindowImplementation)
+        return gWindowImplementation->mSDL_Display;
+    return nullptr;
+}
+
+#endif
+
 
 LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
-			 const std::string& title, S32 x, S32 y, S32 width,
-			 S32 height, U32 flags,
-			 BOOL fullscreen, BOOL clearBg,
-			 BOOL disable_vsync, BOOL use_gl,
-			 BOOL ignore_pixel_depth, U32 fsaa_samples)
-	: LLWindow(callbacks, fullscreen, flags),
-	  Lock_Display(NULL),
-	  Unlock_Display(NULL), mGamma(1.0f)
-{
-	// Initialize the keyboard
-	gKeyboard = new LLKeyboardSDL();
-	gKeyboard->setCallbacks(callbacks);
-	// Note that we can't set up key-repeat until after SDL has init'd video
-
-	// Ignore use_gl for now, only used for drones on PC
-	mWindow = NULL;
-	mNeedsResize = FALSE;
-	mOverrideAspectRatio = 0.f;
-	mGrabbyKeyFlags = 0;
-	mReallyCapturedCount = 0;
-	mHaveInputFocus = -1;
-	mIsMinimized = -1;
-	mFSAASamples = fsaa_samples;
+                         const std::string& title, S32 x, S32 y, S32 width,
+                         S32 height, U32 flags,
+                         BOOL fullscreen, BOOL clearBg,
+                         BOOL disable_vsync, BOOL use_gl,
+                         BOOL ignore_pixel_depth, U32 fsaa_samples)
+        : LLWindow(callbacks, fullscreen, flags),
+        Lock_Display(NULL),
+        //Unlock_Display(NULL), mGamma(1.0f)
+        Unlock_Display(NULL), mGamma(1.0f)
+{
+    // Initialize the keyboard
+    gKeyboard = new LLKeyboardSDL();
+    gKeyboard->setCallbacks(callbacks);
+    // Note that we can't set up key-repeat until after SDL has init'd video
+
+    // Ignore use_gl for now, only used for drones on PC
+    mWindow = NULL;
+    mContext = {};
+    mNeedsResize = FALSE;
+    mOverrideAspectRatio = 0.f;
+    mGrabbyKeyFlags = 0;
+    mReallyCapturedCount = 0;
+    mHaveInputFocus = -1;
+    mIsMinimized = -1;
+    mFSAASamples = fsaa_samples;
 
 #if LL_X11
-	mSDL_XWindowID = None;
-	mSDL_Display = NULL;
+    mSDL_XWindowID = None;
+    mSDL_Display = NULL;
 #endif // LL_X11
 
-#if LL_GTK
-	// We MUST be the first to initialize GTK so that GTK doesn't get badly
-	// initialized with a non-C locale and cause lots of serious random
-	// weirdness.
-	ll_try_gtk_init();
-#endif // LL_GTK
+    // Assume 4:3 aspect ratio until we know better
+    mOriginalAspectRatio = 1024.0 / 768.0;
 
-	// Assume 4:3 aspect ratio until we know better
-	mOriginalAspectRatio = 1024.0 / 768.0;
+    if (title.empty())
+        mWindowTitle = "SDL Window";  // *FIX: (?)
+    else
+        mWindowTitle = title;
 
-	if (title.empty())
-		mWindowTitle = "SDL Window";  // *FIX: (?)
-	else
-		mWindowTitle = title;
-
-	// Create the GL context and set it up for windowed or fullscreen, as appropriate.
-	if(createContext(x, y, width, height, 32, fullscreen, disable_vsync))
-	{
-		gGLManager.initGL();
+    // Create the GL context and set it up for windowed or fullscreen, as appropriate.
+    if(createContext(x, y, width, height, 32, fullscreen, disable_vsync))
+    {
+        gGLManager.initGL();
 
-		//start with arrow cursor
-		initCursors();
-		setCursor( UI_CURSOR_ARROW );
-	}
+        //start with arrow cursor
+        initCursors();
+        setCursor( UI_CURSOR_ARROW );
+    }
 
-	stop_glerror();
+    stop_glerror();
 
-	// Stash an object pointer for OSMessageBox()
-	gWindowImplementation = this;
+    // Stash an object pointer for OSMessageBox()
+    gWindowImplementation = this;
 
 #if LL_X11
-	mFlashing = FALSE;
+    mFlashing = FALSE;
+    initialiseX11Clipboard();
 #endif // LL_X11
 
-	mKeyScanCode = 0;
-	mKeyVirtualKey = 0;
-	mKeyModifiers = KMOD_NONE;
+    mKeyVirtualKey = 0;
+    mKeyModifiers = KMOD_NONE;
 }
 
 static SDL_Surface *Load_BMP_Resource(const char *basename)
 {
-	const int PATH_BUFFER_SIZE=1000;
-	char path_buffer[PATH_BUFFER_SIZE];	/* Flawfinder: ignore */
-	
-	// Figure out where our BMP is living on the disk
-	snprintf(path_buffer, PATH_BUFFER_SIZE-1, "%s%sres-sdl%s%s",	
-		 gDirUtilp->getAppRODataDir().c_str(),
-		 gDirUtilp->getDirDelimiter().c_str(),
-		 gDirUtilp->getDirDelimiter().c_str(),
-		 basename);
-	path_buffer[PATH_BUFFER_SIZE-1] = '\0';
-	
-	return SDL_LoadBMP(path_buffer);
+    const int PATH_BUFFER_SIZE=1000;
+    char path_buffer[PATH_BUFFER_SIZE];	/* Flawfinder: ignore */
+
+    // Figure out where our BMP is living on the disk
+    snprintf(path_buffer, PATH_BUFFER_SIZE-1, "%s%sres-sdl%s%s",
+             gDirUtilp->getAppRODataDir().c_str(),
+             gDirUtilp->getDirDelimiter().c_str(),
+             gDirUtilp->getDirDelimiter().c_str(),
+             basename);
+    path_buffer[PATH_BUFFER_SIZE-1] = '\0';
+
+    return SDL_LoadBMP(path_buffer);
 }
 
 #if LL_X11
@@ -274,520 +442,513 @@ static SDL_Surface *Load_BMP_Resource(const char *basename)
 // '?' is the X11 display number derived from $DISPLAY
 static int x11_detect_VRAM_kb_fp(FILE *fp, const char *prefix_str)
 {
-	const int line_buf_size = 1000;
-	char line_buf[line_buf_size];
-	while (fgets(line_buf, line_buf_size, fp))
-	{
-		//LL_DEBUGS() << "XLOG: " << line_buf << LL_ENDL;
-
-		// Why the ad-hoc parser instead of using a regex?  Our
-		// favourite regex implementation - libboost_regex - is
-		// quite a heavy and troublesome dependency for the client, so
-		// it seems a shame to introduce it for such a simple task.
-		// *FIXME: libboost_regex is a dependency now anyway, so we may
-		// as well use it instead of this hand-rolled nonsense.
-		const char *part1_template = prefix_str;
-		const char part2_template[] = " kB";
-		char *part1 = strstr(line_buf, part1_template);
-		if (part1) // found start of matching line
-		{
-			part1 = &part1[strlen(part1_template)]; // -> after
-			char *part2 = strstr(part1, part2_template);
-			if (part2) // found end of matching line
-			{
-				// now everything between part1 and part2 is
-				// supposed to be numeric, describing the
-				// number of kB of Video RAM supported
-				int rtn = 0;
-				for (; part1 < part2; ++part1)
-				{
-					if (*part1 < '0' || *part1 > '9')
-					{
-						// unexpected char, abort parse
-						rtn = 0;
-						break;
-					}
-					rtn *= 10;
-					rtn += (*part1) - '0';
-				}
-				if (rtn > 0)
-				{
-					// got the kB number.  return it now.
-					return rtn;
-				}
-			}
-		}
-	}
-	return 0; // 'could not detect'
+    const int line_buf_size = 1000;
+    char line_buf[line_buf_size];
+    while (fgets(line_buf, line_buf_size, fp))
+    {
+        //LL_DEBUGS() << "XLOG: " << line_buf << LL_ENDL;
+
+        // Why the ad-hoc parser instead of using a regex?  Our
+        // favourite regex implementation - libboost_regex - is
+        // quite a heavy and troublesome dependency for the client, so
+        // it seems a shame to introduce it for such a simple task.
+        // *FIXME: libboost_regex is a dependency now anyway, so we may
+        // as well use it instead of this hand-rolled nonsense.
+        const char *part1_template = prefix_str;
+        const char part2_template[] = " kB";
+        char *part1 = strstr(line_buf, part1_template);
+        if (part1) // found start of matching line
+        {
+            part1 = &part1[strlen(part1_template)]; // -> after
+            char *part2 = strstr(part1, part2_template);
+            if (part2) // found end of matching line
+            {
+                // now everything between part1 and part2 is
+                // supposed to be numeric, describing the
+                // number of kB of Video RAM supported
+                int rtn = 0;
+                for (; part1 < part2; ++part1)
+                {
+                    if (*part1 < '0' || *part1 > '9')
+                    {
+                        // unexpected char, abort parse
+                        rtn = 0;
+                        break;
+                    }
+                    rtn *= 10;
+                    rtn += (*part1) - '0';
+                }
+                if (rtn > 0)
+                {
+                    // got the kB number.  return it now.
+                    return rtn;
+                }
+            }
+        }
+    }
+    return 0; // 'could not detect'
 }
 
 static int x11_detect_VRAM_kb()
 {
-	std::string x_log_location("/var/log/");
-	std::string fname;
-	int rtn = 0; // 'could not detect'
-	int display_num = 0;
-	FILE *fp;
-	char *display_env = getenv("DISPLAY"); // e.g. :0 or :0.0 or :1.0 etc
-	// parse DISPLAY number so we can go grab the right log file
-	if (display_env[0] == ':' &&
-	    display_env[1] >= '0' && display_env[1] <= '9')
-	{
-		display_num = display_env[1] - '0';
-	}
-
-	// *TODO: we could be smarter and see which of Xorg/XFree86 has the
-	// freshest time-stamp.
-
-	// Try Xorg log first
-	fname = x_log_location;
-	fname += "Xorg.";
-	fname += ('0' + display_num);
-	fname += ".log";
-	fp = fopen(fname.c_str(), "r");
-	if (fp)
-	{
-		LL_INFOS() << "Looking in " << fname
-			<< " for VRAM info..." << LL_ENDL;
-		rtn = x11_detect_VRAM_kb_fp(fp, ": VideoRAM: ");
-		fclose(fp);
-		if (0 == rtn)
-		{
-			fp = fopen(fname.c_str(), "r");
-			if (fp)
-			{
-				rtn = x11_detect_VRAM_kb_fp(fp, ": Video RAM: ");
-				fclose(fp);
-				if (0 == rtn)
-				{
-					fp = fopen(fname.c_str(), "r");
-					if (fp)
-					{
-						rtn = x11_detect_VRAM_kb_fp(fp, ": Memory: ");
-						fclose(fp);
-					}
-				}
-			}
-		}
-	}
-	else
-	{
-		LL_INFOS() << "Could not open " << fname
-			<< " - skipped." << LL_ENDL;	
-		// Try old XFree86 log otherwise
-		fname = x_log_location;
-		fname += "XFree86.";
-		fname += ('0' + display_num);
-		fname += ".log";
-		fp = fopen(fname.c_str(), "r");
-		if (fp)
-		{
-			LL_INFOS() << "Looking in " << fname
-				<< " for VRAM info..." << LL_ENDL;
-			rtn = x11_detect_VRAM_kb_fp(fp, ": VideoRAM: ");
-			fclose(fp);
-			if (0 == rtn)
-			{
-				fp = fopen(fname.c_str(), "r");
-				if (fp)
-				{
-					rtn = x11_detect_VRAM_kb_fp(fp, ": Memory: ");
-					fclose(fp);
-				}
-			}
-		}
-		else
-		{
-			LL_INFOS() << "Could not open " << fname
-				<< " - skipped." << LL_ENDL;
-		}
-	}
-	return rtn;
+    std::string x_log_location("/var/log/");
+    std::string fname;
+    int rtn = 0; // 'could not detect'
+    int display_num = 0;
+    FILE *fp;
+    char *display_env = getenv("DISPLAY"); // e.g. :0 or :0.0 or :1.0 etc
+    // parse DISPLAY number so we can go grab the right log file
+    if (display_env[0] == ':' &&
+        display_env[1] >= '0' && display_env[1] <= '9')
+    {
+        display_num = display_env[1] - '0';
+    }
+
+    // *TODO: we could be smarter and see which of Xorg/XFree86 has the
+    // freshest time-stamp.
+
+    // Try Xorg log first
+    fname = x_log_location;
+    fname += "Xorg.";
+    fname += ('0' + display_num);
+    fname += ".log";
+    fp = fopen(fname.c_str(), "r");
+    if (fp)
+    {
+        LL_INFOS() << "Looking in " << fname
+                   << " for VRAM info..." << LL_ENDL;
+        rtn = x11_detect_VRAM_kb_fp(fp, ": VideoRAM: ");
+        fclose(fp);
+        if (0 == rtn)
+        {
+            fp = fopen(fname.c_str(), "r");
+            if (fp)
+            {
+                rtn = x11_detect_VRAM_kb_fp(fp, ": Video RAM: ");
+                fclose(fp);
+                if (0 == rtn)
+                {
+                    fp = fopen(fname.c_str(), "r");
+                    if (fp)
+                    {
+                        rtn = x11_detect_VRAM_kb_fp(fp, ": Memory: ");
+                        fclose(fp);
+                    }
+                }
+            }
+        }
+    }
+    else
+    {
+        LL_INFOS() << "Could not open " << fname
+                   << " - skipped." << LL_ENDL;
+        // Try old XFree86 log otherwise
+        fname = x_log_location;
+        fname += "XFree86.";
+        fname += ('0' + display_num);
+        fname += ".log";
+        fp = fopen(fname.c_str(), "r");
+        if (fp)
+        {
+            LL_INFOS() << "Looking in " << fname
+                       << " for VRAM info..." << LL_ENDL;
+            rtn = x11_detect_VRAM_kb_fp(fp, ": VideoRAM: ");
+            fclose(fp);
+            if (0 == rtn)
+            {
+                fp = fopen(fname.c_str(), "r");
+                if (fp)
+                {
+                    rtn = x11_detect_VRAM_kb_fp(fp, ": Memory: ");
+                    fclose(fp);
+                }
+            }
+        }
+        else
+        {
+            LL_INFOS() << "Could not open " << fname
+                       << " - skipped." << LL_ENDL;
+        }
+    }
+    return rtn;
 }
 #endif // LL_X11
 
+void LLWindowSDL::setTitle(const std::string title)
+{
+    SDL_SetWindowTitle( mWindow, title.c_str() );
+}
+
+void LLWindowSDL::tryFindFullscreenSize( int &width, int &height )
+{
+    LL_INFOS() << "createContext: setting up fullscreen " << width << "x" << height << LL_ENDL;
+
+    // If the requested width or height is 0, find the best default for the monitor.
+    if((width == 0) || (height == 0))
+    {
+        // Scan through the list of modes, looking for one which has:
+        //		height between 700 and 800
+        //		aspect ratio closest to the user's original mode
+        S32 resolutionCount = 0;
+        LLWindowResolution *resolutionList = getSupportedResolutions(resolutionCount);
+
+        if(resolutionList != NULL)
+        {
+            F32 closestAspect = 0;
+            U32 closestHeight = 0;
+            U32 closestWidth = 0;
+            int i;
+
+            LL_INFOS() << "createContext: searching for a display mode, original aspect is " << mOriginalAspectRatio << LL_ENDL;
+
+            for(i=0; i < resolutionCount; i++)
+            {
+                F32 aspect = (F32)resolutionList[i].mWidth / (F32)resolutionList[i].mHeight;
+
+                LL_INFOS() << "createContext: width " << resolutionList[i].mWidth << " height " << resolutionList[i].mHeight << " aspect " << aspect << LL_ENDL;
+
+                if( (resolutionList[i].mHeight >= 700) && (resolutionList[i].mHeight <= 800) &&
+                    (fabs(aspect - mOriginalAspectRatio) < fabs(closestAspect - mOriginalAspectRatio)))
+                {
+                    LL_INFOS() << " (new closest mode) " << LL_ENDL;
+
+                    // This is the closest mode we've seen yet.
+                    closestWidth = resolutionList[i].mWidth;
+                    closestHeight = resolutionList[i].mHeight;
+                    closestAspect = aspect;
+                }
+            }
+
+            width = closestWidth;
+            height = closestHeight;
+        }
+    }
+
+    if((width == 0) || (height == 0))
+    {
+        // Mode search failed for some reason.  Use the old-school default.
+        width = 1024;
+        height = 768;
+    }
+}
+
 BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync)
 {
-	//bool			glneedsinit = false;
-
-	LL_INFOS() << "createContext, fullscreen=" << fullscreen <<
-	    " size=" << width << "x" << height << LL_ENDL;
-
-	// captures don't survive contexts
-	mGrabbyKeyFlags = 0;
-	mReallyCapturedCount = 0;
-	
-	if (SDL_Init(SDL_INIT_VIDEO) < 0)
-	{
-		LL_INFOS() << "sdl_init() failed! " << SDL_GetError() << LL_ENDL;
-		setupFailure("sdl_init() failure,  window creation error", "error", OSMB_OK);
-		return false;
-	}
-
-	SDL_version c_sdl_version;
-	SDL_VERSION(&c_sdl_version);
-	LL_INFOS() << "Compiled against SDL "
-		<< int(c_sdl_version.major) << "."
-		<< int(c_sdl_version.minor) << "."
-		<< int(c_sdl_version.patch) << LL_ENDL;
-	const SDL_version *r_sdl_version;
-	r_sdl_version = SDL_Linked_Version();
-	LL_INFOS() << " Running against SDL "
-		<< int(r_sdl_version->major) << "."
-		<< int(r_sdl_version->minor) << "."
-		<< int(r_sdl_version->patch) << LL_ENDL;
-
-	const SDL_VideoInfo *video_info = SDL_GetVideoInfo( );
-	if (!video_info)
-	{
-		LL_INFOS() << "SDL_GetVideoInfo() failed! " << SDL_GetError() << LL_ENDL;
-		setupFailure("SDL_GetVideoInfo() failed, Window creation error", "Error", OSMB_OK);
-		return FALSE;
-	}
-
-	if (video_info->current_h > 0)
-	{
-		mOriginalAspectRatio = (float)video_info->current_w / (float)video_info->current_h;
-		LL_INFOS() << "Original aspect ratio was " << video_info->current_w << ":" << video_info->current_h << "=" << mOriginalAspectRatio << LL_ENDL;
-	}
-
-	SDL_EnableUNICODE(1);
-	SDL_WM_SetCaption(mWindowTitle.c_str(), mWindowTitle.c_str());
-
-	// Set the application icon.
-	SDL_Surface *bmpsurface;
-	bmpsurface = Load_BMP_Resource("ll_icon.BMP");
-	if (bmpsurface)
-	{
-		// This attempts to give a black-keyed mask to the icon.
-		SDL_SetColorKey(bmpsurface,
-				SDL_SRCCOLORKEY,
-				SDL_MapRGB(bmpsurface->format, 0,0,0) );
-		SDL_WM_SetIcon(bmpsurface, NULL);
-		// The SDL examples cheerfully avoid freeing the icon
-		// surface, but I'm betting that's leaky.
-		SDL_FreeSurface(bmpsurface);
-		bmpsurface = NULL;
-	}
-
-	// note: these SetAttributes make Tom's 9600-on-AMD64 fail to
-	// get a visual, but it's broken anyway when it does, and without
-	// these SetAttributes we might easily get an avoidable substandard
-	// visual to work with on most other machines.
-	SDL_GL_SetAttribute(SDL_GL_RED_SIZE,  8);
-	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8);
-	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
-    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, (bits <= 16) ? 16 : 24);
-	// We need stencil support for a few (minor) things.
-	if (!getenv("LL_GL_NO_STENCIL"))
-		SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
-        SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, (bits <= 16) ? 1 : 8);
-
-        // *FIX: try to toggle vsync here?
-
-	mFullscreen = fullscreen;
-
-	int sdlflags = SDL_OPENGL | SDL_RESIZABLE | SDL_ANYFORMAT;
-
-	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
-
-	if (mFSAASamples > 0)
-	{
-		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
-		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, mFSAASamples);
-	}
-	
-    	mSDLFlags = sdlflags;
-
-	if (mFullscreen)
-	{
-		LL_INFOS() << "createContext: setting up fullscreen " << width << "x" << height << LL_ENDL;
-
-		// If the requested width or height is 0, find the best default for the monitor.
-		if((width == 0) || (height == 0))
-		{
-			// Scan through the list of modes, looking for one which has:
-			//		height between 700 and 800
-			//		aspect ratio closest to the user's original mode
-			S32 resolutionCount = 0;
-			LLWindowResolution *resolutionList = getSupportedResolutions(resolutionCount);
-
-			if(resolutionList != NULL)
-			{
-				F32 closestAspect = 0;
-				U32 closestHeight = 0;
-				U32 closestWidth = 0;
-				int i;
-
-				LL_INFOS() << "createContext: searching for a display mode, original aspect is " << mOriginalAspectRatio << LL_ENDL;
-
-				for(i=0; i < resolutionCount; i++)
-				{
-					F32 aspect = (F32)resolutionList[i].mWidth / (F32)resolutionList[i].mHeight;
-
-					LL_INFOS() << "createContext: width " << resolutionList[i].mWidth << " height " << resolutionList[i].mHeight << " aspect " << aspect << LL_ENDL;
-
-					if( (resolutionList[i].mHeight >= 700) && (resolutionList[i].mHeight <= 800) &&
-						(fabs(aspect - mOriginalAspectRatio) < fabs(closestAspect - mOriginalAspectRatio)))
-					{
-						LL_INFOS() << " (new closest mode) " << LL_ENDL;
-
-						// This is the closest mode we've seen yet.
-						closestWidth = resolutionList[i].mWidth;
-						closestHeight = resolutionList[i].mHeight;
-						closestAspect = aspect;
-					}
-				}
-
-				width = closestWidth;
-				height = closestHeight;
-			}
-		}
-
-		if((width == 0) || (height == 0))
-		{
-			// Mode search failed for some reason.  Use the old-school default.
-			width = 1024;
-			height = 768;
-		}
-
-		mWindow = SDL_SetVideoMode(width, height, bits, sdlflags | SDL_FULLSCREEN);
-		if (!mWindow && bits > 16)
-		{
-			SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
-			mWindow = SDL_SetVideoMode(width, height, bits, sdlflags | SDL_FULLSCREEN);
-		}
-
-		if (mWindow)
-		{
-			mFullscreen = TRUE;
-			mFullscreenWidth   = mWindow->w;
-			mFullscreenHeight  = mWindow->h;
-			mFullscreenBits    = mWindow->format->BitsPerPixel;
-			mFullscreenRefresh = -1;
-
-			LL_INFOS() << "Running at " << mFullscreenWidth
-				<< "x"   << mFullscreenHeight
-				<< "x"   << mFullscreenBits
-				<< " @ " << mFullscreenRefresh
-				<< LL_ENDL;
-		}
-		else
-		{
-			LL_WARNS() << "createContext: fullscreen creation failure. SDL: " << SDL_GetError() << LL_ENDL;
-			// No fullscreen support
-			mFullscreen = FALSE;
-			mFullscreenWidth   = -1;
-			mFullscreenHeight  = -1;
-			mFullscreenBits    = -1;
-			mFullscreenRefresh = -1;
-
-			std::string error = llformat("Unable to run fullscreen at %d x %d.\nRunning in window.", width, height);	
-			OSMessageBox(error, "Error", OSMB_OK);
-		}
-	}
-
-	if(!mFullscreen && (mWindow == NULL))
-	{
-		if (width == 0)
-		    width = 1024;
-		if (height == 0)
-		    width = 768;
-
-		LL_INFOS() << "createContext: creating window " << width << "x" << height << "x" << bits << LL_ENDL;
-		mWindow = SDL_SetVideoMode(width, height, bits, sdlflags);
-		if (!mWindow && bits > 16)
-		{
-			SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
-			mWindow = SDL_SetVideoMode(width, height, bits, sdlflags);
-		}
-
-		if (!mWindow)
-		{
-			LL_WARNS() << "createContext: window creation failure. SDL: " << SDL_GetError() << LL_ENDL;
-			setupFailure("Window creation error", "Error", OSMB_OK);
-			return FALSE;
-		}
-	} else if (!mFullscreen && (mWindow != NULL))
-	{
-		LL_INFOS() << "createContext: SKIPPING - !fullscreen, but +mWindow " << width << "x" << height << "x" << bits << LL_ENDL;
-	}
-	
-	// Detect video memory size.
+    //bool			glneedsinit = false;
+
+    LL_INFOS() << "createContext, fullscreen=" << fullscreen <<
+               " size=" << width << "x" << height << LL_ENDL;
+
+    // captures don't survive contexts
+    mGrabbyKeyFlags = 0;
+    mReallyCapturedCount = 0;
+
+    std::initializer_list<std::tuple< char const*, char const * > > hintList =
+            {
+                    {SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR,"0"},
+                    {SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH,"1"},
+            };
+
+    for( auto hint: hintList )
+    {
+        SDL_SetHint( std::get<0>(hint), std::get<1>(hint));
+    }
+
+    std::initializer_list<std::tuple<uint32_t, char const*, bool>> initList=
+            { {SDL_INIT_VIDEO,"SDL_INIT_VIDEO", true},
+              {SDL_INIT_AUDIO,"SDL_INIT_AUDIO", false},
+              {SDL_INIT_GAMECONTROLLER,"SDL_INIT_GAMECONTROLLER", false},
+              {SDL_INIT_SENSOR,"SDL_INIT_SENSOR", false}
+            };
+
+    for( auto subSystem : initList)
+    {
+        if( SDL_InitSubSystem( std::get<0>(subSystem) ) < 0 )
+        {
+            LL_WARNS() << "SDL_InitSubSystem for " << std::get<1>(subSystem) << " failed " << SDL_GetError() << LL_ENDL;
+
+            if( std::get<2>(subSystem))
+                setupFailure("SDL_Init() failure", "error", OSMB_OK);
+
+        }
+    }
+
+    SDL_version c_sdl_version;
+    SDL_VERSION(&c_sdl_version);
+    LL_INFOS() << "Compiled against SDL "
+               << int(c_sdl_version.major) << "."
+               << int(c_sdl_version.minor) << "."
+               << int(c_sdl_version.patch) << LL_ENDL;
+    SDL_version r_sdl_version;
+    SDL_GetVersion(&r_sdl_version);
+    LL_INFOS() << " Running against SDL "
+               << int(r_sdl_version.major) << "."
+               << int(r_sdl_version.minor) << "."
+               << int(r_sdl_version.patch) << LL_ENDL;
+
+    if (width == 0)
+        width = 1024;
+    if (height == 0)
+        width = 768;
+
+    mFullscreen = fullscreen;
+
+    int sdlflags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
+
+    if( mFullscreen )
+    {
+        sdlflags |= SDL_WINDOW_FULLSCREEN;
+        tryFindFullscreenSize( width, height );
+    }
+
+    mSDLFlags = sdlflags;
+
+    GLint redBits{8}, greenBits{8}, blueBits{8}, alphaBits{8};
+
+    GLint depthBits{(bits <= 16) ? 16 : 24}, stencilBits{8};
+
+    if (getenv("LL_GL_NO_STENCIL"))
+        stencilBits = 0;
+
+    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, alphaBits);
+    SDL_GL_SetAttribute(SDL_GL_RED_SIZE,   redBits);
+    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, greenBits);
+    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,  blueBits);
+    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depthBits );
+
+    // We need stencil support for a few (minor) things.
+    if (stencilBits)
+        SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencilBits);
+    // *FIX: try to toggle vsync here?
+
+    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+    if (mFSAASamples > 0)
+    {
+        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
+        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, mFSAASamples);
+    }
+
+    SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
+    mWindow = SDL_CreateWindow( mWindowTitle.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, mSDLFlags );
+
+    if( mWindow )
+    {
+        mContext = SDL_GL_CreateContext( mWindow );
+
+        if( mContext == 0 )
+        {
+            LL_WARNS() << "Cannot create GL context " << SDL_GetError() << LL_ENDL;
+            setupFailure("GL Context creation error creation error", "Error", OSMB_OK);
+            return FALSE;
+        }
+        // SDL_GL_SetSwapInterval(1);
+        mSurface = SDL_GetWindowSurface( mWindow );
+    }
+
+
+    if( mFullscreen )
+    {
+        if (mSurface)
+        {
+            mFullscreen = TRUE;
+            mFullscreenWidth = mSurface->w;
+            mFullscreenHeight = mSurface->h;
+            mFullscreenBits    = mSurface->format->BitsPerPixel;
+            mFullscreenRefresh = -1;
+
+            LL_INFOS() << "Running at " << mFullscreenWidth
+                       << "x"   << mFullscreenHeight
+                       << "x"   << mFullscreenBits
+                       << " @ " << mFullscreenRefresh
+                       << LL_ENDL;
+        }
+        else
+        {
+            LL_WARNS() << "createContext: fullscreen creation failure. SDL: " << SDL_GetError() << LL_ENDL;
+            // No fullscreen support
+            mFullscreen = FALSE;
+            mFullscreenWidth   = -1;
+            mFullscreenHeight  = -1;
+            mFullscreenBits    = -1;
+            mFullscreenRefresh = -1;
+
+            std::string error = llformat("Unable to run fullscreen at %d x %d.\nRunning in window.", width, height);
+            OSMessageBox(error, "Error", OSMB_OK);
+            return FALSE;
+        }
+    }
+    else
+    {
+        if (!mWindow)
+        {
+            LL_WARNS() << "createContext: window creation failure. SDL: " << SDL_GetError() << LL_ENDL;
+            setupFailure("Window creation error", "Error", OSMB_OK);
+            return FALSE;
+        }
+    }
+
+    // Set the application icon.
+    SDL_Surface *bmpsurface;
+    bmpsurface = Load_BMP_Resource("ll_icon.BMP");
+    if (bmpsurface)
+    {
+        SDL_SetWindowIcon(mWindow, bmpsurface);
+        SDL_FreeSurface(bmpsurface);
+        bmpsurface = NULL;
+    }
+
+    // Detect video memory size.
 # if LL_X11
-	gGLManager.mVRAM = x11_detect_VRAM_kb() / 1024;
-	if (gGLManager.mVRAM != 0)
-	{
-		LL_INFOS() << "X11 log-parser detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL;
-	} else
+    gGLManager.mVRAM = x11_detect_VRAM_kb() / 1024;
+    if (gGLManager.mVRAM != 0)
+    {
+        LL_INFOS() << "X11 log-parser detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL;
+    } else
 # endif // LL_X11
-	{
-		// fallback to letting SDL detect VRAM.
-		// note: I've not seen SDL's detection ever actually find
-		// VRAM != 0, but if SDL *does* detect it then that's a bonus.
-		gGLManager.mVRAM = video_info->video_mem / 1024;
-		if (gGLManager.mVRAM != 0)
-		{
-			LL_INFOS() << "SDL detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL;
-		}
-	}
-	// If VRAM is not detected, that is handled later
-
-	// *TODO: Now would be an appropriate time to check for some
-	// explicitly unsupported cards.
-	//const char* RENDERER = (const char*) glGetString(GL_RENDERER);
-
-	GLint depthBits, stencilBits, redBits, greenBits, blueBits, alphaBits;
-
-	glGetIntegerv(GL_RED_BITS, &redBits);
-	glGetIntegerv(GL_GREEN_BITS, &greenBits);
-	glGetIntegerv(GL_BLUE_BITS, &blueBits);
-	glGetIntegerv(GL_ALPHA_BITS, &alphaBits);
-	glGetIntegerv(GL_DEPTH_BITS, &depthBits);
-	glGetIntegerv(GL_STENCIL_BITS, &stencilBits);
-	
-	LL_INFOS() << "GL buffer:" << LL_ENDL;
-        LL_INFOS() << "  Red Bits " << S32(redBits) << LL_ENDL;
-        LL_INFOS() << "  Green Bits " << S32(greenBits) << LL_ENDL;
-        LL_INFOS() << "  Blue Bits " << S32(blueBits) << LL_ENDL;
-	LL_INFOS()	<< "  Alpha Bits " << S32(alphaBits) << LL_ENDL;
-	LL_INFOS()	<< "  Depth Bits " << S32(depthBits) << LL_ENDL;
-	LL_INFOS()	<< "  Stencil Bits " << S32(stencilBits) << LL_ENDL;
-
-	GLint colorBits = redBits + greenBits + blueBits + alphaBits;
-	// fixme: actually, it's REALLY important for picking that we get at
-	// least 8 bits each of red,green,blue.  Alpha we can be a bit more
-	// relaxed about if we have to.
-	if (colorBits < 32)
-	{
-		close();
-		setupFailure(
-			"Second Life requires True Color (32-bit) to run in a window.\n"
-			"Please go to Control Panels -> Display -> Settings and\n"
-			"set the screen to 32-bit color.\n"
-			"Alternately, if you choose to run fullscreen, Second Life\n"
-			"will automatically adjust the screen each time it runs.",
-			"Error",
-			OSMB_OK);
-		return FALSE;
-	}
-
-#if 0  // *FIX: we're going to brave it for now...
-	if (alphaBits < 8)
-	{
-		close();
-		setupFailure(
-			"Second Life is unable to run because it can't get an 8 bit alpha\n"
-			"channel.  Usually this is due to video card driver issues.\n"
-			"Please make sure you have the latest video card drivers installed.\n"
-			"Also be sure your monitor is set to True Color (32-bit) in\n"
-			"Control Panels -> Display -> Settings.\n"
-			"If you continue to receive this message, contact customer service.",
-			"Error",
-			OSMB_OK);
-		return FALSE;
-	}
-#endif
+    {
+        // fallback to letting SDL detect VRAM.
+        // note: I've not seen SDL's detection ever actually find
+        // VRAM != 0, but if SDL *does* detect it then that's a bonus.
+        gGLManager.mVRAM = 0;
+        if (gGLManager.mVRAM != 0)
+        {
+            LL_INFOS() << "SDL detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL;
+        }
+    }
+    // If VRAM is not detected, that is handled later
+
+    // *TODO: Now would be an appropriate time to check for some
+    // explicitly unsupported cards.
+    //const char* RENDERER = (const char*) glGetString(GL_RENDERER);
+
+    SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &redBits);
+    SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &greenBits);
+    SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &blueBits);
+    SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &alphaBits);
+    SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depthBits);
+    SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &stencilBits);
+
+    LL_INFOS() << "GL buffer:" << LL_ENDL;
+    LL_INFOS() << "  Red Bits " << S32(redBits) << LL_ENDL;
+    LL_INFOS() << "  Green Bits " << S32(greenBits) << LL_ENDL;
+    LL_INFOS() << "  Blue Bits " << S32(blueBits) << LL_ENDL;
+    LL_INFOS() << "  Alpha Bits " << S32(alphaBits) << LL_ENDL;
+    LL_INFOS() << "  Depth Bits " << S32(depthBits) << LL_ENDL;
+    LL_INFOS() << "  Stencil Bits " << S32(stencilBits) << LL_ENDL;
+
+    GLint colorBits = redBits + greenBits + blueBits + alphaBits;
+    // fixme: actually, it's REALLY important for picking that we get at
+    // least 8 bits each of red,green,blue.  Alpha we can be a bit more
+    // relaxed about if we have to.
+    if (colorBits < 32)
+    {
+        close();
+        setupFailure(
+                "Second Life requires True Color (32-bit) to run in a window.\n"
+                "Please go to Control Panels -> Display -> Settings and\n"
+                "set the screen to 32-bit color.\n"
+                "Alternately, if you choose to run fullscreen, Second Life\n"
+                "will automatically adjust the screen each time it runs.",
+                "Error",
+                OSMB_OK);
+        return FALSE;
+    }
 
 #if LL_X11
-	/* Grab the window manager specific information */
-	SDL_SysWMinfo info;
-	SDL_VERSION(&info.version);
-	if ( SDL_GetWMInfo(&info) )
-	{
-		/* Save the information for later use */
-		if ( info.subsystem == SDL_SYSWM_X11 )
-		{
-			mSDL_Display = info.info.x11.display;
-			mSDL_XWindowID = info.info.x11.wmwindow;
-			Lock_Display = info.info.x11.lock_func;
-			Unlock_Display = info.info.x11.unlock_func;
-		}
-		else
-		{
-			LL_WARNS() << "We're not running under X11?  Wild."
-				<< LL_ENDL;
-		}
-	}
-	else
-	{
-		LL_WARNS() << "We're not running under any known WM.  Wild."
-			<< LL_ENDL;
-	}
+    /* Grab the window manager specific information */
+    SDL_SysWMinfo info;
+    SDL_VERSION(&info.version);
+    if ( SDL_GetWindowWMInfo(mWindow, &info) )
+    {
+        /* Save the information for later use */
+        if ( info.subsystem == SDL_SYSWM_X11 )
+        {
+            mSDL_Display = info.info.x11.display;
+            mSDL_XWindowID = info.info.x11.window;
+        }
+        else
+        {
+            LL_WARNS() << "We're not running under X11?  Wild."
+                       << LL_ENDL;
+        }
+    }
+    else
+    {
+        LL_WARNS() << "We're not running under any known WM.  Wild."
+                   << LL_ENDL;
+    }
 #endif // LL_X11
 
 
-	//make sure multisampling is disabled by default
-	glDisable(GL_MULTISAMPLE_ARB);
-	
-	// We need to do this here, once video is init'd
-	if (-1 == SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,
-				      SDL_DEFAULT_REPEAT_INTERVAL))
-	    LL_WARNS() << "Couldn't enable key-repeat: " << SDL_GetError() <<LL_ENDL;
+    SDL_StartTextInput();
+    //make sure multisampling is disabled by default
+    glDisable(GL_MULTISAMPLE_ARB);
 
-	// Don't need to get the current gamma, since there's a call that restores it to the system defaults.
-	return TRUE;
+    // Don't need to get the current gamma, since there's a call that restores it to the system defaults.
+    return TRUE;
 }
 
 
 // changing fullscreen resolution, or switching between windowed and fullscreen mode.
 BOOL LLWindowSDL::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp)
 {
-	const BOOL needsRebuild = TRUE;  // Just nuke the context and start over.
-	BOOL result = true;
+    const BOOL needsRebuild = TRUE;  // Just nuke the context and start over.
+    BOOL result = true;
 
-	LL_INFOS() << "switchContext, fullscreen=" << fullscreen << LL_ENDL;
-	stop_glerror();
-	if(needsRebuild)
-	{
-		destroyContext();
-		result = createContext(0, 0, size.mX, size.mY, 0, fullscreen, disable_vsync);
-		if (result)
-		{
-			gGLManager.initGL();
+    LL_INFOS() << "switchContext, fullscreen=" << fullscreen << LL_ENDL;
+    stop_glerror();
+    if(needsRebuild)
+    {
+        destroyContext();
+        result = createContext(0, 0, size.mX, size.mY, 0, fullscreen, disable_vsync);
+        if (result)
+        {
+            gGLManager.initGL();
 
-			//start with arrow cursor
-			initCursors();
-			setCursor( UI_CURSOR_ARROW );
-		}
-	}
+            //start with arrow cursor
+            initCursors();
+            setCursor( UI_CURSOR_ARROW );
+        }
+    }
 
-	stop_glerror();
+    stop_glerror();
 
-	return result;
+    return result;
 }
 
 void LLWindowSDL::destroyContext()
 {
-	LL_INFOS() << "destroyContext begins" << LL_ENDL;
+    LL_INFOS() << "destroyContext begins" << LL_ENDL;
 
+    SDL_StopTextInput();
 #if LL_X11
-	mSDL_Display = NULL;
-	mSDL_XWindowID = None;
-	Lock_Display = NULL;
-	Unlock_Display = NULL;
+    mSDL_Display = NULL;
+    mSDL_XWindowID = None;
+    Lock_Display = NULL;
+    Unlock_Display = NULL;
 #endif // LL_X11
 
-	// Clean up remaining GL state before blowing away window
-	LL_INFOS() << "shutdownGL begins" << LL_ENDL;
-	gGLManager.shutdownGL();
-	LL_INFOS() << "SDL_QuitSS/VID begins" << LL_ENDL;
-	SDL_QuitSubSystem(SDL_INIT_VIDEO);  // *FIX: this might be risky...
+    // Clean up remaining GL state before blowing away window
+    LL_INFOS() << "shutdownGL begins" << LL_ENDL;
+    gGLManager.shutdownGL();
+    LL_INFOS() << "SDL_QuitSS/VID begins" << LL_ENDL;
+    SDL_QuitSubSystem(SDL_INIT_VIDEO);  // *FIX: this might be risky...
 
-	mWindow = NULL;
+    mWindow = NULL;
 }
 
 LLWindowSDL::~LLWindowSDL()
 {
-	quitCursors();
-	destroyContext();
+    quitCursors();
+    destroyContext();
 
-	if(mSupportedResolutions != NULL)
-	{
-		delete []mSupportedResolutions;
-	}
+    if(mSupportedResolutions != NULL)
+    {
+        delete []mSupportedResolutions;
+    }
 
-	gWindowImplementation = NULL;
+    gWindowImplementation = NULL;
 }
 
 
@@ -818,87 +979,87 @@ void LLWindowSDL::restore()
 // Usually called from LLWindowManager::destroyWindow()
 void LLWindowSDL::close()
 {
-	// Is window is already closed?
-	//	if (!mWindow)
-	//	{
-	//		return;
-	//	}
+    // Is window is already closed?
+    //	if (!mWindow)
+    //	{
+    //		return;
+    //	}
 
-	// Make sure cursor is visible and we haven't mangled the clipping state.
-	setMouseClipping(FALSE);
-	showCursor();
+    // Make sure cursor is visible and we haven't mangled the clipping state.
+    setMouseClipping(FALSE);
+    showCursor();
 
-	destroyContext();
+    destroyContext();
 }
 
 BOOL LLWindowSDL::isValid()
 {
-	return (mWindow != NULL);
+    return (mWindow != NULL);
 }
 
 BOOL LLWindowSDL::getVisible()
 {
-	BOOL result = FALSE;
+    BOOL result = FALSE;
 
     // *FIX: This isn't really right...
-	// Then what is?
-	if (mWindow)
-	{
-		result = TRUE;
-	}
+    // Then what is?
+    if (mWindow)
+    {
+        result = TRUE;
+    }
 
-	return(result);
+    return(result);
 }
 
 BOOL LLWindowSDL::getMinimized()
 {
-	BOOL result = FALSE;
+    BOOL result = FALSE;
 
-	if (mWindow && (1 == mIsMinimized))
-	{
-		result = TRUE;
-	}
-	return(result);
+    if (mWindow && (1 == mIsMinimized))
+    {
+        result = TRUE;
+    }
+    return(result);
 }
 
 BOOL LLWindowSDL::getMaximized()
 {
-	BOOL result = FALSE;
+    BOOL result = FALSE;
 
-	if (mWindow)
-	{
-		// TODO
-	}
+    if (mWindow)
+    {
+        // TODO
+    }
 
-	return(result);
+    return(result);
 }
 
 BOOL LLWindowSDL::maximize()
 {
-	// TODO
-	return FALSE;
+    // TODO
+    return FALSE;
 }
 
 BOOL LLWindowSDL::getFullscreen()
 {
-	return mFullscreen;
+    return mFullscreen;
 }
 
 BOOL LLWindowSDL::getPosition(LLCoordScreen *position)
 {
     // *FIX: can anything be done with this?
-	position->mX = 0;
-	position->mY = 0;
+    position->mX = 0;
+    position->mY = 0;
     return TRUE;
 }
 
 BOOL LLWindowSDL::getSize(LLCoordScreen *size)
 {
-    if (mWindow)
+    if (mSurface)
     {
-        size->mX = mWindow->w;
-        size->mY = mWindow->h;
-	return (TRUE);
+        size->mX = mSurface->w;
+        size->mY = mSurface->h;
+        return (TRUE);
     }
 
     return (FALSE);
@@ -906,11 +1067,11 @@ BOOL LLWindowSDL::getSize(LLCoordScreen *size)
 
 BOOL LLWindowSDL::getSize(LLCoordWindow *size)
 {
-    if (mWindow)
+    if (mSurface)
     {
-        size->mX = mWindow->w;
-        size->mY = mWindow->h;
-	return (TRUE);
+        size->mX = mSurface->w;
+        size->mY = mSurface->h;
+        return (TRUE);
     }
 
     return (FALSE);
@@ -918,94 +1079,91 @@ BOOL LLWindowSDL::getSize(LLCoordWindow *size)
 
 BOOL LLWindowSDL::setPosition(const LLCoordScreen position)
 {
-	if(mWindow)
-	{
+    if(mWindow)
+    {
         // *FIX: (?)
-		//MacMoveWindow(mWindow, position.mX, position.mY, false);
-	}
+        //MacMoveWindow(mWindow, position.mX, position.mY, false);
+    }
 
-	return TRUE;
+    return TRUE;
 }
 
-BOOL LLWindowSDL::setSizeImpl(const LLCoordScreen size)
+template< typename T > bool setSizeImpl( const T& newSize, SDL_Window *pWin )
 {
-	if(mWindow)
-	{
-		// Push a resize event onto SDL's queue - we'll handle it
-		// when it comes out again.
-		SDL_Event event;
-		event.type = SDL_VIDEORESIZE;
-		event.resize.w = size.mX;
-		event.resize.h = size.mY;
-		SDL_PushEvent(&event); // copied into queue
+    if( !pWin )
+        return false;
+
+    auto nFlags = SDL_GetWindowFlags( pWin );
+
+    if( nFlags & SDL_WINDOW_MAXIMIZED )
+        SDL_RestoreWindow( pWin );
+
+
+    SDL_SetWindowSize( pWin, newSize.mX, newSize.mY );
+    SDL_Event event;
+    event.type = SDL_WINDOWEVENT;
+    event.window.event = SDL_WINDOWEVENT_RESIZED;
+    event.window.windowID = SDL_GetWindowID( pWin );
+    event.window.data1 = newSize.mX;
+    event.window.data2 = newSize.mY;
+    SDL_PushEvent( &event );
 
-		return TRUE;
-	}
-		
-	return FALSE;
+    return true;
 }
 
-BOOL LLWindowSDL::setSizeImpl(const LLCoordWindow size)
+BOOL LLWindowSDL::setSizeImpl(const LLCoordScreen size)
 {
-	if(mWindow)
-	{
-		// Push a resize event onto SDL's queue - we'll handle it
-		// when it comes out again.
-		SDL_Event event;
-		event.type = SDL_VIDEORESIZE;
-		event.resize.w = size.mX;
-		event.resize.h = size.mY;
-		SDL_PushEvent(&event); // copied into queue
-
-		return TRUE;
-	}
+    return ::setSizeImpl( size, mWindow );
+}
 
-	return FALSE;
+BOOL LLWindowSDL::setSizeImpl(const LLCoordWindow size)
+{
+    return ::setSizeImpl( size, mWindow );
 }
 
 
 void LLWindowSDL::swapBuffers()
 {
-	if (mWindow)
-	{	
-		SDL_GL_SwapBuffers();
-	}
+    if (mWindow)
+    {
+        SDL_GL_SwapWindow( mWindow );
+    }
 }
 
 U32 LLWindowSDL::getFSAASamples()
 {
-	return mFSAASamples;
+    return mFSAASamples;
 }
 
 void LLWindowSDL::setFSAASamples(const U32 samples)
 {
-	mFSAASamples = samples;
+    mFSAASamples = samples;
 }
 
 F32 LLWindowSDL::getGamma()
 {
-	return 1/mGamma;
+    return 1/mGamma;
 }
 
 BOOL LLWindowSDL::restoreGamma()
 {
-	//CGDisplayRestoreColorSyncSettings();
-    SDL_SetGamma(1.0f, 1.0f, 1.0f);
-	return true;
+    //CGDisplayRestoreColorSyncSettings();
+    // SDL_SetGamma(1.0f, 1.0f, 1.0f);
+    return true;
 }
 
 BOOL LLWindowSDL::setGamma(const F32 gamma)
 {
-	mGamma = gamma;
-	if (mGamma == 0) mGamma = 0.1f;
-	mGamma = 1/mGamma;
-	SDL_SetGamma(mGamma, mGamma, mGamma);
-	return true;
+    mGamma = gamma;
+    if (mGamma == 0) mGamma = 0.1f;
+    mGamma = 1/mGamma;
+    // SDL_SetGamma(mGamma, mGamma, mGamma);
+    return true;
 }
 
 BOOL LLWindowSDL::isCursorHidden()
 {
-	return mCursorHidden;
+    return mCursorHidden;
 }
 
 
@@ -1019,110 +1177,98 @@ void LLWindowSDL::setMouseClipping( BOOL b )
 // virtual
 void LLWindowSDL::setMinSize(U32 min_width, U32 min_height, bool enforce_immediately)
 {
-	LLWindow::setMinSize(min_width, min_height, enforce_immediately);
+    LLWindow::setMinSize(min_width, min_height, enforce_immediately);
 
 #if LL_X11
-	// Set the minimum size limits for X11 window
-	// so the window manager doesn't allow resizing below those limits.
-	XSizeHints* hints = XAllocSizeHints();
-	hints->flags |= PMinSize;
-	hints->min_width = mMinWindowWidth;
-	hints->min_height = mMinWindowHeight;
+    // Set the minimum size limits for X11 window
+    // so the window manager doesn't allow resizing below those limits.
+    XSizeHints* hints = XAllocSizeHints();
+    hints->flags |= PMinSize;
+    hints->min_width = mMinWindowWidth;
+    hints->min_height = mMinWindowHeight;
 
-	XSetWMNormalHints(mSDL_Display, mSDL_XWindowID, hints);
+    XSetWMNormalHints(mSDL_Display, mSDL_XWindowID, hints);
 
-	XFree(hints);
+    XFree(hints);
 #endif
 }
 
 BOOL LLWindowSDL::setCursorPosition(const LLCoordWindow position)
 {
-	BOOL result = TRUE;
-	LLCoordScreen screen_pos;
+    BOOL result = TRUE;
+    LLCoordScreen screen_pos;
 
-	if (!convertCoords(position, &screen_pos))
-	{
-		return FALSE;
-	}
+    if (!convertCoords(position, &screen_pos))
+    {
+        return FALSE;
+    }
+
+    //LL_INFOS() << "setCursorPosition(" << screen_pos.mX << ", " << screen_pos.mY << ")" << LL_ENDL;
 
-	//LL_INFOS() << "setCursorPosition(" << screen_pos.mX << ", " << screen_pos.mY << ")" << LL_ENDL;
+    // do the actual forced cursor move.
+    SDL_WarpMouseInWindow(mWindow, screen_pos.mX, screen_pos.mY);
 
-	// do the actual forced cursor move.
-	SDL_WarpMouse(screen_pos.mX, screen_pos.mY);
-	
-	//LL_INFOS() << llformat("llcw %d,%d -> scr %d,%d", position.mX, position.mY, screen_pos.mX, screen_pos.mY) << LL_ENDL;
+    //LL_INFOS() << llformat("llcw %d,%d -> scr %d,%d", position.mX, position.mY, screen_pos.mX, screen_pos.mY) << LL_ENDL;
 
-	return result;
+    return result;
 }
 
 BOOL LLWindowSDL::getCursorPosition(LLCoordWindow *position)
 {
-	//Point cursor_point;
-	LLCoordScreen screen_pos;
+    //Point cursor_point;
+    LLCoordScreen screen_pos;
 
-	//GetMouse(&cursor_point);
+    //GetMouse(&cursor_point);
     int x, y;
     SDL_GetMouseState(&x, &y);
 
-	screen_pos.mX = x;
-	screen_pos.mY = y;
+    screen_pos.mX = x;
+    screen_pos.mY = y;
 
-	return convertCoords(screen_pos, position);
+    return convertCoords(screen_pos, position);
 }
 
 
 F32 LLWindowSDL::getNativeAspectRatio()
 {
-#if 0
-	// RN: this hack presumes that the largest supported resolution is monitor-limited
-	// and that pixels in that mode are square, therefore defining the native aspect ratio
-	// of the monitor...this seems to work to a close approximation for most CRTs/LCDs
-	S32 num_resolutions;
-	LLWindowResolution* resolutions = getSupportedResolutions(num_resolutions);
-
-
-	return ((F32)resolutions[num_resolutions - 1].mWidth / (F32)resolutions[num_resolutions - 1].mHeight);
-	//rn: AC
-#endif
+    // MBW -- there are a couple of bad assumptions here.  One is that the display list won't include
+    //		ridiculous resolutions nobody would ever use.  The other is that the list is in order.
 
-	// MBW -- there are a couple of bad assumptions here.  One is that the display list won't include
-	//		ridiculous resolutions nobody would ever use.  The other is that the list is in order.
+    // New assumptions:
+    // - pixels are square (the only reasonable choice, really)
+    // - The user runs their display at a native resolution, so the resolution of the display
+    //    when the app is launched has an aspect ratio that matches the monitor.
 
-	// New assumptions:
-	// - pixels are square (the only reasonable choice, really)
-	// - The user runs their display at a native resolution, so the resolution of the display
-	//    when the app is launched has an aspect ratio that matches the monitor.
+    //RN: actually, the assumption that there are no ridiculous resolutions (above the display's native capabilities) has
+    // been born out in my experience.
+    // Pixels are often not square (just ask the people who run their LCDs at 1024x768 or 800x600 when running fullscreen, like me)
+    // The ordering of display list is a blind assumption though, so we should check for max values
+    // Things might be different on the Mac though, so I'll defer to MBW
 
-	//RN: actually, the assumption that there are no ridiculous resolutions (above the display's native capabilities) has 
-	// been born out in my experience.  
-	// Pixels are often not square (just ask the people who run their LCDs at 1024x768 or 800x600 when running fullscreen, like me)
-	// The ordering of display list is a blind assumption though, so we should check for max values
-	// Things might be different on the Mac though, so I'll defer to MBW
+    // The constructor for this class grabs the aspect ratio of the monitor before doing any resolution
+    // switching, and stashes it in mOriginalAspectRatio.  Here, we just return it.
 
-	// The constructor for this class grabs the aspect ratio of the monitor before doing any resolution
-	// switching, and stashes it in mOriginalAspectRatio.  Here, we just return it.
-
-	if (mOverrideAspectRatio > 0.f)
-	{
-		return mOverrideAspectRatio;
-	}
+    if (mOverrideAspectRatio > 0.f)
+    {
+        return mOverrideAspectRatio;
+    }
 
-	return mOriginalAspectRatio;
+    return mOriginalAspectRatio;
 }
 
 F32 LLWindowSDL::getPixelAspectRatio()
 {
-	F32 pixel_aspect = 1.f;
-	if (getFullscreen())
-	{
-		LLCoordScreen screen_size;
-		if (getSize(&screen_size))
-		{
-			pixel_aspect = getNativeAspectRatio() * (F32)screen_size.mY / (F32)screen_size.mX;
-		}
-	}
+    F32 pixel_aspect = 1.f;
+    if (getFullscreen())
+    {
+        LLCoordScreen screen_size;
+        if (getSize(&screen_size))
+        {
+            pixel_aspect = getNativeAspectRatio() * (F32)screen_size.mY / (F32)screen_size.mX;
+        }
+    }
 
-	return pixel_aspect;
+    return pixel_aspect;
 }
 
 
@@ -1130,67 +1276,61 @@ F32 LLWindowSDL::getPixelAspectRatio()
 // dialogs are still usable in fullscreen.
 void LLWindowSDL::beforeDialog()
 {
-	bool running_x11 = false;
+    bool running_x11 = false;
 #if LL_X11
-	running_x11 = (mSDL_XWindowID != None);
+    running_x11 = (mSDL_XWindowID != None);
 #endif //LL_X11
 
-	LL_INFOS() << "LLWindowSDL::beforeDialog()" << LL_ENDL;
-
-	if (SDLReallyCaptureInput(FALSE)) // must ungrab input so popup works!
-	{
-		if (mFullscreen)
-		{
-			// need to temporarily go non-fullscreen; bless SDL
-			// for providing a SDL_WM_ToggleFullScreen() - though
-			// it only works in X11
-			if (running_x11 && mWindow)
-			{
-				SDL_WM_ToggleFullScreen(mWindow);
-			}
-		}
-	}
+    LL_INFOS() << "LLWindowSDL::beforeDialog()" << LL_ENDL;
+
+    if (SDLReallyCaptureInput(FALSE)) // must ungrab input so popup works!
+    {
+        if (mFullscreen)
+        {
+            // need to temporarily go non-fullscreen; bless SDL
+            // for providing a SDL_WM_ToggleFullScreen() - though
+            // it only works in X11
+            if (running_x11 && mWindow)
+            {
+                SDL_SetWindowFullscreen( mWindow, 0 );
+            }
+        }
+    }
 
 #if LL_X11
-	if (mSDL_Display)
-	{
-		// Everything that we/SDL asked for should happen before we
-		// potentially hand control over to GTK.
-		maybe_lock_display();
-		XSync(mSDL_Display, False);
-		maybe_unlock_display();
-	}
+    if (mSDL_Display)
+    {
+        // Everything that we/SDL asked for should happen before we
+        // potentially hand control over to GTK.
+        maybe_lock_display();
+        XSync(mSDL_Display, False);
+        maybe_unlock_display();
+    }
 #endif // LL_X11
 
-#if LL_GTK
-	// this is a good time to grab some GTK version information for
-	// diagnostics, if not already done.
-	ll_try_gtk_init();
-#endif // LL_GTK
-
-	maybe_lock_display();
+    maybe_lock_display();
 }
 
 void LLWindowSDL::afterDialog()
 {
-	bool running_x11 = false;
+    bool running_x11 = false;
 #if LL_X11
-	running_x11 = (mSDL_XWindowID != None);
+    running_x11 = (mSDL_XWindowID != None);
 #endif //LL_X11
 
-	LL_INFOS() << "LLWindowSDL::afterDialog()" << LL_ENDL;
+    LL_INFOS() << "LLWindowSDL::afterDialog()" << LL_ENDL;
 
-	maybe_unlock_display();
+    maybe_unlock_display();
 
-	if (mFullscreen)
-	{
-		// need to restore fullscreen mode after dialog - only works
-		// in X11
-		if (running_x11 && mWindow)
-		{
-			SDL_WM_ToggleFullScreen(mWindow);
-		}
-	}
+    if (mFullscreen)
+    {
+        // need to restore fullscreen mode after dialog - only works
+        // in X11
+        if (running_x11 && mWindow)
+        {
+            SDL_SetWindowFullscreen( mWindow, 0 );
+        }
+    }
 }
 
 
@@ -1198,210 +1338,120 @@ void LLWindowSDL::afterDialog()
 // set/reset the XWMHints flag for 'urgency' that usually makes the icon flash
 void LLWindowSDL::x11_set_urgent(BOOL urgent)
 {
-	if (mSDL_Display && !mFullscreen)
-	{
-		XWMHints *wm_hints;
-		
-		LL_INFOS() << "X11 hint for urgency, " << urgent << LL_ENDL;
+    if (mSDL_Display && !mFullscreen)
+    {
+        XWMHints *wm_hints;
+
+        LL_INFOS() << "X11 hint for urgency, " << urgent << LL_ENDL;
 
-		maybe_lock_display();
-		wm_hints = XGetWMHints(mSDL_Display, mSDL_XWindowID);
-		if (!wm_hints)
-			wm_hints = XAllocWMHints();
+        maybe_lock_display();
+        wm_hints = XGetWMHints(mSDL_Display, mSDL_XWindowID);
+        if (!wm_hints)
+            wm_hints = XAllocWMHints();
 
-		if (urgent)
-			wm_hints->flags |= XUrgencyHint;
-		else
-			wm_hints->flags &= ~XUrgencyHint;
+        if (urgent)
+            wm_hints->flags |= XUrgencyHint;
+        else
+            wm_hints->flags &= ~XUrgencyHint;
 
-		XSetWMHints(mSDL_Display, mSDL_XWindowID, wm_hints);
-		XFree(wm_hints);
-		XSync(mSDL_Display, False);
-		maybe_unlock_display();
-	}
+        XSetWMHints(mSDL_Display, mSDL_XWindowID, wm_hints);
+        XFree(wm_hints);
+        XSync(mSDL_Display, False);
+        maybe_unlock_display();
+    }
 }
 #endif // LL_X11
 
 void LLWindowSDL::flashIcon(F32 seconds)
 {
+    if (getMinimized())
+    {
 #if !LL_X11
-	LL_INFOS() << "Stub LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL;
-#else	
-	LL_INFOS() << "X11 LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL;
-	
-	F32 remaining_time = mFlashTimer.getRemainingTimeF32();
-	if (remaining_time < seconds)
-		remaining_time = seconds;
-	mFlashTimer.reset();
-	mFlashTimer.setTimerExpirySec(remaining_time);
-
-	x11_set_urgent(TRUE);
-	mFlashing = TRUE;
-#endif // LL_X11
-}
-
-
-#if LL_GTK
-BOOL LLWindowSDL::isClipboardTextAvailable()
-{
-	if (ll_try_gtk_init())
-	{
-		GtkClipboard * const clipboard =
-			gtk_clipboard_get(GDK_NONE);
-		return gtk_clipboard_wait_is_text_available(clipboard) ?
-			TRUE : FALSE;
-	}
-	return FALSE; // failure
-}
-
-BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &text)
-{
-	if (ll_try_gtk_init())
-	{
-		GtkClipboard * const clipboard =
-			gtk_clipboard_get(GDK_NONE);
-		gchar * const data = gtk_clipboard_wait_for_text(clipboard);
-		if (data)
-		{
-			text = LLWString(utf8str_to_wstring(data));
-			g_free(data);
-			return TRUE;
-		}
-	}
-	return FALSE; // failure
-}
-
-BOOL LLWindowSDL::copyTextToClipboard(const LLWString &text)
-{
-	if (ll_try_gtk_init())
-	{
-		const std::string utf8 = wstring_to_utf8str(text);
-		GtkClipboard * const clipboard =
-			gtk_clipboard_get(GDK_NONE);
-		gtk_clipboard_set_text(clipboard, utf8.c_str(), utf8.length());
-		return TRUE;
-	}
-	return FALSE; // failure
-}
-
+        LL_INFOS() << "Stub LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL;
+#else
+        LL_INFOS() << "X11 LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL;
 
-BOOL LLWindowSDL::isPrimaryTextAvailable()
-{
-	if (ll_try_gtk_init())
-	{
-		GtkClipboard * const clipboard =
-			gtk_clipboard_get(GDK_SELECTION_PRIMARY);
-		return gtk_clipboard_wait_is_text_available(clipboard) ?
-			TRUE : FALSE;
-	}
-	return FALSE; // failure
-}
-
-BOOL LLWindowSDL::pasteTextFromPrimary(LLWString &text)
-{
-	if (ll_try_gtk_init())
-	{
-		GtkClipboard * const clipboard =
-			gtk_clipboard_get(GDK_SELECTION_PRIMARY);
-		gchar * const data = gtk_clipboard_wait_for_text(clipboard);
-		if (data)
-		{
-			text = LLWString(utf8str_to_wstring(data));
-			g_free(data);
-			return TRUE;
-		}
-	}
-	return FALSE; // failure
-}
-
-BOOL LLWindowSDL::copyTextToPrimary(const LLWString &text)
-{
-	if (ll_try_gtk_init())
-	{
-		const std::string utf8 = wstring_to_utf8str(text);
-		GtkClipboard * const clipboard =
-			gtk_clipboard_get(GDK_SELECTION_PRIMARY);
-		gtk_clipboard_set_text(clipboard, utf8.c_str(), utf8.length());
-		return TRUE;
-	}
-	return FALSE; // failure
-}
+        F32 remaining_time = mFlashTimer.getRemainingTimeF32();
+        if (remaining_time < seconds)
+            remaining_time = seconds;
+        mFlashTimer.reset();
+        mFlashTimer.setTimerExpirySec(remaining_time);
 
-#else
+        x11_set_urgent(TRUE);
+        mFlashing = TRUE;
+#endif // LL_X11
+    }
+}
 
 BOOL LLWindowSDL::isClipboardTextAvailable()
 {
-	return FALSE; // unsupported
+    return mSDL_Display && XGetSelectionOwner(mSDL_Display, XA_CLIPBOARD) != None;
 }
 
 BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &dst)
 {
-	return FALSE; // unsupported
+    return getSelectionText(XA_CLIPBOARD, dst);
 }
 
 BOOL LLWindowSDL::copyTextToClipboard(const LLWString &s)
 {
-	return FALSE;  // unsupported
+    return setSelectionText(XA_CLIPBOARD, s);
 }
 
 BOOL LLWindowSDL::isPrimaryTextAvailable()
 {
-	return FALSE; // unsupported
+    LLWString text;
+    return getSelectionText(XA_PRIMARY, text) && !text.empty();
 }
 
 BOOL LLWindowSDL::pasteTextFromPrimary(LLWString &dst)
 {
-	return FALSE; // unsupported
+    return getSelectionText(XA_PRIMARY, dst);
 }
 
 BOOL LLWindowSDL::copyTextToPrimary(const LLWString &s)
 {
-	return FALSE;  // unsupported
+    return setSelectionText(XA_PRIMARY, s);
 }
 
-#endif // LL_GTK
-
 LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_resolutions)
 {
-	if (!mSupportedResolutions)
-	{
-		mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS];
-		mNumSupportedResolutions = 0;
+    if (!mSupportedResolutions)
+    {
+        mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS];
+        mNumSupportedResolutions = 0;
+
+        // <FS:ND> Use display no from mWindow/mSurface here?
+        int max = SDL_GetNumDisplayModes(0);
+        max = llclamp( max, 0, MAX_NUM_RESOLUTIONS );
 
-        SDL_Rect **modes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN);
-        if ( (modes != NULL) && (modes != ((SDL_Rect **) -1)) )
+        for( int i =0; i < max; ++i )
         {
-            int count = 0;
-            while (*modes && count<MAX_NUM_RESOLUTIONS)  // they're sorted biggest to smallest, so find end...
+            SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 };
+            if (SDL_GetDisplayMode( 0 , i, &mode) != 0)
             {
-                modes++;
-                count++;
+                continue;
             }
 
-            while (count--)
+            int w = mode.w;
+            int h = mode.h;
+            if ((w >= 800) && (h >= 600))
             {
-                modes--;
-                SDL_Rect *r = *modes;
-                int w = r->w;
-                int h = r->h;
-                if ((w >= 800) && (h >= 600))
+                // make sure we don't add the same resolution multiple times!
+                if ( (mNumSupportedResolutions == 0) ||
+                     ((mSupportedResolutions[mNumSupportedResolutions-1].mWidth != w) &&
+                      (mSupportedResolutions[mNumSupportedResolutions-1].mHeight != h)) )
                 {
-                    // make sure we don't add the same resolution multiple times!
-                    if ( (mNumSupportedResolutions == 0) ||
-                         ((mSupportedResolutions[mNumSupportedResolutions-1].mWidth != w) &&
-                          (mSupportedResolutions[mNumSupportedResolutions-1].mHeight != h)) )
-                    {
-                        mSupportedResolutions[mNumSupportedResolutions].mWidth = w;
-                        mSupportedResolutions[mNumSupportedResolutions].mHeight = h;
-                        mNumSupportedResolutions++;
-                    }
+                    mSupportedResolutions[mNumSupportedResolutions].mWidth = w;
+                    mSupportedResolutions[mNumSupportedResolutions].mHeight = h;
+                    mNumSupportedResolutions++;
                 }
             }
         }
-	}
+    }
 
-	num_resolutions = mNumSupportedResolutions;
-	return mSupportedResolutions;
+    num_resolutions = mNumSupportedResolutions;
+    return mSupportedResolutions;
 }
 
 BOOL LLWindowSDL::convertCoords(LLCoordGL from, LLCoordWindow *to)
@@ -1409,10 +1459,10 @@ BOOL LLWindowSDL::convertCoords(LLCoordGL from, LLCoordWindow *to)
     if (!to)
         return FALSE;
 
-	to->mX = from.mX;
-	to->mY = mWindow->h - from.mY - 1;
+    to->mX = from.mX;
+    to->mY = mSurface->h - from.mY - 1;
 
-	return TRUE;
+    return TRUE;
 }
 
 BOOL LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordGL* to)
@@ -1420,46 +1470,46 @@ BOOL LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordGL* to)
     if (!to)
         return FALSE;
 
-	to->mX = from.mX;
-	to->mY = mWindow->h - from.mY - 1;
+    to->mX = from.mX;
+    to->mY = mSurface->h - from.mY - 1;
 
-	return TRUE;
+    return TRUE;
 }
 
 BOOL LLWindowSDL::convertCoords(LLCoordScreen from, LLCoordWindow* to)
 {
     if (!to)
-		return FALSE;
+        return FALSE;
 
-	// In the fullscreen case, window and screen coordinates are the same.
-	to->mX = from.mX;
-	to->mY = from.mY;
+    // In the fullscreen case, window and screen coordinates are the same.
+    to->mX = from.mX;
+    to->mY = from.mY;
     return (TRUE);
 }
 
 BOOL LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordScreen *to)
 {
     if (!to)
-		return FALSE;
+        return FALSE;
 
-	// In the fullscreen case, window and screen coordinates are the same.
-	to->mX = from.mX;
-	to->mY = from.mY;
+    // In the fullscreen case, window and screen coordinates are the same.
+    to->mX = from.mX;
+    to->mY = from.mY;
     return (TRUE);
 }
 
 BOOL LLWindowSDL::convertCoords(LLCoordScreen from, LLCoordGL *to)
 {
-	LLCoordWindow window_coord;
+    LLCoordWindow window_coord;
 
-	return(convertCoords(from, &window_coord) && convertCoords(window_coord, to));
+    return(convertCoords(from, &window_coord) && convertCoords(window_coord, to));
 }
 
 BOOL LLWindowSDL::convertCoords(LLCoordGL from, LLCoordScreen *to)
 {
-	LLCoordWindow window_coord;
+    LLCoordWindow window_coord;
 
-	return(convertCoords(from, &window_coord) && convertCoords(window_coord, to));
+    return(convertCoords(from, &window_coord) && convertCoords(window_coord, to));
 }
 
 
@@ -1467,226 +1517,216 @@ BOOL LLWindowSDL::convertCoords(LLCoordGL from, LLCoordScreen *to)
 
 void LLWindowSDL::setupFailure(const std::string& text, const std::string& caption, U32 type)
 {
-	destroyContext();
+    destroyContext();
 
-	OSMessageBox(text, caption, type);
+    OSMessageBox(text, caption, type);
 }
 
 BOOL LLWindowSDL::SDLReallyCaptureInput(BOOL capture)
 {
-	// note: this used to be safe to call nestedly, but in the
-	// end that's not really a wise usage pattern, so don't.
-
-	if (capture)
-		mReallyCapturedCount = 1;
-	else
-		mReallyCapturedCount = 0;
-	
-	SDL_GrabMode wantmode, newmode;
-	if (mReallyCapturedCount <= 0) // uncapture
-	{
-		wantmode = SDL_GRAB_OFF;
-	} else // capture
-	{
-		wantmode = SDL_GRAB_ON;
-	}
-	
-	if (mReallyCapturedCount < 0) // yuck, imbalance.
-	{
-		mReallyCapturedCount = 0;
-		LL_WARNS() << "ReallyCapture count was < 0" << LL_ENDL;
-	}
-
-	if (!mFullscreen) /* only bother if we're windowed anyway */
-	{
+    // note: this used to be safe to call nestedly, but in the
+    // end that's not really a wise usage pattern, so don't.
+
+    if (capture)
+        mReallyCapturedCount = 1;
+    else
+        mReallyCapturedCount = 0;
+
+    bool wantGrab;
+    if (mReallyCapturedCount <= 0) // uncapture
+    {
+        wantGrab = false;
+    } else // capture
+    {
+        wantGrab = true;
+    }
+
+    if (mReallyCapturedCount < 0) // yuck, imbalance.
+    {
+        mReallyCapturedCount = 0;
+        LL_WARNS() << "ReallyCapture count was < 0" << LL_ENDL;
+    }
+
+    bool newGrab = wantGrab;
+
 #if LL_X11
-		if (mSDL_Display)
-		{
-			/* we dirtily mix raw X11 with SDL so that our pointer
-			   isn't (as often) constrained to the limits of the
-			   window while grabbed, which feels nicer and
-			   hopefully eliminates some reported 'sticky pointer'
-			   problems.  We use raw X11 instead of
-			   SDL_WM_GrabInput() because the latter constrains
-			   the pointer to the window and also steals all
-			   *keyboard* input from the window manager, which was
-			   frustrating users. */
-			int result;
-			if (wantmode == SDL_GRAB_ON)
-			{
-				//LL_INFOS() << "X11 POINTER GRABBY" << LL_ENDL;
-				//newmode = SDL_WM_GrabInput(wantmode);
-				maybe_lock_display();
-				result = XGrabPointer(mSDL_Display, mSDL_XWindowID,
-						      True, 0, GrabModeAsync,
-						      GrabModeAsync,
-						      None, None, CurrentTime);
-				maybe_unlock_display();
-				if (GrabSuccess == result)
-					newmode = SDL_GRAB_ON;
-				else
-					newmode = SDL_GRAB_OFF;
-			} else if (wantmode == SDL_GRAB_OFF)
-			{
-				//LL_INFOS() << "X11 POINTER UNGRABBY" << LL_ENDL;
-				newmode = SDL_GRAB_OFF;
-				//newmode = SDL_WM_GrabInput(SDL_GRAB_OFF);
-				
-				maybe_lock_display();
-				XUngrabPointer(mSDL_Display, CurrentTime);
-				// Make sure the ungrab happens RIGHT NOW.
-				XSync(mSDL_Display, False);
-				maybe_unlock_display();
-			} else
-			{
-				newmode = SDL_GRAB_QUERY; // neutral
-			}
-		} else // not actually running on X11, for some reason
-			newmode = wantmode;
+    if (!mFullscreen) /* only bother if we're windowed anyway */
+    {
+        if (mSDL_Display)
+        {
+            /* we dirtily mix raw X11 with SDL so that our pointer
+               isn't (as often) constrained to the limits of the
+               window while grabbed, which feels nicer and
+               hopefully eliminates some reported 'sticky pointer'
+               problems.  We use raw X11 instead of
+               SDL_WM_GrabInput() because the latter constrains
+               the pointer to the window and also steals all
+               *keyboard* input from the window manager, which was
+               frustrating users. */
+            int result;
+            if (wantGrab == true)
+            {
+                maybe_lock_display();
+                result = XGrabPointer(mSDL_Display, mSDL_XWindowID,
+                                      True, 0, GrabModeAsync,
+                                      GrabModeAsync,
+                                      None, None, CurrentTime);
+                maybe_unlock_display();
+                if (GrabSuccess == result)
+                    newGrab = true;
+                else
+                    newGrab = false;
+            }
+            else
+            {
+                newGrab = false;
+
+                maybe_lock_display();
+                XUngrabPointer(mSDL_Display, CurrentTime);
+                // Make sure the ungrab happens RIGHT NOW.
+                XSync(mSDL_Display, False);
+                maybe_unlock_display();
+            }
+        }
+    }
 #endif // LL_X11
-	} else {
-		// pretend we got what we wanted, when really we don't care.
-		newmode = wantmode;
-	}
-	
-	// return boolean success for whether we ended up in the desired state
-	return (capture && SDL_GRAB_ON==newmode) ||
-		(!capture && SDL_GRAB_OFF==newmode);
-}
-
-U32 LLWindowSDL::SDLCheckGrabbyKeys(SDLKey keysym, BOOL gain)
-{
-	/* part of the fix for SL-13243: Some popular window managers like
-	   to totally eat alt-drag for the purposes of moving windows.  We
-	   spoil their day by acquiring the exclusive X11 mouse lock for as
-	   long as ALT is held down, so the window manager can't easily
-	   see what's happening.  Tested successfully with Metacity.
-	   And... do the same with CTRL, for other darn WMs.  We don't
-	   care about other metakeys as SL doesn't use them with dragging
-	   (for now). */
-
-	/* We maintain a bitmap of critical keys which are up and down
-	   instead of simply key-counting, because SDL sometimes reports
-	   misbalanced keyup/keydown event pairs to us for whatever reason. */
-
-	U32 mask = 0;
-	switch (keysym)
-	{
-	case SDLK_LALT:
-		mask = 1U << 0; break;
-	case SDLK_RALT:
-		mask = 1U << 1; break;
-	case SDLK_LCTRL:
-		mask = 1U << 2; break;
-	case SDLK_RCTRL:
-		mask = 1U << 3; break;
-	default:
-		break;
-	}
-
-	if (gain)
-		mGrabbyKeyFlags |= mask;
-	else
-		mGrabbyKeyFlags &= ~mask;
-
-	//LL_INFOS() << "mGrabbyKeyFlags=" << mGrabbyKeyFlags << LL_ENDL;
-
-	/* 0 means we don't need to mousegrab, otherwise grab. */
-	return mGrabbyKeyFlags;
+    // return boolean success for whether we ended up in the desired state
+    return capture == newGrab;
+}
+
+U32 LLWindowSDL::SDLCheckGrabbyKeys(U32 keysym, BOOL gain)
+{
+    /* part of the fix for SL-13243: Some popular window managers like
+       to totally eat alt-drag for the purposes of moving windows.  We
+       spoil their day by acquiring the exclusive X11 mouse lock for as
+       long as ALT is held down, so the window manager can't easily
+       see what's happening.  Tested successfully with Metacity.
+       And... do the same with CTRL, for other darn WMs.  We don't
+       care about other metakeys as SL doesn't use them with dragging
+       (for now). */
+
+    /* We maintain a bitmap of critical keys which are up and down
+       instead of simply key-counting, because SDL sometimes reports
+       misbalanced keyup/keydown event pairs to us for whatever reason. */
+
+    U32 mask = 0;
+    switch (keysym)
+    {
+        case SDLK_LALT:
+            mask = 1U << 0; break;
+        case SDLK_RALT:
+            mask = 1U << 1; break;
+        case SDLK_LCTRL:
+            mask = 1U << 2; break;
+        case SDLK_RCTRL:
+            mask = 1U << 3; break;
+        default:
+            break;
+    }
+
+    if (gain)
+        mGrabbyKeyFlags |= mask;
+    else
+        mGrabbyKeyFlags &= ~mask;
+
+    //LL_INFOS() << "mGrabbyKeyFlags=" << mGrabbyKeyFlags << LL_ENDL;
+
+    /* 0 means we don't need to mousegrab, otherwise grab. */
+    return mGrabbyKeyFlags;
 }
 
 
 void check_vm_bloat()
 {
 #if LL_LINUX
-	// watch our own VM and RSS sizes, warn if we bloated rapidly
-	static const std::string STATS_FILE = "/proc/self/stat";
-	FILE *fp = fopen(STATS_FILE.c_str(), "r");
-	if (fp)
-	{
-		static long long last_vm_size = 0;
-		static long long last_rss_size = 0;
-		const long long significant_vm_difference = 250 * 1024*1024;
-		const long long significant_rss_difference = 50 * 1024*1024;
-		long long this_vm_size = 0;
-		long long this_rss_size = 0;
-
-		ssize_t res;
-		size_t dummy;
-		char *ptr = NULL;
-		for (int i=0; i<22; ++i) // parse past the values we don't want
-		{
-			res = getdelim(&ptr, &dummy, ' ', fp);
-			if (-1 == res)
-			{
-				LL_WARNS() << "Unable to parse " << STATS_FILE << LL_ENDL;
-				goto finally;
-			}
-			free(ptr);
-			ptr = NULL;
-		}
-		// 23rd space-delimited entry is vsize
-		res = getdelim(&ptr, &dummy, ' ', fp);
-		llassert(ptr);
-		if (-1 == res)
-		{
-			LL_WARNS() << "Unable to parse " << STATS_FILE << LL_ENDL;
-			goto finally;
-		}
-		this_vm_size = atoll(ptr);
-		free(ptr);
-		ptr = NULL;
-		// 24th space-delimited entry is RSS
-		res = getdelim(&ptr, &dummy, ' ', fp);
-		llassert(ptr);
-		if (-1 == res)
-		{
-			LL_WARNS() << "Unable to parse " << STATS_FILE << LL_ENDL;
-			goto finally;
-		}
-		this_rss_size = getpagesize() * atoll(ptr);
-		free(ptr);
-		ptr = NULL;
-
-		LL_INFOS() << "VM SIZE IS NOW " << (this_vm_size/(1024*1024)) << " MB, RSS SIZE IS NOW " << (this_rss_size/(1024*1024)) << " MB" << LL_ENDL;
-
-		if (llabs(last_vm_size - this_vm_size) >
-		    significant_vm_difference)
-		{
-			if (this_vm_size > last_vm_size)
-			{
-				LL_WARNS() << "VM size grew by " << (this_vm_size - last_vm_size)/(1024*1024) << " MB in last frame" << LL_ENDL;
-			}
-			else
-			{
-				LL_INFOS() << "VM size shrank by " << (last_vm_size - this_vm_size)/(1024*1024) << " MB in last frame" << LL_ENDL;
-			}
-		}
-
-		if (llabs(last_rss_size - this_rss_size) >
-		    significant_rss_difference)
-		{
-			if (this_rss_size > last_rss_size)
-			{
-				LL_WARNS() << "RSS size grew by " << (this_rss_size - last_rss_size)/(1024*1024) << " MB in last frame" << LL_ENDL;
-			}
-			else
-			{
-				LL_INFOS() << "RSS size shrank by " << (last_rss_size - this_rss_size)/(1024*1024) << " MB in last frame" << LL_ENDL;
-			}
-		}
-
-		last_rss_size = this_rss_size;
-		last_vm_size = this_vm_size;
-
-finally:
-		if (NULL != ptr)
-		{
-			free(ptr);
-			ptr = NULL;
-		}
-		fclose(fp);
-	}
+    // watch our own VM and RSS sizes, warn if we bloated rapidly
+    static const std::string STATS_FILE = "/proc/self/stat";
+    FILE *fp = fopen(STATS_FILE.c_str(), "r");
+    if (fp)
+    {
+        static long long last_vm_size = 0;
+        static long long last_rss_size = 0;
+        const long long significant_vm_difference = 250 * 1024*1024;
+        const long long significant_rss_difference = 50 * 1024*1024;
+        long long this_vm_size = 0;
+        long long this_rss_size = 0;
+
+        ssize_t res;
+        size_t dummy;
+        char *ptr = NULL;
+        for (int i=0; i<22; ++i) // parse past the values we don't want
+        {
+            res = getdelim(&ptr, &dummy, ' ', fp);
+            if (-1 == res)
+            {
+                LL_WARNS() << "Unable to parse " << STATS_FILE << LL_ENDL;
+                goto finally;
+            }
+            free(ptr);
+            ptr = NULL;
+        }
+        // 23rd space-delimited entry is vsize
+        res = getdelim(&ptr, &dummy, ' ', fp);
+        llassert(ptr);
+        if (-1 == res)
+        {
+            LL_WARNS() << "Unable to parse " << STATS_FILE << LL_ENDL;
+            goto finally;
+        }
+        this_vm_size = atoll(ptr);
+        free(ptr);
+        ptr = NULL;
+        // 24th space-delimited entry is RSS
+        res = getdelim(&ptr, &dummy, ' ', fp);
+        llassert(ptr);
+        if (-1 == res)
+        {
+            LL_WARNS() << "Unable to parse " << STATS_FILE << LL_ENDL;
+            goto finally;
+        }
+        this_rss_size = getpagesize() * atoll(ptr);
+        free(ptr);
+        ptr = NULL;
+
+        LL_INFOS() << "VM SIZE IS NOW " << (this_vm_size/(1024*1024)) << " MB, RSS SIZE IS NOW " << (this_rss_size/(1024*1024)) << " MB" << LL_ENDL;
+
+        if (llabs(last_vm_size - this_vm_size) >
+            significant_vm_difference)
+        {
+            if (this_vm_size > last_vm_size)
+            {
+                LL_WARNS() << "VM size grew by " << (this_vm_size - last_vm_size)/(1024*1024) << " MB in last frame" << LL_ENDL;
+            }
+            else
+            {
+                LL_INFOS() << "VM size shrank by " << (last_vm_size - this_vm_size)/(1024*1024) << " MB in last frame" << LL_ENDL;
+            }
+        }
+
+        if (llabs(last_rss_size - this_rss_size) >
+            significant_rss_difference)
+        {
+            if (this_rss_size > last_rss_size)
+            {
+                LL_WARNS() << "RSS size grew by " << (this_rss_size - last_rss_size)/(1024*1024) << " MB in last frame" << LL_ENDL;
+            }
+            else
+            {
+                LL_INFOS() << "RSS size shrank by " << (last_rss_size - this_rss_size)/(1024*1024) << " MB in last frame" << LL_ENDL;
+            }
+        }
+
+        last_rss_size = this_rss_size;
+        last_vm_size = this_vm_size;
+
+        finally:
+        if (NULL != ptr)
+        {
+            free(ptr);
+            ptr = NULL;
+        }
+        fclose(fp);
+    }
 #endif // LL_LINUX
 }
 
@@ -1694,38 +1734,22 @@ finally:
 // virtual
 void LLWindowSDL::processMiscNativeEvents()
 {
-#if LL_GTK
-	// Pump GTK events to avoid starvation for:
-	// * DBUS servicing
-	// * Anything else which quietly hooks into the default glib/GTK loop
-    if (ll_try_gtk_init())
-    {
-	    // Yuck, Mozilla's GTK callbacks play with the locale - push/pop
-	    // the locale to protect it, as exotic/non-C locales
-	    // causes our code lots of general critical weirdness
-	    // and crashness. (SL-35450)
-	    static std::string saved_locale;
-	    saved_locale = ll_safe_string(setlocale(LC_ALL, NULL));
-
-	    // Pump until we've nothing left to do or passed 1/15th of a
-	    // second pumping for this frame.
-	    static LLTimer pump_timer;
-	    pump_timer.reset();
-	    pump_timer.setTimerExpirySec(1.0f / 15.0f);
-	    do {
-		     // Always do at least one non-blocking pump
-		    gtk_main_iteration_do(FALSE);
-	    } while (gtk_events_pending() &&
-		     !pump_timer.hasExpired());
-
-	    setlocale(LC_ALL, saved_locale.c_str() );
-    }
-#endif // LL_GTK
+#if LL_GLIB
+    // Pump until we've nothing left to do or passed 1/15th of a
+    // second pumping for this frame.
+    static LLTimer pump_timer;
+    pump_timer.reset();
+    pump_timer.setTimerExpirySec(1.0f / 15.0f);
+    do
+    {
+        g_main_context_iteration(g_main_context_default(), FALSE);
+    } while( g_main_context_pending(g_main_context_default()) && !pump_timer.hasExpired());
+#endif
 
     // hack - doesn't belong here - but this is just for debugging
     if (getenv("LL_DEBUG_BLOAT"))
     {
-	    check_vm_bloat();
+        check_vm_bloat();
     }
 }
 
@@ -1743,43 +1767,83 @@ void LLWindowSDL::gatherInput()
     {
         switch (event.type)
         {
+            case SDL_MOUSEWHEEL:
+                if( event.wheel.y != 0 )
+                    mCallbacks->handleScrollWheel(this, -event.wheel.y);
+                break;
+
             case SDL_MOUSEMOTION:
             {
                 LLCoordWindow winCoord(event.button.x, event.button.y);
                 LLCoordGL openGlCoord;
                 convertCoords(winCoord, &openGlCoord);
-				MASK mask = gKeyboard->currentMask(TRUE);
-				mCallbacks->handleMouseMove(this, openGlCoord, mask);
+                MASK mask = gKeyboard->currentMask(TRUE);
+                mCallbacks->handleMouseMove(this, openGlCoord, mask);
+                break;
+            }
+
+            case SDL_TEXTINPUT:
+            {
+                auto string = utf8str_to_utf16str( event.text.text );
+                mKeyModifiers = gKeyboard->currentMask( FALSE );
+                mInputType = "textinput";
+                for( auto key: string )
+                {
+                    mKeyVirtualKey = key;
+
+                    if( (MASK_CONTROL|MASK_ALT)&mKeyModifiers )
+                        gKeyboard->handleKeyDown(mKeyVirtualKey, mKeyModifiers );
+                    else
+                        handleUnicodeUTF16( key, mKeyModifiers );
+                }
                 break;
             }
 
             case SDL_KEYDOWN:
-		    mKeyScanCode = event.key.keysym.scancode;
-		    mKeyVirtualKey = event.key.keysym.unicode;
-		    mKeyModifiers = event.key.keysym.mod;
-
-		    gKeyboard->handleKeyDown(event.key.keysym.sym, event.key.keysym.mod);
-		    // part of the fix for SL-13243
-		    if (SDLCheckGrabbyKeys(event.key.keysym.sym, TRUE) != 0)
-			    SDLReallyCaptureInput(TRUE);
-
-		    if (event.key.keysym.unicode)
-		    {
-			    handleUnicodeUTF16(event.key.keysym.unicode,
-					       gKeyboard->currentMask(FALSE));
-		    }
+                mKeyVirtualKey = event.key.keysym.sym;
+                mKeyModifiers = event.key.keysym.mod;
+                mInputType = "keydown";
+
+                // treat all possible Enter/Return keys the same
+                if (mKeyVirtualKey == SDLK_RETURN2 || mKeyVirtualKey == SDLK_KP_ENTER)
+                {
+                    mKeyVirtualKey = SDLK_RETURN;
+                }
+
+                gKeyboard->handleKeyDown(mKeyVirtualKey, mKeyModifiers );
+
+                // <FS:ND> Slightly hacky :| To make the viewer honor enter (eg to accept form input) we've to not only send handleKeyDown but also send a
+                // invoke handleUnicodeUTF16 in case the user hits return.
+                // Note that we cannot blindly use handleUnicodeUTF16 for each SDL_KEYDOWN. Doing so will create bogus keyboard input (like % for cursor left).
+                if( mKeyVirtualKey == SDLK_RETURN )
+                {
+                    // fix return key not working when capslock, scrolllock or numlock are enabled
+                    mKeyModifiers &= (~(KMOD_NUM | KMOD_CAPS | KMOD_MODE | KMOD_SCROLL));
+                    handleUnicodeUTF16( mKeyVirtualKey, mKeyModifiers );
+                }
+
+                // part of the fix for SL-13243
+                if (SDLCheckGrabbyKeys(event.key.keysym.sym, TRUE) != 0)
+                    SDLReallyCaptureInput(TRUE);
+
                 break;
 
             case SDL_KEYUP:
-		    mKeyScanCode = event.key.keysym.scancode;
-		    mKeyVirtualKey = event.key.keysym.unicode;
-		    mKeyModifiers = event.key.keysym.mod;
+                mKeyVirtualKey = event.key.keysym.sym;
+                mKeyModifiers = event.key.keysym.mod;
+                mInputType = "keyup";
+
+                // treat all possible Enter/Return keys the same
+                if (mKeyVirtualKey == SDLK_RETURN2 || mKeyVirtualKey == SDLK_KP_ENTER)
+                {
+                    mKeyVirtualKey = SDLK_RETURN;
+                }
 
-		    if (SDLCheckGrabbyKeys(event.key.keysym.sym, FALSE) == 0)
-			    SDLReallyCaptureInput(FALSE); // part of the fix for SL-13243
+                if (SDLCheckGrabbyKeys(mKeyVirtualKey, FALSE) == 0)
+                    SDLReallyCaptureInput(FALSE); // part of the fix for SL-13243
 
-		    gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod);
-		    break;
+                gKeyboard->handleKeyUp(mKeyVirtualKey,mKeyModifiers);
+                break;
 
             case SDL_MOUSEBUTTONDOWN:
             {
@@ -1787,7 +1851,7 @@ void LLWindowSDL::gatherInput()
                 LLCoordWindow winCoord(event.button.x, event.button.y);
                 LLCoordGL openGlCoord;
                 convertCoords(winCoord, &openGlCoord);
-		MASK mask = gKeyboard->currentMask(TRUE);
+                MASK mask = gKeyboard->currentMask(TRUE);
 
                 if (event.button.button == SDL_BUTTON_LEFT)   // SDL doesn't manage double clicking...
                 {
@@ -1799,7 +1863,7 @@ void LLWindowSDL::gatherInput()
                         if (++leftClick >= 2)
                         {
                             leftClick = 0;
-			    isDoubleClick = true;
+                            isDoubleClick = true;
                         }
                     }
                     lastLeftDown = now;
@@ -1814,7 +1878,7 @@ void LLWindowSDL::gatherInput()
                         if (++rightClick >= 2)
                         {
                             rightClick = 0;
-    					    isDoubleClick = true;
+                            isDoubleClick = true;
                         }
                     }
                     lastRightDown = now;
@@ -1823,24 +1887,24 @@ void LLWindowSDL::gatherInput()
                 if (event.button.button == SDL_BUTTON_LEFT)  // left
                 {
                     if (isDoubleClick)
-				        mCallbacks->handleDoubleClick(this, openGlCoord, mask);
+                        mCallbacks->handleDoubleClick(this, openGlCoord, mask);
                     else
-    				    mCallbacks->handleMouseDown(this, openGlCoord, mask);
+                        mCallbacks->handleMouseDown(this, openGlCoord, mask);
                 }
 
                 else if (event.button.button == SDL_BUTTON_RIGHT)  // right
                 {
-			mCallbacks->handleRightMouseDown(this, openGlCoord, mask);
+                    mCallbacks->handleRightMouseDown(this, openGlCoord, mask);
                 }
 
                 else if (event.button.button == SDL_BUTTON_MIDDLE)  // middle
-				{
-				    mCallbacks->handleMiddleMouseDown(this, openGlCoord, mask);
-				}
+                {
+                    mCallbacks->handleMiddleMouseDown(this, openGlCoord, mask);
+                }
                 else if (event.button.button == 4)  // mousewheel up...thanks to X11 for making SDL consider these "buttons".
-					mCallbacks->handleScrollWheel(this, -1);
+                    mCallbacks->handleScrollWheel(this, -1);
                 else if (event.button.button == 5)  // mousewheel down...thanks to X11 for making SDL consider these "buttons".
-					mCallbacks->handleScrollWheel(this, 1);
+                    mCallbacks->handleScrollWheel(this, 1);
 
                 break;
             }
@@ -1850,365 +1914,346 @@ void LLWindowSDL::gatherInput()
                 LLCoordWindow winCoord(event.button.x, event.button.y);
                 LLCoordGL openGlCoord;
                 convertCoords(winCoord, &openGlCoord);
-		MASK mask = gKeyboard->currentMask(TRUE);
+                MASK mask = gKeyboard->currentMask(TRUE);
 
                 if (event.button.button == SDL_BUTTON_LEFT)  // left
-			mCallbacks->handleMouseUp(this, openGlCoord, mask);
+                    mCallbacks->handleMouseUp(this, openGlCoord, mask);
                 else if (event.button.button == SDL_BUTTON_RIGHT)  // right
-			mCallbacks->handleRightMouseUp(this, openGlCoord, mask);
+                    mCallbacks->handleRightMouseUp(this, openGlCoord, mask);
                 else if (event.button.button == SDL_BUTTON_MIDDLE)  // middle
-			mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask);
+                    mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask);
                 // don't handle mousewheel here...
 
                 break;
             }
 
-            case SDL_VIDEOEXPOSE:  // VIDEOEXPOSE doesn't specify the damage, but hey, it's OpenGL...repaint the whole thing!
-			    mCallbacks->handlePaint(this, 0, 0, mWindow->w, mWindow->h);
-                break;
-
-            case SDL_VIDEORESIZE:  // *FIX: handle this?
+            case SDL_WINDOWEVENT:  // *FIX: handle this?
             {
-		LL_INFOS() << "Handling a resize event: " << event.resize.w <<
-			"x" << event.resize.h << LL_ENDL;
-
-		S32 width = llmax(event.resize.w, (S32)mMinWindowWidth);
-		S32 height = llmax(event.resize.h, (S32)mMinWindowHeight);
-
-		// *FIX: I'm not sure this is necessary!
-		mWindow = SDL_SetVideoMode(width, height, 32, mSDLFlags);
-		if (!mWindow)
-		{
-			// *FIX: More informative dialog?
-			LL_INFOS() << "Could not recreate context after resize! Quitting..." << LL_ENDL;
-			if(mCallbacks->handleCloseRequest(this))
-    			{
-    				// Get the app to initiate cleanup.
-    				mCallbacks->handleQuit(this);
-    				// The app is responsible for calling destroyWindow when done with GL
-    			}
-                break;
-		}
+                if( event.window.event == SDL_WINDOWEVENT_RESIZED
+                    /* || event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED*/ ) // <FS:ND> SDL_WINDOWEVENT_SIZE_CHANGED is followed by SDL_WINDOWEVENT_RESIZED, so handling one shall be enough
+                {
+                    LL_INFOS() << "Handling a resize event: " << event.window.data1 << "x" << event.window.data2 << LL_ENDL;
 
-		mCallbacks->handleResize(this, width, height);
-                break;
-            }
-            case SDL_ACTIVEEVENT:
-                if (event.active.state & SDL_APPINPUTFOCUS)
+                    S32 width = llmax(event.window.data1, (S32)mMinWindowWidth);
+                    S32 height = llmax(event.window.data2, (S32)mMinWindowHeight);
+                    mSurface = SDL_GetWindowSurface( mWindow );
+
+                    // *FIX: I'm not sure this is necessary!
+                    // <FS:ND> I think is is not
+                    // SDL_SetWindowSize(mWindow, width, height);
+                    //
+
+                    mCallbacks->handleResize(this, width, height);
+                }
+                else if( event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED ) // <FS:ND> What about SDL_WINDOWEVENT_ENTER (mouse focus)
                 {
-			// Note that for SDL (particularly on X11), keyboard
-			// and mouse focus are independent things.  Here we are
-			// tracking keyboard focus state changes.
-
-			// We have to do our own state massaging because SDL
-			// can send us two unfocus events in a row for example,
-			// which confuses the focus code [SL-24071].
-			if (event.active.gain != mHaveInputFocus)
-			{
-				mHaveInputFocus = !!event.active.gain;
-
-				if (mHaveInputFocus)
-					mCallbacks->handleFocus(this);
-				else
-					mCallbacks->handleFocusLost(this);
-			}
+                    // We have to do our own state massaging because SDL
+                    // can send us two unfocus events in a row for example,
+                    // which confuses the focus code [SL-24071].
+                    mHaveInputFocus = true;
+
+                    mCallbacks->handleFocus(this);
                 }
-                if (event.active.state & SDL_APPACTIVE)
+                else if( event.window.event == SDL_WINDOWEVENT_FOCUS_LOST ) // <FS:ND> What about SDL_WINDOWEVENT_LEAVE (mouse focus)
                 {
-			// Change in iconification/minimization state.
-			if ((!event.active.gain) != mIsMinimized)
-			{
-				mIsMinimized = (!event.active.gain);
-
-				mCallbacks->handleActivate(this, !mIsMinimized);
-				LL_INFOS() << "SDL deiconification state switched to " << BOOL(event.active.gain) << LL_ENDL;
-			}
-			else
-			{
-				LL_INFOS() << "Ignored bogus redundant SDL deiconification state switch to " << BOOL(event.active.gain) << LL_ENDL;
-			}
+                    // We have to do our own state massaging because SDL
+                    // can send us two unfocus events in a row for example,
+                    // which confuses the focus code [SL-24071].
+                    mHaveInputFocus = false;
+
+                    mCallbacks->handleFocusLost(this);
+                }
+                else if( event.window.event == SDL_WINDOWEVENT_MINIMIZED ||
+                         event.window.event == SDL_WINDOWEVENT_MAXIMIZED ||
+                         event.window.event == SDL_WINDOWEVENT_RESTORED ||
+                         event.window.event == SDL_WINDOWEVENT_EXPOSED ||
+                         event.window.event == SDL_WINDOWEVENT_SHOWN )
+                {
+                    mIsMinimized = (event.window.event == SDL_WINDOWEVENT_MINIMIZED);
+
+                    mCallbacks->handleActivate(this, !mIsMinimized);
+                    LL_INFOS() << "SDL deiconification state switched to " << mIsMinimized << LL_ENDL;
                 }
-                break;
 
+                break;
+            }
             case SDL_QUIT:
-			    if(mCallbacks->handleCloseRequest(this))
-    			{
-    				// Get the app to initiate cleanup.
-    				mCallbacks->handleQuit(this);
-    				// The app is responsible for calling destroyWindow when done with GL
-    			}
+                if(mCallbacks->handleCloseRequest(this))
+                {
+                    // Get the app to initiate cleanup.
+                    mCallbacks->handleQuit(this);
+                    // The app is responsible for calling destroyWindow when done with GL
+                }
+                break;
+            default:
+                //LL_INFOS() << "Unhandled SDL event type " << event.type << LL_ENDL;
                 break;
-	default:
-		//LL_INFOS() << "Unhandled SDL event type " << event.type << LL_ENDL;
-		break;
         }
     }
-	
-	updateCursor();
+
+    updateCursor();
 
 #if LL_X11
     // This is a good time to stop flashing the icon if our mFlashTimer has
     // expired.
     if (mFlashing && mFlashTimer.hasExpired())
     {
-	    x11_set_urgent(FALSE);
-	    mFlashing = FALSE;
+        x11_set_urgent(FALSE);
+        mFlashing = FALSE;
     }
 #endif // LL_X11
 }
 
 static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty)
 {
-	SDL_Cursor *sdlcursor = NULL;
-	SDL_Surface *bmpsurface;
-
-	// Load cursor pixel data from BMP file
-	bmpsurface = Load_BMP_Resource(filename);
-	if (bmpsurface && bmpsurface->w%8==0)
-	{
-		SDL_Surface *cursurface;
-		LL_DEBUGS() << "Loaded cursor file " << filename << " "
-			 << bmpsurface->w << "x" << bmpsurface->h << LL_ENDL;
-		cursurface = SDL_CreateRGBSurface (SDL_SWSURFACE,
-						   bmpsurface->w,
-						   bmpsurface->h,
-						   32,
-						   SDL_SwapLE32(0xFFU),
-						   SDL_SwapLE32(0xFF00U),
-						   SDL_SwapLE32(0xFF0000U),
-						   SDL_SwapLE32(0xFF000000U));
-		SDL_FillRect(cursurface, NULL, SDL_SwapLE32(0x00000000U));
-
-		// Blit the cursor pixel data onto a 32-bit RGBA surface so we
-		// only have to cope with processing one type of pixel format.
-		if (0 == SDL_BlitSurface(bmpsurface, NULL,
-					 cursurface, NULL))
-		{
-			// n.b. we already checked that width is a multiple of 8.
-			const int bitmap_bytes = (cursurface->w * cursurface->h) / 8;
-			unsigned char *cursor_data = new unsigned char[bitmap_bytes];
-			unsigned char *cursor_mask = new unsigned char[bitmap_bytes];
-			memset(cursor_data, 0, bitmap_bytes);
-			memset(cursor_mask, 0, bitmap_bytes);
-			int i,j;
-			// Walk the RGBA cursor pixel data, extracting both data and
-			// mask to build SDL-friendly cursor bitmaps from.  The mask
-			// is inferred by color-keying against 200,200,200
-			for (i=0; i<cursurface->h; ++i) {
-				for (j=0; j<cursurface->w; ++j) {
-					U8 *pixelp =
-						((U8*)cursurface->pixels)
-						+ cursurface->pitch * i
-						+ j*cursurface->format->BytesPerPixel;
-					U8 srcred = pixelp[0];
-					U8 srcgreen = pixelp[1];
-					U8 srcblue = pixelp[2];
-					BOOL mask_bit = (srcred != 200)
-						|| (srcgreen != 200)
-						|| (srcblue != 200);
-					BOOL data_bit = mask_bit && (srcgreen <= 80);//not 0x80
-					unsigned char bit_offset = (cursurface->w/8) * i
-						+ j/8;
-					cursor_data[bit_offset]	|= (data_bit) << (7 - (j&7));
-					cursor_mask[bit_offset]	|= (mask_bit) << (7 - (j&7));
-				}
-			}
-			sdlcursor = SDL_CreateCursor((Uint8*)cursor_data,
-						     (Uint8*)cursor_mask,
-						     cursurface->w, cursurface->h,
-						     hotx, hoty);
-			delete[] cursor_data;
-			delete[] cursor_mask;
-		} else {
-			LL_WARNS() << "CURSOR BLIT FAILURE, cursurface: " << cursurface << LL_ENDL;
-		}
-		SDL_FreeSurface(cursurface);
-		SDL_FreeSurface(bmpsurface);
-	} else {
-		LL_WARNS() << "CURSOR LOAD FAILURE " << filename << LL_ENDL;
-	}
-
-	return sdlcursor;
+    SDL_Cursor *sdlcursor = NULL;
+    SDL_Surface *bmpsurface;
+
+    // Load cursor pixel data from BMP file
+    bmpsurface = Load_BMP_Resource(filename);
+    if (bmpsurface && bmpsurface->w%8==0)
+    {
+        SDL_Surface *cursurface;
+        LL_DEBUGS() << "Loaded cursor file " << filename << " "
+                    << bmpsurface->w << "x" << bmpsurface->h << LL_ENDL;
+        cursurface = SDL_CreateRGBSurface (SDL_SWSURFACE,
+                                           bmpsurface->w,
+                                           bmpsurface->h,
+                                           32,
+                                           SDL_SwapLE32(0xFFU),
+                                           SDL_SwapLE32(0xFF00U),
+                                           SDL_SwapLE32(0xFF0000U),
+                                           SDL_SwapLE32(0xFF000000U));
+        SDL_FillRect(cursurface, NULL, SDL_SwapLE32(0x00000000U));
+
+        // Blit the cursor pixel data onto a 32-bit RGBA surface so we
+        // only have to cope with processing one type of pixel format.
+        if (0 == SDL_BlitSurface(bmpsurface, NULL,
+                                 cursurface, NULL))
+        {
+            // n.b. we already checked that width is a multiple of 8.
+            const int bitmap_bytes = (cursurface->w * cursurface->h) / 8;
+            unsigned char *cursor_data = new unsigned char[bitmap_bytes];
+            unsigned char *cursor_mask = new unsigned char[bitmap_bytes];
+            memset(cursor_data, 0, bitmap_bytes);
+            memset(cursor_mask, 0, bitmap_bytes);
+            int i,j;
+            // Walk the RGBA cursor pixel data, extracting both data and
+            // mask to build SDL-friendly cursor bitmaps from.  The mask
+            // is inferred by color-keying against 200,200,200
+            for (i=0; i<cursurface->h; ++i) {
+                for (j=0; j<cursurface->w; ++j) {
+                    U8 *pixelp =
+                            ((U8*)cursurface->pixels)
+                            + cursurface->pitch * i
+                            + j*cursurface->format->BytesPerPixel;
+                    U8 srcred = pixelp[0];
+                    U8 srcgreen = pixelp[1];
+                    U8 srcblue = pixelp[2];
+                    BOOL mask_bit = (srcred != 200)
+                                    || (srcgreen != 200)
+                                    || (srcblue != 200);
+                    BOOL data_bit = mask_bit && (srcgreen <= 80);//not 0x80
+                    unsigned char bit_offset = (cursurface->w/8) * i
+                                               + j/8;
+                    cursor_data[bit_offset]	|= (data_bit) << (7 - (j&7));
+                    cursor_mask[bit_offset]	|= (mask_bit) << (7 - (j&7));
+                }
+            }
+            sdlcursor = SDL_CreateCursor((Uint8*)cursor_data,
+                                         (Uint8*)cursor_mask,
+                                         cursurface->w, cursurface->h,
+                                         hotx, hoty);
+            delete[] cursor_data;
+            delete[] cursor_mask;
+        } else {
+            LL_WARNS() << "CURSOR BLIT FAILURE, cursurface: " << cursurface << LL_ENDL;
+        }
+        SDL_FreeSurface(cursurface);
+        SDL_FreeSurface(bmpsurface);
+    } else {
+        LL_WARNS() << "CURSOR LOAD FAILURE " << filename << LL_ENDL;
+    }
+
+    return sdlcursor;
 }
 
 void LLWindowSDL::updateCursor()
 {
-	if (ATIbug) {
-		// cursor-updating is very flaky when this bug is
-		// present; do nothing.
-		return;
-	}
-
-	if (mCurrentCursor != mNextCursor)
-	{
-		if (mNextCursor < UI_CURSOR_COUNT)
-		{
-			SDL_Cursor *sdlcursor = mSDLCursors[mNextCursor];
-			// Try to default to the arrow for any cursors that
-			// did not load correctly.
-			if (!sdlcursor && mSDLCursors[UI_CURSOR_ARROW])
-				sdlcursor = mSDLCursors[UI_CURSOR_ARROW];
-			if (sdlcursor)
-				SDL_SetCursor(sdlcursor);
-		} else {
-			LL_WARNS() << "Tried to set invalid cursor number " << mNextCursor << LL_ENDL;
-		}
-		mCurrentCursor = mNextCursor;
-	}
+    if (ATIbug) {
+        // cursor-updating is very flaky when this bug is
+        // present; do nothing.
+        return;
+    }
+
+    if (mCurrentCursor != mNextCursor)
+    {
+        if (mNextCursor < UI_CURSOR_COUNT)
+        {
+            SDL_Cursor *sdlcursor = mSDLCursors[mNextCursor];
+            // Try to default to the arrow for any cursors that
+            // did not load correctly.
+            if (!sdlcursor && mSDLCursors[UI_CURSOR_ARROW])
+                sdlcursor = mSDLCursors[UI_CURSOR_ARROW];
+            if (sdlcursor)
+                SDL_SetCursor(sdlcursor);
+        } else {
+            LL_WARNS() << "Tried to set invalid cursor number " << mNextCursor << LL_ENDL;
+        }
+        mCurrentCursor = mNextCursor;
+    }
 }
 
 void LLWindowSDL::initCursors()
 {
-	int i;
-	// Blank the cursor pointer array for those we may miss.
-	for (i=0; i<UI_CURSOR_COUNT; ++i)
-	{
-		mSDLCursors[i] = NULL;
-	}
-	// Pre-make an SDL cursor for each of the known cursor types.
-	// We hardcode the hotspots - to avoid that we'd have to write
-	// a .cur file loader.
-	// NOTE: SDL doesn't load RLE-compressed BMP files.
-	mSDLCursors[UI_CURSOR_ARROW] = makeSDLCursorFromBMP("llarrow.BMP",0,0);
-	mSDLCursors[UI_CURSOR_WAIT] = makeSDLCursorFromBMP("wait.BMP",12,15);
-	mSDLCursors[UI_CURSOR_HAND] = makeSDLCursorFromBMP("hand.BMP",7,10);
-	mSDLCursors[UI_CURSOR_IBEAM] = makeSDLCursorFromBMP("ibeam.BMP",15,16);
-	mSDLCursors[UI_CURSOR_CROSS] = makeSDLCursorFromBMP("cross.BMP",16,14);
-	mSDLCursors[UI_CURSOR_SIZENWSE] = makeSDLCursorFromBMP("sizenwse.BMP",14,17);
-	mSDLCursors[UI_CURSOR_SIZENESW] = makeSDLCursorFromBMP("sizenesw.BMP",17,17);
-	mSDLCursors[UI_CURSOR_SIZEWE] = makeSDLCursorFromBMP("sizewe.BMP",16,14);
-	mSDLCursors[UI_CURSOR_SIZENS] = makeSDLCursorFromBMP("sizens.BMP",17,16);
+    int i;
+    // Blank the cursor pointer array for those we may miss.
+    for (i=0; i<UI_CURSOR_COUNT; ++i)
+    {
+        mSDLCursors[i] = NULL;
+    }
+    // Pre-make an SDL cursor for each of the known cursor types.
+    // We hardcode the hotspots - to avoid that we'd have to write
+    // a .cur file loader.
+    // NOTE: SDL doesn't load RLE-compressed BMP files.
+    mSDLCursors[UI_CURSOR_ARROW] = makeSDLCursorFromBMP("llarrow.BMP",0,0);
+    mSDLCursors[UI_CURSOR_WAIT] = makeSDLCursorFromBMP("wait.BMP",12,15);
+    mSDLCursors[UI_CURSOR_HAND] = makeSDLCursorFromBMP("hand.BMP",7,10);
+    mSDLCursors[UI_CURSOR_IBEAM] = makeSDLCursorFromBMP("ibeam.BMP",15,16);
+    mSDLCursors[UI_CURSOR_CROSS] = makeSDLCursorFromBMP("cross.BMP",16,14);
+    mSDLCursors[UI_CURSOR_SIZENWSE] = makeSDLCursorFromBMP("sizenwse.BMP",14,17);
+    mSDLCursors[UI_CURSOR_SIZENESW] = makeSDLCursorFromBMP("sizenesw.BMP",17,17);
+    mSDLCursors[UI_CURSOR_SIZEWE] = makeSDLCursorFromBMP("sizewe.BMP",16,14);
+    mSDLCursors[UI_CURSOR_SIZENS] = makeSDLCursorFromBMP("sizens.BMP",17,16);
     mSDLCursors[UI_CURSOR_SIZEALL] = makeSDLCursorFromBMP("sizeall.BMP", 17, 17);
-	mSDLCursors[UI_CURSOR_NO] = makeSDLCursorFromBMP("llno.BMP",8,8);
-	mSDLCursors[UI_CURSOR_WORKING] = makeSDLCursorFromBMP("working.BMP",12,15);
-	mSDLCursors[UI_CURSOR_TOOLGRAB] = makeSDLCursorFromBMP("lltoolgrab.BMP",2,13);
-	mSDLCursors[UI_CURSOR_TOOLLAND] = makeSDLCursorFromBMP("lltoolland.BMP",1,6);
-	mSDLCursors[UI_CURSOR_TOOLFOCUS] = makeSDLCursorFromBMP("lltoolfocus.BMP",8,5);
-	mSDLCursors[UI_CURSOR_TOOLCREATE] = makeSDLCursorFromBMP("lltoolcreate.BMP",7,7);
-	mSDLCursors[UI_CURSOR_ARROWDRAG] = makeSDLCursorFromBMP("arrowdrag.BMP",0,0);
-	mSDLCursors[UI_CURSOR_ARROWCOPY] = makeSDLCursorFromBMP("arrowcop.BMP",0,0);
-	mSDLCursors[UI_CURSOR_ARROWDRAGMULTI] = makeSDLCursorFromBMP("llarrowdragmulti.BMP",0,0);
-	mSDLCursors[UI_CURSOR_ARROWCOPYMULTI] = makeSDLCursorFromBMP("arrowcopmulti.BMP",0,0);
-	mSDLCursors[UI_CURSOR_NOLOCKED] = makeSDLCursorFromBMP("llnolocked.BMP",8,8);
-	mSDLCursors[UI_CURSOR_ARROWLOCKED] = makeSDLCursorFromBMP("llarrowlocked.BMP",0,0);
-	mSDLCursors[UI_CURSOR_GRABLOCKED] = makeSDLCursorFromBMP("llgrablocked.BMP",2,13);
-	mSDLCursors[UI_CURSOR_TOOLTRANSLATE] = makeSDLCursorFromBMP("lltooltranslate.BMP",0,0);
-	mSDLCursors[UI_CURSOR_TOOLROTATE] = makeSDLCursorFromBMP("lltoolrotate.BMP",0,0);
-	mSDLCursors[UI_CURSOR_TOOLSCALE] = makeSDLCursorFromBMP("lltoolscale.BMP",0,0);
-	mSDLCursors[UI_CURSOR_TOOLCAMERA] = makeSDLCursorFromBMP("lltoolcamera.BMP",7,5);
-	mSDLCursors[UI_CURSOR_TOOLPAN] = makeSDLCursorFromBMP("lltoolpan.BMP",7,5);
-	mSDLCursors[UI_CURSOR_TOOLZOOMIN] = makeSDLCursorFromBMP("lltoolzoomin.BMP",7,5);
+    mSDLCursors[UI_CURSOR_NO] = makeSDLCursorFromBMP("llno.BMP",8,8);
+    mSDLCursors[UI_CURSOR_WORKING] = makeSDLCursorFromBMP("working.BMP",12,15);
+    mSDLCursors[UI_CURSOR_TOOLGRAB] = makeSDLCursorFromBMP("lltoolgrab.BMP",2,13);
+    mSDLCursors[UI_CURSOR_TOOLLAND] = makeSDLCursorFromBMP("lltoolland.BMP",1,6);
+    mSDLCursors[UI_CURSOR_TOOLFOCUS] = makeSDLCursorFromBMP("lltoolfocus.BMP",8,5);
+    mSDLCursors[UI_CURSOR_TOOLCREATE] = makeSDLCursorFromBMP("lltoolcreate.BMP",7,7);
+    mSDLCursors[UI_CURSOR_ARROWDRAG] = makeSDLCursorFromBMP("arrowdrag.BMP",0,0);
+    mSDLCursors[UI_CURSOR_ARROWCOPY] = makeSDLCursorFromBMP("arrowcop.BMP",0,0);
+    mSDLCursors[UI_CURSOR_ARROWDRAGMULTI] = makeSDLCursorFromBMP("llarrowdragmulti.BMP",0,0);
+    mSDLCursors[UI_CURSOR_ARROWCOPYMULTI] = makeSDLCursorFromBMP("arrowcopmulti.BMP",0,0);
+    mSDLCursors[UI_CURSOR_NOLOCKED] = makeSDLCursorFromBMP("llnolocked.BMP",8,8);
+    mSDLCursors[UI_CURSOR_ARROWLOCKED] = makeSDLCursorFromBMP("llarrowlocked.BMP",0,0);
+    mSDLCursors[UI_CURSOR_GRABLOCKED] = makeSDLCursorFromBMP("llgrablocked.BMP",2,13);
+    mSDLCursors[UI_CURSOR_TOOLTRANSLATE] = makeSDLCursorFromBMP("lltooltranslate.BMP",0,0);
+    mSDLCursors[UI_CURSOR_TOOLROTATE] = makeSDLCursorFromBMP("lltoolrotate.BMP",0,0);
+    mSDLCursors[UI_CURSOR_TOOLSCALE] = makeSDLCursorFromBMP("lltoolscale.BMP",0,0);
+    mSDLCursors[UI_CURSOR_TOOLCAMERA] = makeSDLCursorFromBMP("lltoolcamera.BMP",7,5);
+    mSDLCursors[UI_CURSOR_TOOLPAN] = makeSDLCursorFromBMP("lltoolpan.BMP",7,5);
+    mSDLCursors[UI_CURSOR_TOOLZOOMIN] = makeSDLCursorFromBMP("lltoolzoomin.BMP",7,5);
     mSDLCursors[UI_CURSOR_TOOLZOOMOUT] = makeSDLCursorFromBMP("lltoolzoomout.BMP", 7, 5);
-	mSDLCursors[UI_CURSOR_TOOLPICKOBJECT3] = makeSDLCursorFromBMP("toolpickobject3.BMP",0,0);
-	mSDLCursors[UI_CURSOR_TOOLPLAY] = makeSDLCursorFromBMP("toolplay.BMP",0,0);
-	mSDLCursors[UI_CURSOR_TOOLPAUSE] = makeSDLCursorFromBMP("toolpause.BMP",0,0);
-	mSDLCursors[UI_CURSOR_TOOLMEDIAOPEN] = makeSDLCursorFromBMP("toolmediaopen.BMP",0,0);
-	mSDLCursors[UI_CURSOR_PIPETTE] = makeSDLCursorFromBMP("lltoolpipette.BMP",2,28);
-	mSDLCursors[UI_CURSOR_TOOLSIT] = makeSDLCursorFromBMP("toolsit.BMP",20,15);
-	mSDLCursors[UI_CURSOR_TOOLBUY] = makeSDLCursorFromBMP("toolbuy.BMP",20,15);
-	mSDLCursors[UI_CURSOR_TOOLOPEN] = makeSDLCursorFromBMP("toolopen.BMP",20,15);
-	mSDLCursors[UI_CURSOR_TOOLPATHFINDING] = makeSDLCursorFromBMP("lltoolpathfinding.BMP", 16, 16);
-	mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_START] = makeSDLCursorFromBMP("lltoolpathfindingpathstart.BMP", 16, 16);
-	mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD] = makeSDLCursorFromBMP("lltoolpathfindingpathstartadd.BMP", 16, 16);
-	mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_END] = makeSDLCursorFromBMP("lltoolpathfindingpathend.BMP", 16, 16);
-	mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD] = makeSDLCursorFromBMP("lltoolpathfindingpathendadd.BMP", 16, 16);
-	mSDLCursors[UI_CURSOR_TOOLNO] = makeSDLCursorFromBMP("llno.BMP",8,8);
-
-	if (getenv("LL_ATI_MOUSE_CURSOR_BUG") != NULL) {
-		LL_INFOS() << "Disabling cursor updating due to LL_ATI_MOUSE_CURSOR_BUG" << LL_ENDL;
-		ATIbug = true;
-	}
+    mSDLCursors[UI_CURSOR_TOOLPICKOBJECT3] = makeSDLCursorFromBMP("toolpickobject3.BMP",0,0);
+    mSDLCursors[UI_CURSOR_TOOLPLAY] = makeSDLCursorFromBMP("toolplay.BMP",0,0);
+    mSDLCursors[UI_CURSOR_TOOLPAUSE] = makeSDLCursorFromBMP("toolpause.BMP",0,0);
+    mSDLCursors[UI_CURSOR_TOOLMEDIAOPEN] = makeSDLCursorFromBMP("toolmediaopen.BMP",0,0);
+    mSDLCursors[UI_CURSOR_PIPETTE] = makeSDLCursorFromBMP("lltoolpipette.BMP",2,28);
+    mSDLCursors[UI_CURSOR_TOOLSIT] = makeSDLCursorFromBMP("toolsit.BMP",20,15);
+    mSDLCursors[UI_CURSOR_TOOLBUY] = makeSDLCursorFromBMP("toolbuy.BMP",20,15);
+    mSDLCursors[UI_CURSOR_TOOLOPEN] = makeSDLCursorFromBMP("toolopen.BMP",20,15);
+    mSDLCursors[UI_CURSOR_TOOLPATHFINDING] = makeSDLCursorFromBMP("lltoolpathfinding.BMP", 16, 16);
+    mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_START] = makeSDLCursorFromBMP("lltoolpathfindingpathstart.BMP", 16, 16);
+    mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD] = makeSDLCursorFromBMP("lltoolpathfindingpathstartadd.BMP", 16, 16);
+    mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_END] = makeSDLCursorFromBMP("lltoolpathfindingpathend.BMP", 16, 16);
+    mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD] = makeSDLCursorFromBMP("lltoolpathfindingpathendadd.BMP", 16, 16);
+    mSDLCursors[UI_CURSOR_TOOLNO] = makeSDLCursorFromBMP("llno.BMP",8,8);
+
+    if (getenv("LL_ATI_MOUSE_CURSOR_BUG") != NULL) {
+        LL_INFOS() << "Disabling cursor updating due to LL_ATI_MOUSE_CURSOR_BUG" << LL_ENDL;
+        ATIbug = true;
+    }
 }
 
 void LLWindowSDL::quitCursors()
 {
-	int i;
-	if (mWindow)
-	{
-		for (i=0; i<UI_CURSOR_COUNT; ++i)
-		{
-			if (mSDLCursors[i])
-			{
-				SDL_FreeCursor(mSDLCursors[i]);
-				mSDLCursors[i] = NULL;
-			}
-		}
-	} else {
-		// SDL doesn't refcount cursors, so if the window has
-		// already been destroyed then the cursors have gone with it.
-		LL_INFOS() << "Skipping quitCursors: mWindow already gone." << LL_ENDL;
-		for (i=0; i<UI_CURSOR_COUNT; ++i)
-			mSDLCursors[i] = NULL;
-	}
+    int i;
+    if (mWindow)
+    {
+        for (i=0; i<UI_CURSOR_COUNT; ++i)
+        {
+            if (mSDLCursors[i])
+            {
+                SDL_FreeCursor(mSDLCursors[i]);
+                mSDLCursors[i] = NULL;
+            }
+        }
+    } else {
+        // SDL doesn't refcount cursors, so if the window has
+        // already been destroyed then the cursors have gone with it.
+        LL_INFOS() << "Skipping quitCursors: mWindow already gone." << LL_ENDL;
+        for (i=0; i<UI_CURSOR_COUNT; ++i)
+            mSDLCursors[i] = NULL;
+    }
 }
 
 void LLWindowSDL::captureMouse()
 {
-	// SDL already enforces the semantics that captureMouse is
-	// used for, i.e. that we continue to get mouse events as long
-	// as a button is down regardless of whether we left the
-	// window, and in a less obnoxious way than SDL_WM_GrabInput	
-	// which would confine the cursor to the window too.
+    // SDL already enforces the semantics that captureMouse is
+    // used for, i.e. that we continue to get mouse events as long
+    // as a button is down regardless of whether we left the
+    // window, and in a less obnoxious way than SDL_WM_GrabInput
+    // which would confine the cursor to the window too.
 
-	LL_DEBUGS() << "LLWindowSDL::captureMouse" << LL_ENDL;
+    LL_DEBUGS() << "LLWindowSDL::captureMouse" << LL_ENDL;
 }
 
 void LLWindowSDL::releaseMouse()
 {
-	// see LWindowSDL::captureMouse()
-	
-	LL_DEBUGS() << "LLWindowSDL::releaseMouse" << LL_ENDL;
+    // see LWindowSDL::captureMouse()
+
+    LL_DEBUGS() << "LLWindowSDL::releaseMouse" << LL_ENDL;
 }
 
 void LLWindowSDL::hideCursor()
 {
-	if(!mCursorHidden)
-	{
-		// LL_INFOS() << "hideCursor: hiding" << LL_ENDL;
-		mCursorHidden = TRUE;
-		mHideCursorPermanent = TRUE;
-		SDL_ShowCursor(0);
-	}
-	else
-	{
-		// LL_INFOS() << "hideCursor: already hidden" << LL_ENDL;
-	}
+    if(!mCursorHidden)
+    {
+        // LL_INFOS() << "hideCursor: hiding" << LL_ENDL;
+        mCursorHidden = TRUE;
+        mHideCursorPermanent = TRUE;
+        SDL_ShowCursor(0);
+    }
+    else
+    {
+        // LL_INFOS() << "hideCursor: already hidden" << LL_ENDL;
+    }
 }
 
 void LLWindowSDL::showCursor()
 {
-	if(mCursorHidden)
-	{
-		// LL_INFOS() << "showCursor: showing" << LL_ENDL;
-		mCursorHidden = FALSE;
-		mHideCursorPermanent = FALSE;
-		SDL_ShowCursor(1);
-	}
-	else
-	{
-		// LL_INFOS() << "showCursor: already visible" << LL_ENDL;
-	}
+    if(mCursorHidden)
+    {
+        // LL_INFOS() << "showCursor: showing" << LL_ENDL;
+        mCursorHidden = FALSE;
+        mHideCursorPermanent = FALSE;
+        SDL_ShowCursor(1);
+    }
+    else
+    {
+        // LL_INFOS() << "showCursor: already visible" << LL_ENDL;
+    }
 }
 
 void LLWindowSDL::showCursorFromMouseMove()
 {
-	if (!mHideCursorPermanent)
-	{
-		showCursor();
-	}
+    if (!mHideCursorPermanent)
+    {
+        showCursor();
+    }
 }
 
 void LLWindowSDL::hideCursorUntilMouseMove()
 {
-	if (!mHideCursorPermanent)
-	{
-		hideCursor();
-		mHideCursorPermanent = FALSE;
-	}
+    if (!mHideCursorPermanent)
+    {
+        hideCursor();
+        mHideCursorPermanent = FALSE;
+    }
 }
 
-
-
 //
 // LLSplashScreenSDL - I don't think we'll bother to implement this; it's
 // fairly obsolete at this point.
@@ -2233,272 +2278,128 @@ void LLSplashScreenSDL::hideImpl()
 {
 }
 
+S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 type)
+{
+    SDL_MessageBoxData oData = { SDL_MESSAGEBOX_INFORMATION, nullptr, caption.c_str(), text.c_str(), 0, nullptr, nullptr };
+    SDL_MessageBoxButtonData btnOk[] = {{SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, OSBTN_OK, "OK" }};
+    SDL_MessageBoxButtonData btnOkCancel [] =  {{SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, OSBTN_OK, "OK" }, {SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, OSBTN_CANCEL, "Cancel"} };
+    SDL_MessageBoxButtonData btnYesNo[] = { {SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, OSBTN_YES, "Yes" }, {SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, OSBTN_NO, "No"} };
 
+    switch (type)
+    {
+        default:
+        case OSMB_OK:
+            oData.flags = SDL_MESSAGEBOX_WARNING;
+            oData.buttons = btnOk;
+            oData.numbuttons = 1;
+            break;
+        case OSMB_OKCANCEL:
+            oData.flags = SDL_MESSAGEBOX_INFORMATION;
+            oData.buttons = btnOkCancel;
+            oData.numbuttons = 2;
+            break;
+        case OSMB_YESNO:
+            oData.flags = SDL_MESSAGEBOX_INFORMATION;
+            oData.buttons = btnYesNo;
+            oData.numbuttons = 2;
+            break;
+    }
 
-#if LL_GTK
-static void response_callback (GtkDialog *dialog,
-			       gint       arg1,
-			       gpointer   user_data)
-{
-	gint *response = (gint*)user_data;
-	*response = arg1;
-	gtk_widget_destroy(GTK_WIDGET(dialog));
-	gtk_main_quit();
+    int btn{0};
+    if( 0 == SDL_ShowMessageBox( &oData, &btn ) )
+        return btn;
+    return OSBTN_CANCEL;
 }
 
-S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 type)
+BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b)
 {
-	S32 rtn = OSBTN_CANCEL;
-
-	if(gWindowImplementation != NULL)
-		gWindowImplementation->beforeDialog();
-
-	if (LLWindowSDL::ll_try_gtk_init())
-	{
-		GtkWidget *win = NULL;
-
-		LL_INFOS() << "Creating a dialog because we're in windowed mode and GTK is happy." << LL_ENDL;
-		
-		GtkDialogFlags flags = GTK_DIALOG_MODAL;
-		GtkMessageType messagetype;
-		GtkButtonsType buttons;
-		switch (type)
-		{
-		default:
-		case OSMB_OK:
-			messagetype = GTK_MESSAGE_WARNING;
-			buttons = GTK_BUTTONS_OK;
-			break;
-		case OSMB_OKCANCEL:
-			messagetype = GTK_MESSAGE_QUESTION;
-			buttons = GTK_BUTTONS_OK_CANCEL;
-			break;
-		case OSMB_YESNO:
-			messagetype = GTK_MESSAGE_QUESTION;
-			buttons = GTK_BUTTONS_YES_NO;
-			break;
-		}
-		win = gtk_message_dialog_new(NULL, flags, messagetype, buttons, "%s",
-									 text.c_str());
-
-# if LL_X11
-		// Make GTK tell the window manager to associate this
-		// dialog with our non-GTK SDL window, which should try
-		// to keep it on top etc.
-		if (gWindowImplementation &&
-		    gWindowImplementation->mSDL_XWindowID != None)
-		{
-			gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin
-			GdkWindow *gdkwin = gdk_window_foreign_new(gWindowImplementation->mSDL_XWindowID);
-			gdk_window_set_transient_for(GTK_WIDGET(win)->window,
-						     gdkwin);
-		}
-# endif //LL_X11
-
-		gtk_window_set_position(GTK_WINDOW(win),
-					GTK_WIN_POS_CENTER_ON_PARENT);
-
-		gtk_window_set_type_hint(GTK_WINDOW(win),
-					 GDK_WINDOW_TYPE_HINT_DIALOG);
-
-		if (!caption.empty())
-			gtk_window_set_title(GTK_WINDOW(win), caption.c_str());
-
-		gint response = GTK_RESPONSE_NONE;
-		g_signal_connect (win,
-				  "response", 
-				  G_CALLBACK (response_callback),
-				  &response);
-
-		// we should be able to use a gtk_dialog_run(), but it's
-		// apparently not written to exist in a world without a higher
-		// gtk_main(), so we manage its signal/destruction outselves.
-		gtk_widget_show_all (win);
-		gtk_main();
-
-		//LL_INFOS() << "response: " << response << LL_ENDL;
-		switch (response)
-		{
-		case GTK_RESPONSE_OK:     rtn = OSBTN_OK; break;
-		case GTK_RESPONSE_YES:    rtn = OSBTN_YES; break;
-		case GTK_RESPONSE_NO:     rtn = OSBTN_NO; break;
-		case GTK_RESPONSE_APPLY:  rtn = OSBTN_OK; break;
-		case GTK_RESPONSE_NONE:
-		case GTK_RESPONSE_CANCEL:
-		case GTK_RESPONSE_CLOSE:
-		case GTK_RESPONSE_DELETE_EVENT:
-		default: rtn = OSBTN_CANCEL;
-		}
-	}
-	else
-	{
-		LL_INFOS() << "MSGBOX: " << caption << ": " << text << LL_ENDL;
-		LL_INFOS() << "Skipping dialog because we're in fullscreen mode or GTK is not happy." << LL_ENDL;
-		rtn = OSBTN_OK;
-	}
-
-	if(gWindowImplementation != NULL)
-		gWindowImplementation->afterDialog();
-
-	return rtn;
-}
-
-static void color_changed_callback(GtkWidget *widget,
-				   gpointer user_data)
-{
-	GtkColorSelection *colorsel = GTK_COLOR_SELECTION(widget);
-	GdkColor *colorp = (GdkColor*)user_data;
-	
-	gtk_color_selection_get_current_color(colorsel, colorp);
+    return (FALSE);
 }
 
-
 /*
         Make the raw keyboard data available - used to poke through to LLQtWebKit so
         that Qt/Webkit has access to the virtual keycodes etc. that it needs
 */
 LLSD LLWindowSDL::getNativeKeyData()
 {
-        LLSD result = LLSD::emptyMap();
-
-	U32 modifiers = 0; // pretend-native modifiers... oh what a tangled web we weave!
-
-	// we go through so many levels of device abstraction that I can't really guess
-	// what a plugin under GDK under Qt under SL under SDL under X11 considers
-	// a 'native' modifier mask.  this has been sort of reverse-engineered... they *appear*
-	// to match GDK consts, but that may be co-incidence.
-	modifiers |= (mKeyModifiers & KMOD_LSHIFT) ? 0x0001 : 0;
-	modifiers |= (mKeyModifiers & KMOD_RSHIFT) ? 0x0001 : 0;// munge these into the same shift
-	modifiers |= (mKeyModifiers & KMOD_CAPS)   ? 0x0002 : 0;
-	modifiers |= (mKeyModifiers & KMOD_LCTRL)  ? 0x0004 : 0;
-	modifiers |= (mKeyModifiers & KMOD_RCTRL)  ? 0x0004 : 0;// munge these into the same ctrl
-	modifiers |= (mKeyModifiers & KMOD_LALT)   ? 0x0008 : 0;// untested
-	modifiers |= (mKeyModifiers & KMOD_RALT)   ? 0x0008 : 0;// untested
-	// *todo: test ALTs - I don't have a case for testing these.  Do you?
-	// *todo: NUM? - I don't care enough right now (and it's not a GDK modifier).
-
-        result["scan_code"] = (S32)mKeyScanCode;
-        result["virtual_key"] = (S32)mKeyVirtualKey;
-	result["modifiers"] = (S32)modifiers;
-
-        return result;
-}
-
-
-BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b)
-{
-	BOOL rtn = FALSE;
+    LLSD result = LLSD::emptyMap();
 
-	beforeDialog();
+    U32 modifiers = 0; // pretend-native modifiers... oh what a tangled web we weave!
 
-	if (ll_try_gtk_init())
-	{
-		GtkWidget *win = NULL;
+    // we go through so many levels of device abstraction that I can't really guess
+    // what a plugin under GDK under Qt under SL under SDL under X11 considers
+    // a 'native' modifier mask.  this has been sort of reverse-engineered... they *appear*
+    // to match GDK consts, but that may be co-incidence.
+    modifiers |= (mKeyModifiers & KMOD_LSHIFT) ? 0x0001 : 0;
+    modifiers |= (mKeyModifiers & KMOD_RSHIFT) ? 0x0001 : 0;// munge these into the same shift
+    modifiers |= (mKeyModifiers & KMOD_CAPS)   ? 0x0002 : 0;
+    modifiers |= (mKeyModifiers & KMOD_LCTRL)  ? 0x0004 : 0;
+    modifiers |= (mKeyModifiers & KMOD_RCTRL)  ? 0x0004 : 0;// munge these into the same ctrl
+    modifiers |= (mKeyModifiers & KMOD_LALT)   ? 0x0008 : 0;// untested
+    modifiers |= (mKeyModifiers & KMOD_RALT)   ? 0x0008 : 0;// untested
+    // *todo: test ALTs - I don't have a case for testing these.  Do you?
+    // *todo: NUM? - I don't care enough right now (and it's not a GDK modifier).
 
-		win = gtk_color_selection_dialog_new(NULL);
-
-# if LL_X11
-		// Get GTK to tell the window manager to associate this
-		// dialog with our non-GTK SDL window, which should try
-		// to keep it on top etc.
-		if (mSDL_XWindowID != None)
-		{
-			gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin
-			GdkWindow *gdkwin = gdk_window_foreign_new(mSDL_XWindowID);
-			gdk_window_set_transient_for(GTK_WIDGET(win)->window,
-						     gdkwin);
-		}
-# endif //LL_X11
-
-		GtkColorSelection *colorsel = GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG(win)->colorsel);
-
-		GdkColor color, orig_color;
-		orig_color.pixel = 0;
-		orig_color.red = guint16(65535 * *r);
-		orig_color.green= guint16(65535 * *g);
-		orig_color.blue = guint16(65535 * *b);
-		color = orig_color;
-
-		gtk_color_selection_set_previous_color (colorsel, &color);
-		gtk_color_selection_set_current_color (colorsel, &color);
-		gtk_color_selection_set_has_palette (colorsel, TRUE);
-		gtk_color_selection_set_has_opacity_control(colorsel, FALSE);
-
-		gint response = GTK_RESPONSE_NONE;
-		g_signal_connect (win,
-				  "response", 
-				  G_CALLBACK (response_callback),
-				  &response);
-
-		g_signal_connect (G_OBJECT (colorsel), "color_changed",
-				  G_CALLBACK (color_changed_callback),
-				  &color);
-
-		gtk_window_set_modal(GTK_WINDOW(win), TRUE);
-		gtk_widget_show_all(win);
-		// hide the help button - we don't service it.
-		gtk_widget_hide(GTK_COLOR_SELECTION_DIALOG(win)->help_button);
-		gtk_main();
-
-		if (response == GTK_RESPONSE_OK &&
-		    (orig_color.red != color.red
-		     || orig_color.green != color.green
-		     || orig_color.blue != color.blue) )
-		{
-			*r = color.red / 65535.0f;
-			*g = color.green / 65535.0f;
-			*b = color.blue / 65535.0f;
-			rtn = TRUE;
-		}
-	}
-
-	afterDialog();
-
-	return rtn;
-}
-#else
-S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 type)
-{
-	LL_INFOS() << "MSGBOX: " << caption << ": " << text << LL_ENDL;
-	return 0;
-}
-
-BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b)
-{
-	return (FALSE);
+    result["virtual_key"] = (S32)mKeyVirtualKey;
+    result["virtual_key_win"] = (S32)LLKeyboardSDL::mapSDL2toWin( mKeyVirtualKey );
+    result["modifiers"] = (S32)modifiers;
+    result["input_type"] = mInputType;
+    return result;
 }
-#endif // LL_GTK
 
-#if LL_LINUX
+#if LL_LINUX || LL_SOLARIS
 // extracted from spawnWebBrowser for clarity and to eliminate
 //  compiler confusion regarding close(int fd) vs. LLWindow::close()
 void exec_cmd(const std::string& cmd, const std::string& arg)
 {
-	char* const argv[] = {(char*)cmd.c_str(), (char*)arg.c_str(), NULL};
-	fflush(NULL);
-	pid_t pid = fork();
-	if (pid == 0)
-	{ // child
-		// disconnect from stdin/stdout/stderr, or child will
-		// keep our output pipe undesirably alive if it outlives us.
-		close(0);
-		close(1);
-		close(2);
-		// end ourself by running the command
-		execv(cmd.c_str(), argv);	/* Flawfinder: ignore */
-		// if execv returns at all, there was a problem.
-		LL_WARNS() << "execv failure when trying to start " << cmd << LL_ENDL;
-		_exit(1); // _exit because we don't want atexit() clean-up!
-	} else {
-		if (pid > 0)
-		{
-			// parent - wait for child to die
-			int childExitStatus;
-			waitpid(pid, &childExitStatus, 0);
-		} else {
-			LL_WARNS() << "fork failure." << LL_ENDL;
-		}
-	}
+    char* const argv[] = {(char*)cmd.c_str(), (char*)arg.c_str(), NULL};
+    fflush(NULL);
+    pid_t pid = fork();
+    if (pid == 0)
+    { // child
+        // disconnect from stdin/stdout/stderr, or child will
+        // keep our output pipe undesirably alive if it outlives us.
+        // close(0);
+        // close(1);
+        // close(2);
+        // <FS:TS> Reopen stdin, stdout, and stderr to /dev/null.
+        //         It's good practice to always have those file
+        //         descriptors open to something, lest the exec'd
+        //         program actually try to use them.
+        FILE *result;
+        result = freopen("/dev/null","r",stdin);
+        if (result == NULL)
+        {
+            LL_WARNS() << "Error reopening stdin for web browser: "
+                       << strerror(errno) << LL_ENDL;
+        }
+        result = freopen("/dev/null","w",stdout);
+        if (result == NULL)
+        {
+            LL_WARNS() << "Error reopening stdout for web browser: "
+                       << strerror(errno) << LL_ENDL;
+        }
+        result = freopen("/dev/null","w",stderr);
+        if (result == NULL)
+        {
+            LL_WARNS() << "Error reopening stderr for web browser: "
+                       << strerror(errno) << LL_ENDL;
+        }
+        // end ourself by running the command
+        execv(cmd.c_str(), argv);	/* Flawfinder: ignore */
+        // if execv returns at all, there was a problem.
+        LL_WARNS() << "execv failure when trying to start " << cmd << LL_ENDL;
+        _exit(1); // _exit because we don't want atexit() clean-up!
+    } else {
+        if (pid > 0)
+        {
+            // parent - wait for child to die
+            int childExitStatus;
+            waitpid(pid, &childExitStatus, 0);
+        } else {
+            LL_WARNS() << "fork failure." << LL_ENDL;
+        }
+    }
 }
 #endif
 
@@ -2506,192 +2407,215 @@ void exec_cmd(const std::string& cmd, const std::string& arg)
 // Must begin with protocol identifier.
 void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async)
 {
-	bool found = false;
-	S32 i;
-	for (i = 0; i < gURLProtocolWhitelistCount; i++)
-	{
-		if (escaped_url.find(gURLProtocolWhitelist[i]) != std::string::npos)
-		{
-			found = true;
-			break;
-		}
-	}
-
-	if (!found)
-	{
-		LL_WARNS() << "spawn_web_browser called for url with protocol not on whitelist: " << escaped_url << LL_ENDL;
-		return;
-	}
-
-	LL_INFOS() << "spawn_web_browser: " << escaped_url << LL_ENDL;
-	
+    bool found = false;
+    S32 i;
+    for (i = 0; i < gURLProtocolWhitelistCount; i++)
+    {
+        if (escaped_url.find(gURLProtocolWhitelist[i]) != std::string::npos)
+        {
+            found = true;
+            break;
+        }
+    }
+
+    if (!found)
+    {
+        LL_WARNS() << "spawn_web_browser called for url with protocol not on whitelist: " << escaped_url << LL_ENDL;
+        return;
+    }
+
+    LL_INFOS() << "spawn_web_browser: " << escaped_url << LL_ENDL;
+
 #if LL_LINUX
 # if LL_X11
-	if (mSDL_Display)
-	{
-		maybe_lock_display();
-		// Just in case - before forking.
-		XSync(mSDL_Display, False);
-		maybe_unlock_display();
-	}
+    if (mSDL_Display)
+    {
+        maybe_lock_display();
+        // Just in case - before forking.
+        XSync(mSDL_Display, False);
+        maybe_unlock_display();
+    }
 # endif // LL_X11
 
-	std::string cmd, arg;
-	cmd  = gDirUtilp->getAppRODataDir();
-	cmd += gDirUtilp->getDirDelimiter();
-	cmd += "etc";
-	cmd += gDirUtilp->getDirDelimiter();
-	cmd += "launch_url.sh";
-	arg = escaped_url;
-	exec_cmd(cmd, arg);
+    std::string cmd, arg;
+    cmd  = gDirUtilp->getAppRODataDir();
+    cmd += gDirUtilp->getDirDelimiter();
+    cmd += "etc";
+    cmd += gDirUtilp->getDirDelimiter();
+    cmd += "launch_url.sh";
+    arg = escaped_url;
+    exec_cmd(cmd, arg);
 #endif // LL_LINUX
 
-	LL_INFOS() << "spawn_web_browser returning." << LL_ENDL;
+    LL_INFOS() << "spawn_web_browser returning." << LL_ENDL;
 }
 
+void LLWindowSDL::openFile(const std::string& file_name)
+{
+    spawnWebBrowser("file://"+file_name,TRUE);
+}
 
 void *LLWindowSDL::getPlatformWindow()
 {
-#if LL_GTK && LL_LLMOZLIB_ENABLED
-	if (LLWindowSDL::ll_try_gtk_init())
-	{
-		maybe_lock_display();
-
-		GtkWidget *owin = gtk_window_new(GTK_WINDOW_POPUP);
-		// Why a layout widget?  A MozContainer would be ideal, but
-		// it involves exposing Mozilla headers to mozlib-using apps.
-		// A layout widget with a GtkWindow parent has the desired
-		// properties of being plain GTK, having a window, and being
-		// derived from a GtkContainer.
-		GtkWidget *rtnw = gtk_layout_new(NULL, NULL);
-		gtk_container_add(GTK_CONTAINER(owin), rtnw);
-		gtk_widget_realize(rtnw);
-		GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(rtnw), GTK_NO_WINDOW);
-		
-		maybe_unlock_display();
-		
-		return rtnw;
-	}
-#endif // LL_GTK && LL_LLMOZLIB_ENABLED
-	// Unixoid mozilla really needs GTK.
-	return NULL;
+    return NULL;
 }
 
 void LLWindowSDL::bringToFront()
 {
-	// This is currently used when we are 'launched' to a specific
-	// map position externally.
-	LL_INFOS() << "bringToFront" << LL_ENDL;
+    // This is currently used when we are 'launched' to a specific
+    // map position externally.
+    LL_INFOS() << "bringToFront" << LL_ENDL;
 #if LL_X11
-	if (mSDL_Display && !mFullscreen)
-	{
-		maybe_lock_display();
-		XRaiseWindow(mSDL_Display, mSDL_XWindowID);
-		XSync(mSDL_Display, False);
-		maybe_unlock_display();
-	}
+    if (mSDL_Display && !mFullscreen)
+    {
+        maybe_lock_display();
+        XRaiseWindow(mSDL_Display, mSDL_XWindowID);
+        XSync(mSDL_Display, False);
+        maybe_unlock_display();
+    }
 #endif // LL_X11
 }
 
 //static
 std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()
 {
-	// Use libfontconfig to find us a nice ordered list of fallback fonts
-	// specific to this system.
-	std::string final_fallback("/usr/share/fonts/truetype/kochi/kochi-gothic.ttf");
-	const int max_font_count_cutoff = 40; // fonts are expensive in the current system, don't enumerate an arbitrary number of them
-	// Our 'ideal' font properties which define the sorting results.
-	// slant=0 means Roman, index=0 means the first face in a font file
-	// (the one we actually use), weight=80 means medium weight,
-	// spacing=0 means proportional spacing.
-	std::string sort_order("slant=0:index=0:weight=80:spacing=0");
-	// elide_unicode_coverage removes fonts from the list whose unicode
-	// range is covered by fonts earlier in the list.  This usually
-	// removes ~90% of the fonts as redundant (which is great because
-	// the font list can be huge), but might unnecessarily reduce the
-	// renderable range if for some reason our FreeType actually fails
-	// to use some of the fonts we want it to.
-	const bool elide_unicode_coverage = true;
-	std::vector<std::string> rtns;
-	FcFontSet *fs = NULL;
-	FcPattern *sortpat = NULL;
-
-	LL_INFOS() << "Getting system font list from FontConfig..." << LL_ENDL;
-
-	// If the user has a system-wide language preference, then favor
-	// fonts from that language group.  This doesn't affect the types
-	// of languages that can be displayed, but ensures that their
-	// preferred language is rendered from a single consistent font where
-	// possible.
-	FL_Locale *locale = NULL;
-	FL_Success success = FL_FindLocale(&locale, FL_MESSAGES);
-	if (success != 0)
-	{
-		if (success >= 2 && locale->lang) // confident!
-		{
-			LL_INFOS("AppInit") << "Language " << locale->lang << LL_ENDL;
-			LL_INFOS("AppInit") << "Location " << locale->country << LL_ENDL;
-			LL_INFOS("AppInit") << "Variant " << locale->variant << LL_ENDL;
-
-			LL_INFOS() << "Preferring fonts of language: "
-				<< locale->lang
-				<< LL_ENDL;
-			sort_order = "lang=" + std::string(locale->lang) + ":"
-				+ sort_order;
-		}
-	}
-	FL_FreeLocale(&locale);
-
-	if (!FcInit())
-	{
-		LL_WARNS() << "FontConfig failed to initialize." << LL_ENDL;
-		rtns.push_back(final_fallback);
-		return rtns;
-	}
-
-	sortpat = FcNameParse((FcChar8*) sort_order.c_str());
-	if (sortpat)
-	{
-		// Sort the list of system fonts from most-to-least-desirable.
-		FcResult result;
-		fs = FcFontSort(NULL, sortpat, elide_unicode_coverage,
-				NULL, &result);
-		FcPatternDestroy(sortpat);
-	}
-
-	int found_font_count = 0;
-	if (fs)
-	{
-		// Get the full pathnames to the fonts, where available,
-		// which is what we really want.
-		found_font_count = fs->nfont;
-		for (int i=0; i<fs->nfont; ++i)
-		{
-			FcChar8 *filename;
-			if (FcResultMatch == FcPatternGetString(fs->fonts[i],
-								FC_FILE, 0,
-								&filename)
-			    && filename)
-			{
-				rtns.push_back(std::string((const char*)filename));
-				if (rtns.size() >= max_font_count_cutoff)
-					break; // hit limit
-			}
-		}
-		FcFontSetDestroy (fs);
-	}
-
-	LL_DEBUGS() << "Using font list: " << LL_ENDL;
-	for (std::vector<std::string>::iterator it = rtns.begin();
-		 it != rtns.end();
-		 ++it)
-	{
-		LL_DEBUGS() << "  file: " << *it << LL_ENDL;
-	}
-	LL_INFOS() << "Using " << rtns.size() << "/" << found_font_count << " system fonts." << LL_ENDL;
-
-	rtns.push_back(final_fallback);
-	return rtns;
-}
-
-#endif // LL_SDL
+    // Use libfontconfig to find us a nice ordered list of fallback fonts
+    // specific to this system.
+    std::string final_fallback("/usr/share/fonts/truetype/kochi/kochi-gothic.ttf");
+    const int max_font_count_cutoff = 40; // fonts are expensive in the current system, don't enumerate an arbitrary number of them
+    // Our 'ideal' font properties which define the sorting results.
+    // slant=0 means Roman, index=0 means the first face in a font file
+    // (the one we actually use), weight=80 means medium weight,
+    // spacing=0 means proportional spacing.
+    std::string sort_order("slant=0:index=0:weight=80:spacing=0");
+    // elide_unicode_coverage removes fonts from the list whose unicode
+    // range is covered by fonts earlier in the list.  This usually
+    // removes ~90% of the fonts as redundant (which is great because
+    // the font list can be huge), but might unnecessarily reduce the
+    // renderable range if for some reason our FreeType actually fails
+    // to use some of the fonts we want it to.
+    const bool elide_unicode_coverage = true;
+    std::vector<std::string> rtns;
+    FcFontSet *fs = NULL;
+    FcPattern *sortpat = NULL;
+
+    LL_INFOS() << "Getting system font list from FontConfig..." << LL_ENDL;
+
+    // If the user has a system-wide language preference, then favor
+    // fonts from that language group.  This doesn't affect the types
+    // of languages that can be displayed, but ensures that their
+    // preferred language is rendered from a single consistent font where
+    // possible.
+    FL_Locale *locale = NULL;
+    FL_Success success = FL_FindLocale(&locale, FL_MESSAGES);
+    if (success != 0)
+    {
+        if (success >= 2 && locale->lang) // confident!
+        {
+            LL_INFOS("AppInit") << "Language " << locale->lang << LL_ENDL;
+            LL_INFOS("AppInit") << "Location " << locale->country << LL_ENDL;
+            LL_INFOS("AppInit") << "Variant " << locale->variant << LL_ENDL;
+
+            LL_INFOS() << "Preferring fonts of language: "
+                       << locale->lang
+                       << LL_ENDL;
+            sort_order = "lang=" + std::string(locale->lang) + ":"
+                         + sort_order;
+        }
+    }
+    FL_FreeLocale(&locale);
+
+    if (!FcInit())
+    {
+        LL_WARNS() << "FontConfig failed to initialize." << LL_ENDL;
+        rtns.push_back(final_fallback);
+        return rtns;
+    }
+
+    sortpat = FcNameParse((FcChar8*) sort_order.c_str());
+    if (sortpat)
+    {
+        // Sort the list of system fonts from most-to-least-desirable.
+        FcResult result;
+        fs = FcFontSort(NULL, sortpat, elide_unicode_coverage,
+                        NULL, &result);
+        FcPatternDestroy(sortpat);
+    }
+
+    int found_font_count = 0;
+    if (fs)
+    {
+        // Get the full pathnames to the fonts, where available,
+        // which is what we really want.
+        found_font_count = fs->nfont;
+        for (int i=0; i<fs->nfont; ++i)
+        {
+            FcChar8 *filename;
+            if (FcResultMatch == FcPatternGetString(fs->fonts[i],
+                                                    FC_FILE, 0,
+                                                    &filename)
+                && filename)
+            {
+                rtns.push_back(std::string((const char*)filename));
+                if (rtns.size() >= max_font_count_cutoff)
+                    break; // hit limit
+            }
+        }
+        FcFontSetDestroy (fs);
+    }
+
+    LL_DEBUGS() << "Using font list: " << LL_ENDL;
+    for (std::vector<std::string>::iterator it = rtns.begin();
+         it != rtns.end();
+         ++it)
+    {
+        LL_DEBUGS() << "  file: " << *it << LL_ENDL;
+    }
+    LL_INFOS() << "Using " << rtns.size() << "/" << found_font_count << " system fonts." << LL_ENDL;
+
+    rtns.push_back(final_fallback);
+    return rtns;
+}
+
+
+void* LLWindowSDL::createSharedContext()
+{
+    auto *pContext = SDL_GL_CreateContext(mWindow);
+    if ( pContext)
+    {
+        SDL_GL_SetSwapInterval(0);
+        SDL_GL_MakeCurrent(mWindow, mContext);
+
+        LLCoordScreen size;
+        if (getSize(&size))
+            setSize(size);
+
+        LL_DEBUGS() << "Creating shared OpenGL context successful!" << LL_ENDL;
+
+        return (void*)pContext;
+    }
+
+    LL_WARNS() << "Creating shared OpenGL context failed!" << LL_ENDL;
+
+    return nullptr;
+}
+
+void LLWindowSDL::makeContextCurrent(void* contextPtr)
+{
+    LL_PROFILER_GPU_CONTEXT;
+    SDL_GL_MakeCurrent( mWindow, contextPtr );
+}
+
+void LLWindowSDL::destroySharedContext(void* contextPtr)
+{
+    SDL_GL_DeleteContext( contextPtr );
+}
+
+void LLWindowSDL::toggleVSync(bool enable_vsync)
+{
+}
+
+U32 LLWindowSDL::getAvailableVRAMMegabytes()
+{
+    return 4096;
+}
diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h
index 7193e6f45a..74b9ff026c 100644
--- a/indra/llwindow/llwindowsdl.h
+++ b/indra/llwindow/llwindowsdl.h
@@ -1,43 +1,43 @@
-/** 
+/**
  * @file llwindowsdl.h
  * @brief SDL implementation of LLWindow class
  *
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
 
-#ifndef LL_LLWINDOWSDL_H
-#define LL_LLWINDOWSDL_H
+#ifndef LL_LLWINDOWSDL2_H
+#define LL_LLWINDOWSDL2_H
 
 // Simple Directmedia Layer (http://libsdl.org/) implementation of LLWindow class
 
 #include "llwindow.h"
 #include "lltimer.h"
 
-#include "SDL/SDL.h"
-#include "SDL/SDL_endian.h"
+#include "SDL2/SDL.h"
+#include "SDL2/SDL_endian.h"
 
 #if LL_X11
 // get X11-specific headers for use in low-level stuff like copy-and-paste support
-#include "SDL/SDL_syswm.h"
+#include "SDL2/SDL_syswm.h"
 #endif
 
 // AssertMacros.h does bad things.
@@ -46,184 +46,295 @@
 #undef require
 
 
-class LLWindowSDL : public LLWindow
-{
+class LLWindowSDL : public LLWindow {
 public:
-	/*virtual*/ void show();
-	/*virtual*/ void hide();
-	/*virtual*/ void close();
-	/*virtual*/ BOOL getVisible();
-	/*virtual*/ BOOL getMinimized();
-	/*virtual*/ BOOL getMaximized();
-	/*virtual*/ BOOL maximize();
-	/*virtual*/ void minimize();
-	/*virtual*/ void restore();
-	/*virtual*/ BOOL getFullscreen();
-	/*virtual*/ BOOL getPosition(LLCoordScreen *position);
-	/*virtual*/ BOOL getSize(LLCoordScreen *size);
-	/*virtual*/ BOOL getSize(LLCoordWindow *size);
-	/*virtual*/ BOOL setPosition(LLCoordScreen position);
-	/*virtual*/ BOOL setSizeImpl(LLCoordScreen size);
-	/*virtual*/ BOOL setSizeImpl(LLCoordWindow size);
-	/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL);
-	/*virtual*/ BOOL setCursorPosition(LLCoordWindow position);
-	/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position);
-	/*virtual*/ void showCursor();
-	/*virtual*/ void hideCursor();
-	/*virtual*/ void showCursorFromMouseMove();
-	/*virtual*/ void hideCursorUntilMouseMove();
-	/*virtual*/ BOOL isCursorHidden();
-	/*virtual*/ void updateCursor();
-	/*virtual*/ void captureMouse();
-	/*virtual*/ void releaseMouse();
-	/*virtual*/ void setMouseClipping( BOOL b );
-	/*virtual*/	void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true);
-
-	/*virtual*/ BOOL isClipboardTextAvailable();
-	/*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst);
-	/*virtual*/ BOOL copyTextToClipboard(const LLWString & src);
-
-	/*virtual*/ BOOL isPrimaryTextAvailable();
-	/*virtual*/ BOOL pasteTextFromPrimary(LLWString &dst);
-	/*virtual*/ BOOL copyTextToPrimary(const LLWString & src);
- 
-	/*virtual*/ void flashIcon(F32 seconds);
-	/*virtual*/ F32 getGamma();
-	/*virtual*/ BOOL setGamma(const F32 gamma); // Set the gamma
-	/*virtual*/ U32 getFSAASamples();
-	/*virtual*/ void setFSAASamples(const U32 samples);
-	/*virtual*/ BOOL restoreGamma();			// Restore original gamma table (before updating gamma)
-	/*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; }
-	/*virtual*/ void processMiscNativeEvents();
-	/*virtual*/ void gatherInput();
-	/*virtual*/ void swapBuffers();
-	/*virtual*/ void restoreGLContext() {};
-
-	/*virtual*/ void delayInputProcessing() { };
-
-	// handy coordinate space conversion routines
-	/*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to);
-	/*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to);
-	/*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordGL *to);
-	/*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordWindow *to);
-	/*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordGL *to);
-	/*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordScreen *to);
-
-	/*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions);
-	/*virtual*/ F32	getNativeAspectRatio();
-	/*virtual*/ F32 getPixelAspectRatio();
-	/*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; }
-
-	/*virtual*/ void beforeDialog();
-	/*virtual*/ void afterDialog();
-
-	/*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b);
-
-	/*virtual*/ void *getPlatformWindow();
-	/*virtual*/ void bringToFront();
-
-	/*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async);
-	
-	static std::vector<std::string> getDynamicFallbackFontList();
-
-	// Not great that these are public, but they have to be accessible
-	// by non-class code and it's better than making them global.
+    void show() override;
+
+    void hide() override;
+
+    void close() override;
+
+    BOOL getVisible() override;
+
+    BOOL getMinimized() override;
+
+    BOOL getMaximized() override;
+
+    BOOL maximize() override;
+
+    void minimize() override;
+
+    void restore() override;
+
+    BOOL getFullscreen();
+
+    BOOL getPosition(LLCoordScreen *position) override;
+
+    BOOL getSize(LLCoordScreen *size) override;
+
+    BOOL getSize(LLCoordWindow *size) override;
+
+    BOOL setPosition(LLCoordScreen position) override;
+
+    BOOL setSizeImpl(LLCoordScreen size) override;
+
+    BOOL setSizeImpl(LLCoordWindow size) override;
+
+    BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync,
+                                   const LLCoordScreen *const posp = NULL) override;
+
+    BOOL setCursorPosition(LLCoordWindow position) override;
+
+    BOOL getCursorPosition(LLCoordWindow *position) override;
+
+    void showCursor() override;
+
+    void hideCursor() override;
+
+    void showCursorFromMouseMove() override;
+
+    void hideCursorUntilMouseMove() override;
+
+    BOOL isCursorHidden() override;
+
+    void updateCursor() override;
+
+    void captureMouse() override;
+
+    void releaseMouse() override;
+
+    void setMouseClipping(BOOL b) override;
+
+       void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true) override;
+
+    BOOL isClipboardTextAvailable() override;
+
+    BOOL pasteTextFromClipboard(LLWString &dst) override;
+
+    BOOL copyTextToClipboard(const LLWString &src) override;
+
+    BOOL isPrimaryTextAvailable() override;
+
+    BOOL pasteTextFromPrimary(LLWString &dst) override;
+
+    BOOL copyTextToPrimary(const LLWString &src) override;
+
+    void flashIcon(F32 seconds) override;
+
+    F32 getGamma() override;
+
+    BOOL setGamma(const F32 gamma) override; // Set the gamma
+    U32 getFSAASamples() override;
+
+    void setFSAASamples(const U32 samples) override;
+
+    BOOL restoreGamma() override;            // Restore original gamma table (before updating gamma)
+    ESwapMethod getSwapMethod()  override { return mSwapMethod; }
+
+    void processMiscNativeEvents() override;
+
+    void gatherInput() override;
+
+    void swapBuffers() override;
+
+    void restoreGLContext() {};
+
+    void delayInputProcessing()  override {};
+
+    // handy coordinate space conversion routines
+    BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to) override;
+
+    BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to) override;
+
+    BOOL convertCoords(LLCoordWindow from, LLCoordGL *to) override;
+
+    BOOL convertCoords(LLCoordGL from, LLCoordWindow *to) override;
+
+    BOOL convertCoords(LLCoordScreen from, LLCoordGL *to) override;
+
+    BOOL convertCoords(LLCoordGL from, LLCoordScreen *to) override;
+
+    LLWindowResolution *getSupportedResolutions(S32 &num_resolutions) override;
+
+    F32 getNativeAspectRatio() override;
+
+    F32 getPixelAspectRatio() override;
+
+    void setNativeAspectRatio(F32 ratio)  override { mOverrideAspectRatio = ratio; }
+
+    void beforeDialog() override;
+
+    void afterDialog() override;
+
+    BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b) override;
+
+    void *getPlatformWindow() override;
+
+    void bringToFront() override;
+
+    void spawnWebBrowser(const std::string &escaped_url, bool async) override;
+
+    void openFile(const std::string &file_name);
+
+    void setTitle(const std::string title) override;
+
+    static std::vector<std::string> getDynamicFallbackFontList();
+
+    // Not great that these are public, but they have to be accessible
+    // by non-class code and it's better than making them global.
 #if LL_X11
-	Window mSDL_XWindowID;
-	Display *mSDL_Display;
+    Window mSDL_XWindowID;
+    Display *mSDL_Display;
 #endif
-	void (*Lock_Display)(void);
-	void (*Unlock_Display)(void);
+
+    void (*Lock_Display)(void);
+
+    void (*Unlock_Display)(void);
 
 #if LL_GTK
-	// Lazily initialize and check the runtime GTK version for goodness.
-	static bool ll_try_gtk_init(void);
+    // Lazily initialize and check the runtime GTK version for goodness.
+    static bool ll_try_gtk_init(void);
 #endif // LL_GTK
 
 #if LL_X11
-	static Window get_SDL_XWindowID(void);
-	static Display* get_SDL_Display(void);
-#endif // LL_X11	
+
+    static Window get_SDL_XWindowID(void);
+
+    static Display *get_SDL_Display(void);
+
+#endif // LL_X11
+
+    void *createSharedContext() override;
+
+    void makeContextCurrent(void *context) override;
+
+    void destroySharedContext(void *context) override;
+
+    void toggleVSync(bool enable_vsync) override;
+
+    U32 getAvailableVRAMMegabytes() override;
 
 protected:
-	LLWindowSDL(LLWindowCallbacks* callbacks,
-		const std::string& title, int x, int y, int width, int height, U32 flags,
-		BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
-		BOOL ignore_pixel_depth, U32 fsaa_samples);
-	~LLWindowSDL();
+    LLWindowSDL(LLWindowCallbacks *callbacks,
+                const std::string &title, int x, int y, int width, int height, U32 flags,
+                BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
+                BOOL ignore_pixel_depth, U32 fsaa_samples);
+
+    ~LLWindowSDL();
 
-	/*virtual*/ BOOL	isValid();
-	/*virtual*/ LLSD    getNativeKeyData();
+    BOOL isValid() override;
 
-	void	initCursors();
-	void	quitCursors();
-	void	moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
+    LLSD getNativeKeyData() override;
 
-	// Changes display resolution. Returns true if successful
-	BOOL	setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
+    void initCursors();
 
-	// Go back to last fullscreen display resolution.
-	BOOL	setFullscreenResolution();
+    void quitCursors();
 
-	BOOL	shouldPostQuit() { return mPostQuit; }
+    void moveWindow(const LLCoordScreen &position, const LLCoordScreen &size);
+
+    // Changes display resolution. Returns true if successful
+    BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
+
+    // Go back to last fullscreen display resolution.
+    BOOL setFullscreenResolution();
+
+    BOOL shouldPostQuit() { return mPostQuit; }
 
 protected:
-	//
-	// Platform specific methods
-	//
-
-	// create or re-create the GL context/window.  Called from the constructor and switchContext().
-	BOOL createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync);
-	void destroyContext();
-	void setupFailure(const std::string& text, const std::string& caption, U32 type);
-	void fixWindowSize(void);
-	U32 SDLCheckGrabbyKeys(SDLKey keysym, BOOL gain);
-	BOOL SDLReallyCaptureInput(BOOL capture);
-
-	//
-	// Platform specific variables
-	//
-	U32             mGrabbyKeyFlags;
-	int			mReallyCapturedCount;
-	SDL_Surface *	mWindow;
-	std::string mWindowTitle;
-	double		mOriginalAspectRatio;
-	BOOL		mNeedsResize;		// Constructor figured out the window is too big, it needs a resize.
-	LLCoordScreen   mNeedsResizeSize;
-	F32			mOverrideAspectRatio;
-	F32		mGamma;
-	U32		mFSAASamples;
-
-	int		mSDLFlags;
-
-	SDL_Cursor*	mSDLCursors[UI_CURSOR_COUNT];
-	int             mHaveInputFocus; /* 0=no, 1=yes, else unknown */
-	int             mIsMinimized; /* 0=no, 1=yes, else unknown */
-
-	friend class LLWindowManager;
+    //
+    // Platform specific methods
+    //
+
+    // create or re-create the GL context/window.  Called from the constructor and switchContext().
+    BOOL createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync);
+
+    void destroyContext();
+
+    void setupFailure(const std::string &text, const std::string &caption, U32 type);
+
+    void fixWindowSize(void);
+
+    U32 SDLCheckGrabbyKeys(U32 keysym, BOOL gain);
+
+    BOOL SDLReallyCaptureInput(BOOL capture);
+
+    //
+    // Platform specific variables
+    //
+    U32 mGrabbyKeyFlags;
+    int mReallyCapturedCount;
+
+    SDL_Window *mWindow;
+    SDL_Surface *mSurface;
+    SDL_GLContext mContext;
+    SDL_Cursor *mSDLCursors[UI_CURSOR_COUNT];
+
+    std::string mWindowTitle;
+    double mOriginalAspectRatio;
+    BOOL mNeedsResize;        // Constructor figured out the window is too big, it needs a resize.
+    LLCoordScreen mNeedsResizeSize;
+    F32 mOverrideAspectRatio;
+    F32 mGamma;
+    U32 mFSAASamples;
+
+    int mSDLFlags;
+
+    int mHaveInputFocus; /* 0=no, 1=yes, else unknown */
+    int mIsMinimized; /* 0=no, 1=yes, else unknown */
+
+    friend class LLWindowManager;
 
 private:
 #if LL_X11
-	void x11_set_urgent(BOOL urgent);
-	BOOL mFlashing;
-	LLTimer mFlashTimer;
+
+    void x11_set_urgent(BOOL urgent);
+
+    BOOL mFlashing;
+    LLTimer mFlashTimer;
 #endif //LL_X11
-	
-	U32 mKeyScanCode;
-        U32 mKeyVirtualKey;
-	SDLMod mKeyModifiers;
-};
 
+    U32 mKeyVirtualKey;
+    U32 mKeyModifiers;
+    std::string mInputType;
+
+public:
+#if LL_X11
+
+    static Display *getSDLDisplay();
+
+    LLWString const &getPrimaryText() const { return mPrimaryClipboard; }
+
+    LLWString const &getSecondaryText() const { return mSecondaryClipboard; }
+
+    void clearPrimaryText() { mPrimaryClipboard.clear(); }
+
+    void clearSecondaryText() { mSecondaryClipboard.clear(); }
+
+private:
+    void tryFindFullscreenSize(int &aWidth, int &aHeight);
+
+    void initialiseX11Clipboard();
+
+    bool getSelectionText(Atom selection, LLWString &text);
+
+    bool getSelectionText(Atom selection, Atom type, LLWString &text);
+
+    bool setSelectionText(Atom selection, const LLWString &text);
+
+#endif
+    LLWString mPrimaryClipboard;
+    LLWString mSecondaryClipboard;
+};
 
 class LLSplashScreenSDL : public LLSplashScreen
 {
 public:
-	LLSplashScreenSDL();
-	virtual ~LLSplashScreenSDL();
+    LLSplashScreenSDL();
+    virtual ~LLSplashScreenSDL();
 
-	/*virtual*/ void showImpl();
-	/*virtual*/ void updateImpl(const std::string& mesg);
-	/*virtual*/ void hideImpl();
+    void showImpl();
+    void updateImpl(const std::string& mesg);
+    void hideImpl();
 };
 
 S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 type);
diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt
index 972bb7dd2d..fe8fee5e7e 100644
--- a/indra/media_plugins/CMakeLists.txt
+++ b/indra/media_plugins/CMakeLists.txt
@@ -3,7 +3,7 @@
 add_subdirectory(base)
 
 if (LINUX)
-    #add_subdirectory(gstreamer010)
+    add_subdirectory(gstreamer10)
     add_subdirectory(example)
 endif (LINUX)
 
diff --git a/indra/media_plugins/gstreamer10/CMakeLists.txt b/indra/media_plugins/gstreamer10/CMakeLists.txt
new file mode 100644
index 0000000000..ffa3c30519
--- /dev/null
+++ b/indra/media_plugins/gstreamer10/CMakeLists.txt
@@ -0,0 +1,46 @@
+# -*- cmake -*-
+
+project(media_plugin_gstreamer10)
+
+include(00-Common)
+include(LLCommon)
+include(LLImage)
+include(LLMath)
+include(LLWindow)
+include(Linking)
+include(PluginAPI)
+include(OpenGL)
+include(GLIB)
+
+include(GStreamer10Plugin)
+
+### media_plugin_gstreamer10
+
+if(NOT WINDOWS) # not windows therefore gcc LINUX and DARWIN
+add_definitions(-fPIC)
+endif()
+
+set(media_plugin_gstreamer10_SOURCE_FILES
+    media_plugin_gstreamer10.cpp
+    llmediaimplgstreamer_syms.cpp
+    )
+
+set(media_plugin_gstreamer10_HEADER_FILES
+    llmediaimplgstreamer_syms.h
+    llmediaimplgstreamertriviallogging.h
+    )
+
+add_library(media_plugin_gstreamer10
+    SHARED
+    ${media_plugin_gstreamer10_SOURCE_FILES}
+)
+
+target_link_libraries(media_plugin_gstreamer10 media_plugin_base ll::gstreamer10 )
+
+if (WINDOWS)
+  set_target_properties(
+    media_plugin_gstreamer10
+    PROPERTIES
+    LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMT"
+    )
+endif (WINDOWS)
diff --git a/indra/media_plugins/gstreamer10/llmediaimplgstreamer.h b/indra/media_plugins/gstreamer10/llmediaimplgstreamer.h
new file mode 100644
index 0000000000..6bc272c009
--- /dev/null
+++ b/indra/media_plugins/gstreamer10/llmediaimplgstreamer.h
@@ -0,0 +1,53 @@
+/** 
+ * @file llmediaimplgstreamer.h
+ * @author Tofu Linden
+ * @brief implementation that supports media playback via GStreamer.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+// header guard
+#ifndef llmediaimplgstreamer_h
+#define llmediaimplgstreamer_h
+
+#if LL_GSTREAMER010_ENABLED
+
+extern "C" {
+#include <stdio.h>
+#include <gst/gst.h>
+
+#include "apr_pools.h"
+#include "apr_dso.h"
+}
+
+
+extern "C" {
+gboolean llmediaimplgstreamer_bus_callback (GstBus     *bus,
+					    GstMessage *message,
+					    gpointer    data);
+}
+
+#endif // LL_GSTREAMER010_ENABLED
+
+#endif // llmediaimplgstreamer_h
diff --git a/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms.cpp b/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms.cpp
new file mode 100644
index 0000000000..e5e5c1c9a3
--- /dev/null
+++ b/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms.cpp
@@ -0,0 +1,197 @@
+/** 
+ * @file llmediaimplgstreamer_syms.cpp
+ * @brief dynamic GStreamer symbol-grabbing code
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include <string>
+#include <iostream>
+#include <vector>
+
+#ifdef LL_WINDOWS
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0502
+#include <Windows.h>
+#endif
+
+#include "linden_common.h"
+
+extern "C" {
+#include <gst/gst.h>
+#include <gst/app/gstappsink.h>
+}
+
+#include "apr_pools.h"
+#include "apr_dso.h"
+
+#ifdef LL_WINDOWS
+
+#ifndef _M_AMD64
+#define GSTREAMER_REG_KEY "Software\\GStreamer1.0\\x86"
+#define GSTREAMER_DIR_SUFFIX "1.0\\x86\\bin\\"
+#else
+#define GSTREAMER_REG_KEY "Software\\GStreamer1.0\\x86_64"
+#define GSTREAMER_DIR_SUFFIX "1.0\\x86_64\\bin\\"
+#endif
+
+bool openRegKey( HKEY &aKey )
+{
+	// Try native (32 bit view/64 bit view) of registry first.
+	if( ERROR_SUCCESS == ::RegOpenKeyExA( HKEY_LOCAL_MACHINE, GSTREAMER_REG_KEY, 0, KEY_QUERY_VALUE, &aKey ) )
+		return true;
+
+	// If native view fails, use 32 bit view or registry.
+	if( ERROR_SUCCESS == ::RegOpenKeyExA( HKEY_LOCAL_MACHINE, GSTREAMER_REG_KEY, 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &aKey ) )
+		return true;
+
+	return false;
+}
+
+std::string getGStreamerDir()
+{
+	std::string ret;
+	HKEY hKey;
+
+	if( openRegKey( hKey ) )
+	{
+		DWORD dwLen(0);
+		::RegQueryValueExA( hKey, "InstallDir", nullptr, nullptr, nullptr, &dwLen );
+
+		if( dwLen > 0 )
+		{
+			std::vector< char > vctBuffer;
+			vctBuffer.resize( dwLen );
+			::RegQueryValueExA( hKey, "InstallDir", nullptr, nullptr, reinterpret_cast< LPBYTE>(&vctBuffer[ 0 ]), &dwLen );
+			ret = &vctBuffer[0];
+
+			if( ret[ dwLen-1 ] != '\\' )
+				ret += "\\";
+			ret += GSTREAMER_DIR_SUFFIX;
+
+			SetDllDirectoryA( ret.c_str() );
+		}
+		::RegCloseKey( hKey );
+	}
+	return ret;
+}
+#else
+std::string getGStreamerDir() { return ""; }
+#endif
+
+#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) RTN (*ll##GSTSYM)(__VA_ARGS__) = NULL;
+#include "llmediaimplgstreamer_syms_raw.inc"
+#undef LL_GST_SYM
+
+struct Symloader
+{
+	bool mRequired;
+	char const *mName;
+	apr_dso_handle_sym_t *mPPFunc;
+};
+
+#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) { REQ, #GSTSYM , (apr_dso_handle_sym_t*)&ll##GSTSYM}, 
+Symloader sSyms[] = {
+#include "llmediaimplgstreamer_syms_raw.inc"
+{ false, 0, 0 } };
+#undef LL_GST_SYM
+
+// a couple of stubs for disgusting reasons
+GstDebugCategory*
+ll_gst_debug_category_new(gchar *name, guint color, gchar *description)
+{
+	static GstDebugCategory dummy;
+	return &dummy;
+}
+void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname)
+{
+}
+
+static bool sSymsGrabbed = false;
+static apr_pool_t *sSymGSTDSOMemoryPool = NULL;
+
+std::vector< apr_dso_handle_t* > sLoadedLibraries;
+
+bool grab_gst_syms( std::vector< std::string > const &aDSONames )
+{
+	if (sSymsGrabbed)
+		return true;
+
+	//attempt to load the shared libraries
+	apr_pool_create(&sSymGSTDSOMemoryPool, NULL);
+  
+	for( std::vector< std::string >::const_iterator itr = aDSONames.begin(); itr != aDSONames.end(); ++itr )
+	{
+		apr_dso_handle_t *pDSO(NULL);
+		std::string strDSO = getGStreamerDir() + *itr;
+		if( APR_SUCCESS == apr_dso_load( &pDSO, strDSO.c_str(), sSymGSTDSOMemoryPool ))
+			sLoadedLibraries.push_back( pDSO );
+		
+		for( int i = 0; sSyms[ i ].mName; ++i )
+		{
+			if( !*sSyms[ i ].mPPFunc )
+			{
+				apr_dso_sym( sSyms[ i ].mPPFunc, pDSO, sSyms[ i ].mName );
+			}
+		}
+	}
+
+	std::stringstream strm;
+	bool sym_error = false;
+	for( int i = 0; sSyms[ i ].mName; ++i )
+	{
+		if( sSyms[ i ].mRequired && ! *sSyms[ i ].mPPFunc )
+		{
+			sym_error = true;
+			strm << sSyms[ i ].mName << std::endl;
+		}
+	}
+
+	sSymsGrabbed = !sym_error;
+	return sSymsGrabbed;
+}
+
+
+void ungrab_gst_syms()
+{ 
+	// should be safe to call regardless of whether we've
+	// actually grabbed syms.
+
+	for( std::vector< apr_dso_handle_t* >::iterator itr = sLoadedLibraries.begin(); itr != sLoadedLibraries.end(); ++itr )
+		apr_dso_unload( *itr );
+
+	sLoadedLibraries.clear();
+
+	if ( sSymGSTDSOMemoryPool )
+	{
+		apr_pool_destroy(sSymGSTDSOMemoryPool);
+		sSymGSTDSOMemoryPool = NULL;
+	}
+
+	for( int i = 0; sSyms[ i ].mName; ++i )
+		*sSyms[ i ].mPPFunc = NULL;
+
+	sSymsGrabbed = false;
+}
+
diff --git a/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms.h b/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms.h
new file mode 100644
index 0000000000..0874644ee6
--- /dev/null
+++ b/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms.h
@@ -0,0 +1,68 @@
+/** 
+ * @file llmediaimplgstreamer_syms.h
+ * @brief dynamic GStreamer symbol-grabbing code
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+#include <vector>
+extern "C" {
+#include <gst/gst.h>
+}
+
+bool grab_gst_syms( std::vector< std::string > const&);
+void ungrab_gst_syms();
+
+#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) extern RTN (*ll##GSTSYM)(__VA_ARGS__);
+#include "llmediaimplgstreamer_syms_raw.inc"
+#undef LL_GST_SYM
+
+// regrettable hacks to give us better runtime compatibility with older systems
+#define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0)
+#define llg_return_val_if_fail(COND,V) do{if (!(COND)) return V;}while(0)
+
+// regrettable hacks because GStreamer was not designed for runtime loading
+#undef GST_TYPE_MESSAGE
+#define GST_TYPE_MESSAGE (llgst_message_get_type())
+#undef GST_TYPE_OBJECT
+#define GST_TYPE_OBJECT (llgst_object_get_type())
+#undef GST_TYPE_PIPELINE
+#define GST_TYPE_PIPELINE (llgst_pipeline_get_type())
+#undef GST_TYPE_ELEMENT
+#define GST_TYPE_ELEMENT (llgst_element_get_type())
+#undef GST_TYPE_VIDEO_SINK
+#define GST_TYPE_VIDEO_SINK (llgst_video_sink_get_type())
+// more regrettable hacks to stub-out these .h-exposed GStreamer internals
+void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname);
+#undef _gst_debug_register_funcptr
+#define _gst_debug_register_funcptr ll_gst_debug_register_funcptr
+GstDebugCategory* ll_gst_debug_category_new(gchar *name, guint color, gchar *description);
+#undef _gst_debug_category_new
+#define _gst_debug_category_new ll_gst_debug_category_new
+#undef __gst_debug_enabled
+#define __gst_debug_enabled (0)
+
+// more hacks
+#define LLGST_MESSAGE_TYPE_NAME(M) (llgst_message_type_get_name(GST_MESSAGE_TYPE(M)))
diff --git a/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms_raw.inc b/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms_raw.inc
new file mode 100644
index 0000000000..155eeb6809
--- /dev/null
+++ b/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms_raw.inc
@@ -0,0 +1,68 @@
+LL_GST_SYM(true, gst_buffer_new, GstBuffer*, void)
+LL_GST_SYM(true, gst_structure_set_value, void, GstStructure *, const gchar *, const GValue*)
+LL_GST_SYM(true, gst_init_check, gboolean, int *argc, char **argv[], GError ** err)
+LL_GST_SYM(true, gst_message_get_type, GType, void)
+LL_GST_SYM(true, gst_message_type_get_name, const gchar*, GstMessageType type)
+LL_GST_SYM(true, gst_message_parse_error, void, GstMessage *message, GError **gerror, gchar **debug)
+LL_GST_SYM(true, gst_message_parse_warning, void, GstMessage *message, GError **gerror, gchar **debug)
+LL_GST_SYM(true, gst_message_parse_state_changed, void, GstMessage *message, GstState *oldstate, GstState *newstate, GstState *pending)
+LL_GST_SYM(true, gst_element_set_state, GstStateChangeReturn, GstElement *element, GstState state)
+LL_GST_SYM(true, gst_object_unref, void, gpointer object)
+LL_GST_SYM(true, gst_object_get_type, GType, void)
+LL_GST_SYM(true, gst_pipeline_get_type, GType, void)
+LL_GST_SYM(true, gst_pipeline_get_bus, GstBus*, GstPipeline *pipeline)
+LL_GST_SYM(true, gst_bus_add_watch, guint, GstBus * bus, GstBusFunc func, gpointer user_data)
+LL_GST_SYM(true, gst_element_factory_make, GstElement*, const gchar *factoryname, const gchar *name)
+LL_GST_SYM(true, gst_element_get_type, GType, void)
+LL_GST_SYM(true, gst_static_pad_template_get, GstPadTemplate*, GstStaticPadTemplate *pad_template)
+LL_GST_SYM(true, gst_element_class_add_pad_template, void, GstElementClass *klass, GstPadTemplate *temp)
+LL_GST_SYM(true, gst_caps_from_string, GstCaps *, const gchar *string)
+LL_GST_SYM(true, gst_caps_get_structure, GstStructure *, const GstCaps *caps, guint index)
+LL_GST_SYM(true, gst_element_register, gboolean, GstPlugin *plugin, const gchar *name, guint rank, GType type)
+LL_GST_SYM(true, gst_structure_get_int, gboolean, const GstStructure *structure, const gchar *fieldname, gint *value)
+LL_GST_SYM(true, gst_structure_get_value, const GValue *, const GstStructure *structure, const gchar *fieldname)
+LL_GST_SYM(true, gst_value_get_fraction_numerator, gint, const GValue *value)
+LL_GST_SYM(true, gst_value_get_fraction_denominator, gint, const GValue *value)
+LL_GST_SYM(true, gst_structure_get_name, const gchar *, const GstStructure *structure)
+LL_GST_SYM(true, gst_element_seek, bool, GstElement *, gdouble, GstFormat, GstSeekFlags, GstSeekType, gint64, GstSeekType, gint64)
+
+LL_GST_SYM(false, gst_registry_fork_set_enabled, void, gboolean enabled)
+LL_GST_SYM(false, gst_segtrap_set_enabled, void, gboolean enabled)
+LL_GST_SYM(false, gst_message_parse_buffering, void, GstMessage *message, gint *percent)
+LL_GST_SYM(false, gst_message_parse_info, void, GstMessage *message, GError **gerror, gchar **debug)
+LL_GST_SYM(false, gst_element_query_position, gboolean, GstElement *element, GstFormat *format, gint64 *cur)
+LL_GST_SYM(false, gst_version, void, guint *major, guint *minor, guint *micro, guint *nano)
+
+LL_GST_SYM( true, gst_message_parse_tag, void, GstMessage *, GstTagList **)
+LL_GST_SYM( true, gst_tag_list_foreach, void, const GstTagList *, GstTagForeachFunc, gpointer)
+LL_GST_SYM( true, gst_tag_list_get_tag_size, guint, const GstTagList *, const gchar *)
+LL_GST_SYM( true, gst_tag_list_get_value_index, const GValue *, const GstTagList *, const gchar *, guint)
+
+LL_GST_SYM( true, gst_caps_new_simple, GstCaps*, const char *, const char*, ... )
+
+LL_GST_SYM( true, gst_sample_get_caps, GstCaps*, GstSample* )
+LL_GST_SYM( true, gst_sample_get_buffer, GstBuffer*, GstSample* )
+LL_GST_SYM( true, gst_buffer_map, gboolean, GstBuffer*, GstMapInfo*, GstMapFlags )
+LL_GST_SYM( true, gst_buffer_unmap, void, GstBuffer*, GstMapInfo* )
+
+LL_GST_SYM( true, gst_app_sink_set_caps, void, GstAppSink*, GstCaps const* )
+LL_GST_SYM( true, gst_app_sink_pull_sample, GstSample*, GstAppSink* )
+
+LL_GST_SYM( true, g_free, void, gpointer )
+LL_GST_SYM( true, g_error_free, void, GError* )
+
+LL_GST_SYM( true, g_main_context_pending, gboolean, GMainContext* )
+LL_GST_SYM( true, g_main_loop_get_context, GMainContext*, GMainLoop* )
+LL_GST_SYM( true, g_main_context_iteration, gboolean, GMainContext*, gboolean )
+LL_GST_SYM( true, g_main_loop_new, GMainLoop*, GMainContext*, gboolean )
+LL_GST_SYM( true, g_main_loop_quit, void, GMainLoop* )
+LL_GST_SYM( true, gst_mini_object_unref, void, GstMiniObject* )
+LL_GST_SYM( true, g_object_set, void, gpointer, gchar const*, ... )
+LL_GST_SYM( true, g_source_remove, gboolean, guint )
+LL_GST_SYM( true, g_value_get_string, gchar const*, GValue const* )
+
+
+LL_GST_SYM( true, gst_debug_set_active, void, gboolean )
+LL_GST_SYM( true, gst_debug_add_log_function, void, GstLogFunction, gpointer, GDestroyNotify )
+LL_GST_SYM( true, gst_debug_set_default_threshold, void, GstDebugLevel )
+LL_GST_SYM( true, gst_debug_message_get , gchar const*, GstDebugMessage * )
\ No newline at end of file
diff --git a/indra/media_plugins/gstreamer10/media_plugin_gstreamer10.cpp b/indra/media_plugins/gstreamer10/media_plugin_gstreamer10.cpp
new file mode 100644
index 0000000000..07bfb67283
--- /dev/null
+++ b/indra/media_plugins/gstreamer10/media_plugin_gstreamer10.cpp
@@ -0,0 +1,982 @@
+/** 
+ * @file media_plugin_gstreamer10.cpp
+ * @brief GStreamer-1.0 plugin for LLMedia API plugin system
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2016&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2016, Linden Research, Inc. / Nicky Dasmijn
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#define FLIP_Y
+
+#include "linden_common.h"
+
+#include "llgl.h"
+
+#include "llplugininstance.h"
+#include "llpluginmessage.h"
+#include "llpluginmessageclasses.h"
+#include "media_plugin_base.h"
+
+#define G_DISABLE_CAST_CHECKS
+extern "C" {
+#include <gst/gst.h>
+#include <gst/app/gstappsink.h>
+
+}
+
+#include "llmediaimplgstreamer.h"
+#include "llmediaimplgstreamer_syms.h"
+
+static inline void llgst_caps_unref( GstCaps * caps )
+{
+    llgst_mini_object_unref( GST_MINI_OBJECT_CAST( caps ) );
+}
+
+static inline void llgst_sample_unref( GstSample *aSample )
+{
+    llgst_mini_object_unref( GST_MINI_OBJECT_CAST( aSample ) );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+class MediaPluginGStreamer10 : public MediaPluginBase
+{
+public:
+    MediaPluginGStreamer10(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
+    ~MediaPluginGStreamer10();
+
+    /* virtual */ void receiveMessage(const char *message_string);
+
+    static bool startup();
+    static bool closedown();
+
+    gboolean processGSTEvents(GstBus *bus, GstMessage *message);
+
+private:
+    std::string getVersion();
+    bool navigateTo( const std::string urlIn );
+    bool seek( double time_sec );
+    bool setVolume( float volume );
+    
+    // misc
+    bool pause();
+    bool stop();
+    bool play(double rate);
+    bool getTimePos(double &sec_out);
+
+    double MIN_LOOP_SEC = 1.0F;
+    U32 INTERNAL_TEXTURE_SIZE = 1024;
+    
+    bool mIsLooping;
+
+    enum ECommand {
+        COMMAND_NONE,
+        COMMAND_STOP,
+        COMMAND_PLAY,
+        COMMAND_FAST_FORWARD,
+        COMMAND_FAST_REWIND,
+        COMMAND_PAUSE,
+        COMMAND_SEEK,
+    };
+    ECommand mCommand;
+
+private:
+    bool unload();
+    bool load();
+
+    bool update(int milliseconds);
+    void mouseDown( int x, int y );
+    void mouseUp( int x, int y );
+    void mouseMove( int x, int y );
+
+    static bool mDoneInit;
+    
+    guint mBusWatchID;
+    
+    float mVolume;
+
+    int mDepth;
+
+    // padded texture size we need to write into
+    int mTextureWidth;
+    int mTextureHeight;
+    
+    bool mSeekWanted;
+    double mSeekDestination;
+    
+    // Very GStreamer-specific
+    GMainLoop *mPump; // event pump for this media
+    GstElement *mPlaybin;
+    GstAppSink *mAppSink;
+};
+
+//static
+bool MediaPluginGStreamer10::mDoneInit = false;
+
+MediaPluginGStreamer10::MediaPluginGStreamer10( LLPluginInstance::sendMessageFunction host_send_func,
+                                                void *host_user_data )
+    : MediaPluginBase(host_send_func, host_user_data)
+    , mBusWatchID ( 0 )
+    , mSeekWanted(false)
+    , mSeekDestination(0.0)
+    , mPump ( NULL )
+    , mPlaybin ( NULL )
+    , mAppSink ( NULL )
+    , mCommand ( COMMAND_NONE )
+{
+}
+
+gboolean MediaPluginGStreamer10::processGSTEvents(GstBus *bus, GstMessage *message)
+{
+    if (!message) 
+        return TRUE; // shield against GStreamer bug
+
+    switch (GST_MESSAGE_TYPE (message))
+    {
+        case GST_MESSAGE_BUFFERING:
+        {
+            // NEEDS GST 0.10.11+
+            if (llgst_message_parse_buffering)
+            {
+                gint percent = 0;
+                llgst_message_parse_buffering(message, &percent);
+            }
+            break;
+        }
+        case GST_MESSAGE_STATE_CHANGED:
+        {
+            GstState old_state;
+            GstState new_state;
+            GstState pending_state;
+            llgst_message_parse_state_changed(message,
+                                              &old_state,
+                                              &new_state,
+                                              &pending_state);
+
+            switch (new_state)
+            {
+                case GST_STATE_VOID_PENDING:
+                    break;
+                case GST_STATE_NULL:
+                    break;
+                case GST_STATE_READY:
+                    setStatus(STATUS_LOADED);
+                    break;
+                case GST_STATE_PAUSED:
+                    setStatus(STATUS_PAUSED);
+                    break;
+                case GST_STATE_PLAYING:
+                    setStatus(STATUS_PLAYING);
+                    break;
+            }
+            break;
+        }
+        case GST_MESSAGE_ERROR:
+        {
+            GError *err = NULL;
+            gchar *debug = NULL;
+
+            llgst_message_parse_error (message, &err, &debug);
+            if (err)
+                llg_error_free (err);
+            llg_free (debug);
+
+            mCommand = COMMAND_STOP;
+
+            setStatus(STATUS_ERROR);
+
+            break;
+        }
+        case GST_MESSAGE_INFO:
+        {
+            if (llgst_message_parse_info)
+            {
+                GError *err = NULL;
+                gchar *debug = NULL;
+            
+                llgst_message_parse_info (message, &err, &debug);
+                if (err)
+                    llg_error_free (err);
+                llg_free (debug);
+            }
+            break;
+        }
+        case GST_MESSAGE_WARNING:
+        {
+            GError *err = NULL;
+            gchar *debug = NULL;
+            
+            llgst_message_parse_warning (message, &err, &debug);
+            if (err)
+                llg_error_free (err);
+            llg_free (debug);
+
+            break;
+        }
+        case GST_MESSAGE_EOS:
+            /* end-of-stream */
+            if (mIsLooping)
+            {
+                double eos_pos_sec = 0.0F;
+                bool got_eos_position = getTimePos(eos_pos_sec);
+                
+                if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC)
+                {
+                    // if we know that the movie is really short, don't
+                    // loop it else it can easily become a time-hog
+                    // because of GStreamer spin-up overhead
+                    // inject a COMMAND_PAUSE
+                    mCommand = COMMAND_PAUSE;
+                }
+                else
+                {
+                    stop();
+                    play(1.0);
+                }
+            }
+            else // not a looping media
+            {
+                // inject a COMMAND_STOP
+                mCommand = COMMAND_STOP;
+            }
+            break;
+        default:
+            /* unhandled message */
+            break;
+    }
+
+    /* we want to be notified again the next time there is a message
+     * on the bus, so return true (false means we want to stop watching
+     * for messages on the bus and our callback should not be called again)
+     */
+    return TRUE;
+}
+
+extern "C" {
+    gboolean llmediaimplgstreamer_bus_callback (GstBus     *bus,
+                                                GstMessage *message,
+                                                gpointer    data)
+    {
+        MediaPluginGStreamer10 *impl = (MediaPluginGStreamer10*)data;
+        return impl->processGSTEvents(bus, message);
+    }
+} // extern "C"
+
+
+
+bool MediaPluginGStreamer10::navigateTo ( const std::string urlIn )
+{
+    if (!mDoneInit)
+        return false; // error
+
+    setStatus(STATUS_LOADING);
+
+    mSeekWanted = false;
+
+    if (NULL == mPump ||  NULL == mPlaybin)
+    {
+        setStatus(STATUS_ERROR);
+        return false; // error
+    }
+
+    llg_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), NULL);
+
+    // navigateTo implicitly plays, too.
+    play(1.0);
+
+    return true;
+}
+
+
+class GstSampleUnref
+{
+    GstSample *mT;
+public:
+    GstSampleUnref( GstSample *aT )
+        : mT( aT )
+    { llassert_always( mT ); }
+
+    ~GstSampleUnref( )
+    { llgst_sample_unref( mT ); }
+};
+
+bool MediaPluginGStreamer10::update(int milliseconds)
+{
+    if (!mDoneInit)
+        return false; // error
+
+    //  DEBUGMSG("updating media...");
+    
+    // sanity check
+    if (NULL == mPump || NULL == mPlaybin)
+    {
+        return false;
+    }
+
+    // see if there's an outstanding seek wanted
+    if (mSeekWanted &&
+        // bleh, GST has to be happy that the movie is really truly playing
+        // or it may quietly ignore the seek (with rtsp:// at least).
+        (GST_STATE(mPlaybin) == GST_STATE_PLAYING))
+    {
+        seek(mSeekDestination);
+        mSeekWanted = false;
+    }
+
+    // *TODO: time-limit - but there isn't a lot we can do here, most
+    // time is spent in gstreamer's own opaque worker-threads.  maybe
+    // we can do something sneaky like only unlock the video object
+    // for 'milliseconds' and otherwise hold the lock.
+    while (llg_main_context_pending(llg_main_loop_get_context(mPump)))
+    {
+           llg_main_context_iteration(llg_main_loop_get_context(mPump), FALSE);
+    }
+
+    // check for availability of a new frame
+    
+    if( !mAppSink )
+        return true;
+
+    if( GST_STATE(mPlaybin) != GST_STATE_PLAYING) // Do not try to pull a sample if not in playing state
+        return true;
+    
+    GstSample *pSample = llgst_app_sink_pull_sample( mAppSink );
+    if(!pSample)
+        return false; // Done playing
+
+    GstSampleUnref oSampleUnref( pSample );
+    GstCaps *pCaps = llgst_sample_get_caps ( pSample );
+    if (!pCaps)
+        return false;
+
+    gint width = 0, height = 0;
+    GstStructure *pStruct = llgst_caps_get_structure ( pCaps, 0);
+
+    if(!llgst_structure_get_int ( pStruct, "width", &width) )
+        width = 0;
+    if(!llgst_structure_get_int ( pStruct, "height", &height) )
+        height = 0;
+
+    if( !mPixels || width == 0 || height == 0)
+        return true;
+    
+    GstBuffer *pBuffer = llgst_sample_get_buffer ( pSample );
+    GstMapInfo map;
+    llgst_buffer_map ( pBuffer, &map, GST_MAP_READ);
+
+    // Our render buffer is always 1kx1k
+
+    U32 rowSkip = INTERNAL_TEXTURE_SIZE / mTextureHeight;
+    U32 colSkip = INTERNAL_TEXTURE_SIZE / mTextureWidth;
+
+    for (int row = 0; row < mTextureHeight; ++row)
+    {
+        U8 const *pTexelIn = map.data + (row*rowSkip * width *3);
+#ifndef FLIP_Y
+        U8 *pTexelOut = mPixels + (row * mTextureWidth * mDepth );
+#else
+        U8 *pTexelOut = mPixels + ((mTextureHeight-row-1) * mTextureWidth * mDepth );
+#endif      
+        for( int col = 0; col < mTextureWidth; ++col )
+        {
+            pTexelOut[ 0 ] = pTexelIn[0];
+            pTexelOut[ 1 ] = pTexelIn[1];
+            pTexelOut[ 2 ] = pTexelIn[2];
+            pTexelOut += mDepth;
+            pTexelIn += colSkip*3;
+        }
+    }
+
+    llgst_buffer_unmap( pBuffer, &map );
+    setDirty(0,0,mTextureWidth,mTextureHeight);
+
+    return true;
+}
+
+void MediaPluginGStreamer10::mouseDown( int x, int y )
+{
+  // do nothing
+}
+
+void MediaPluginGStreamer10::mouseUp( int x, int y )
+{
+  // do nothing
+}
+
+void MediaPluginGStreamer10::mouseMove( int x, int y )
+{
+  // do nothing
+}
+
+
+bool MediaPluginGStreamer10::pause()
+{
+    // todo: error-check this?
+    if (mDoneInit && mPlaybin)
+    {
+        llgst_element_set_state(mPlaybin, GST_STATE_PAUSED);
+        return true;
+    }
+    return false;
+}
+
+bool MediaPluginGStreamer10::stop()
+{
+    // todo: error-check this?
+    if (mDoneInit && mPlaybin)
+    {
+        llgst_element_set_state(mPlaybin, GST_STATE_READY);
+        return true;
+    }
+    return false;
+}
+
+bool MediaPluginGStreamer10::play(double rate)
+{
+    // NOTE: we don't actually support non-natural rate.
+
+    // todo: error-check this?
+    if (mDoneInit && mPlaybin)
+    {
+        llgst_element_set_state(mPlaybin, GST_STATE_PLAYING);
+        return true;
+    }
+    return false;
+}
+
+bool MediaPluginGStreamer10::setVolume( float volume )
+{
+    // we try to only update volume as conservatively as
+    // possible, as many gst-plugins-base versions up to at least
+    // November 2008 have critical race-conditions in setting volume - sigh
+    if (mVolume == volume)
+        return true; // nothing to do, everything's fine
+
+    mVolume = volume;
+    if (mDoneInit && mPlaybin)
+    {
+        llg_object_set(mPlaybin, "volume", mVolume, NULL);
+        return true;
+    }
+
+    return false;
+}
+
+bool MediaPluginGStreamer10::seek(double time_sec)
+{
+    bool success = false;
+    if (mDoneInit && mPlaybin)
+    {
+        success = llgst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME,
+                GstSeekFlags(GST_SEEK_FLAG_FLUSH |
+                         GST_SEEK_FLAG_KEY_UNIT),
+                GST_SEEK_TYPE_SET, gint64(time_sec*GST_SECOND),
+                GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
+    }
+    return success;
+}
+
+bool MediaPluginGStreamer10::getTimePos(double &sec_out)
+{
+    bool got_position = false;
+    if (mDoneInit && mPlaybin)
+    {
+        gint64 pos(0);
+        GstFormat timefmt = GST_FORMAT_TIME;
+        got_position =
+            llgst_element_query_position &&
+            llgst_element_query_position(mPlaybin,
+                             &timefmt,
+                             &pos);
+        got_position = got_position
+            && (timefmt == GST_FORMAT_TIME);
+        // GStreamer may have other ideas, but we consider the current position
+        // undefined if not PLAYING or PAUSED
+        got_position = got_position &&
+            (GST_STATE(mPlaybin) == GST_STATE_PLAYING ||
+             GST_STATE(mPlaybin) == GST_STATE_PAUSED);
+        if (got_position && !GST_CLOCK_TIME_IS_VALID(pos))
+        {
+            if (GST_STATE(mPlaybin) == GST_STATE_PLAYING)
+            {
+                // if we're playing then we treat an invalid clock time
+                // as 0, for complicated reasons (insert reason here)
+                pos = 0;
+            }
+            else
+            {
+                got_position = false;
+            }
+            
+        }
+        // If all the preconditions succeeded... we can trust the result.
+        if (got_position)
+        {
+            sec_out = double(pos) / double(GST_SECOND); // gst to sec
+        }
+    }
+    return got_position;
+}
+
+bool MediaPluginGStreamer10::load()
+{
+    if (!mDoneInit)
+        return false; // error
+
+    setStatus(STATUS_LOADING);
+
+    mIsLooping = false;
+    mVolume = 0.1234567f; // minor hack to force an initial volume update
+
+    // Create a pumpable main-loop for this media
+    mPump = llg_main_loop_new (NULL, FALSE);
+    if (!mPump)
+    {
+        setStatus(STATUS_ERROR);
+        return false; // error
+    }
+
+    // instantiate a playbin element to do the hard work
+    mPlaybin = llgst_element_factory_make ("playbin", "");
+    if (!mPlaybin)
+    {
+        setStatus(STATUS_ERROR);
+        return false; // error
+    }
+
+    // get playbin's bus
+    GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin));
+    if (!bus)
+    {
+        setStatus(STATUS_ERROR);
+        return false; // error
+    }
+    mBusWatchID = llgst_bus_add_watch (bus,
+                       llmediaimplgstreamer_bus_callback,
+                       this);
+    llgst_object_unref (bus);
+
+    mAppSink = (GstAppSink*)(llgst_element_factory_make ("appsink", ""));
+
+    GstCaps* pCaps = llgst_caps_new_simple( "video/x-raw",
+                                            "format", G_TYPE_STRING, "RGB",
+                                            "width", G_TYPE_INT, INTERNAL_TEXTURE_SIZE,
+                                            "height", G_TYPE_INT, INTERNAL_TEXTURE_SIZE,
+                                            NULL );
+
+    llgst_app_sink_set_caps( mAppSink, pCaps );
+    llgst_caps_unref( pCaps );
+
+    if (!mAppSink)
+    {
+        setStatus(STATUS_ERROR);
+        return false;
+    }
+    
+    llg_object_set(mPlaybin, "video-sink", mAppSink, NULL);
+
+    return true;
+}
+
+bool MediaPluginGStreamer10::unload ()
+{
+    if (!mDoneInit)
+        return false; // error
+
+    // stop getting callbacks for this bus
+    llg_source_remove(mBusWatchID);
+    mBusWatchID = 0;
+
+    if (mPlaybin)
+    {
+        llgst_element_set_state (mPlaybin, GST_STATE_NULL);
+        llgst_object_unref (GST_OBJECT (mPlaybin));
+        mPlaybin = NULL;
+    }
+
+    if (mPump)
+    {
+        llg_main_loop_quit(mPump);
+        mPump = NULL;
+    }
+
+    mAppSink = NULL;
+
+    setStatus(STATUS_NONE);
+
+    return true;
+}
+
+void LogFunction(GstDebugCategory *category, GstDebugLevel level, const gchar *file, const gchar *function, gint line, GObject *object, GstDebugMessage *message, gpointer user_data )
+#ifndef LL_LINUX // Docu says we need G_GNUC_NO_INSTRUMENT, but GCC says 'error'
+    G_GNUC_NO_INSTRUMENT
+#endif
+{
+#ifdef LL_LINUX
+    std::cerr << file << ":" << line << "(" << function << "): " << llgst_debug_message_get( message ) << std::endl;
+#endif
+}
+
+//static
+bool MediaPluginGStreamer10::startup()
+{
+    // first - check if GStreamer is explicitly disabled
+    if (NULL != getenv("LL_DISABLE_GSTREAMER"))
+        return false;
+
+    // only do global GStreamer initialization once.
+    if (!mDoneInit)
+    {
+        ll_init_apr();
+
+        // Get symbols!
+        std::vector< std::string > vctDSONames;
+#if LL_DARWIN
+#elif LL_WINDOWS
+        vctDSONames.push_back( "libgstreamer-1.0-0.dll"  );
+        vctDSONames.push_back( "libgstapp-1.0-0.dll"  );
+        vctDSONames.push_back( "libglib-2.0-0.dll" );
+        vctDSONames.push_back( "libgobject-2.0-0.dll" );
+#else // linux or other ELFy unixoid
+        vctDSONames.push_back( "libgstreamer-1.0.so.0"  );
+        vctDSONames.push_back( "libgstapp-1.0.so.0"  );
+        vctDSONames.push_back( "libglib-2.0.so.0" );
+        vctDSONames.push_back( "libgobject-2.0.so" );
+#endif
+        if( !grab_gst_syms( vctDSONames ) )
+        {
+            return false;
+        }
+
+        if (llgst_segtrap_set_enabled)
+        {
+            llgst_segtrap_set_enabled(FALSE);
+        }
+#if LL_LINUX
+        // Gstreamer tries a fork during init, waitpid-ing on it,
+        // which conflicts with any installed SIGCHLD handler...
+        struct sigaction tmpact, oldact;
+        if (llgst_registry_fork_set_enabled ) {
+            // if we can disable SIGCHLD-using forking behaviour,
+            // do it.
+            llgst_registry_fork_set_enabled(false);
+        }
+        else {
+            // else temporarily install default SIGCHLD handler
+            // while GStreamer initialises
+            tmpact.sa_handler = SIG_DFL;
+            sigemptyset( &tmpact.sa_mask );
+            tmpact.sa_flags = SA_SIGINFO;
+            sigaction(SIGCHLD, &tmpact, &oldact);
+        }
+#endif // LL_LINUX
+        // Protect against GStreamer resetting the locale, yuck.
+        static std::string saved_locale;
+        saved_locale = setlocale(LC_ALL, NULL);
+        
+//      _putenv_s( "GST_PLUGIN_PATH", "E:\\gstreamer\\1.0\\x86\\lib\\gstreamer-1.0" );
+
+        llgst_debug_set_default_threshold( GST_LEVEL_WARNING );
+        llgst_debug_add_log_function( LogFunction, NULL, NULL );
+        llgst_debug_set_active( false );
+
+        // finally, try to initialize GStreamer!
+        GError *err = NULL;
+        gboolean init_gst_success = llgst_init_check(NULL, NULL, &err);
+
+        // restore old locale
+        setlocale(LC_ALL, saved_locale.c_str() );
+
+#if LL_LINUX
+        // restore old SIGCHLD handler
+        if (!llgst_registry_fork_set_enabled)
+            sigaction(SIGCHLD, &oldact, NULL);
+#endif // LL_LINUX
+
+        if (!init_gst_success) // fail
+        {
+            if (err)
+            {
+                llg_error_free(err);
+            }
+            return false;
+        }
+        
+        mDoneInit = true;
+    }
+
+    return true;
+}
+
+//static
+bool MediaPluginGStreamer10::closedown()
+{
+    if (!mDoneInit)
+        return false; // error
+
+    ungrab_gst_syms();
+
+    mDoneInit = false;
+
+    return true;
+}
+
+MediaPluginGStreamer10::~MediaPluginGStreamer10()
+{
+    closedown();
+}
+
+
+std::string MediaPluginGStreamer10::getVersion()
+{
+    std::string plugin_version = "GStreamer10 media plugin, GStreamer version ";
+    if (mDoneInit &&
+        llgst_version)
+    {
+        guint major, minor, micro, nano;
+        llgst_version(&major, &minor, &micro, &nano);
+        plugin_version += llformat("%u.%u.%u.%u (runtime), %u.%u.%u.%u (headers)", (unsigned int)major, (unsigned int)minor,
+                                   (unsigned int)micro, (unsigned int)nano, (unsigned int)GST_VERSION_MAJOR, (unsigned int)GST_VERSION_MINOR,
+                                   (unsigned int)GST_VERSION_MICRO, (unsigned int)GST_VERSION_NANO);
+    }
+    else
+    {
+        plugin_version += "(unknown)";
+    }
+    return plugin_version;
+}
+
+void MediaPluginGStreamer10::receiveMessage(const char *message_string)
+{
+    LLPluginMessage message_in;
+
+    if(message_in.parse(message_string) >= 0)
+    {
+        std::string message_class = message_in.getClass();
+        std::string message_name = message_in.getName();
+
+        if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
+        {
+            if(message_name == "init")
+            {
+                LLPluginMessage message("base", "init_response");
+                LLSD versions = LLSD::emptyMap();
+                versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
+                versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
+                versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
+                message.setValueLLSD("versions", versions);
+
+                load();
+
+                message.setValue("plugin_version", getVersion());
+                sendMessage(message);
+            }
+            else if(message_name == "idle")
+            {
+                // no response is necessary here.
+                double time = message_in.getValueReal("time");
+                
+                // Convert time to milliseconds for update()
+                update((int)(time * 1000.0f));
+            }
+            else if(message_name == "cleanup")
+            {
+                unload();
+                closedown();
+            }
+            else if(message_name == "shm_added")
+            {
+                SharedSegmentInfo info;
+                info.mAddress = message_in.getValuePointer("address");
+                info.mSize = (size_t)message_in.getValueS32("size");
+                std::string name = message_in.getValue("name");
+
+                mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
+            }
+            else if(message_name == "shm_remove")
+            {
+                std::string name = message_in.getValue("name");
+
+                SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+                if(iter != mSharedSegments.end())
+                {
+                    if(mPixels == iter->second.mAddress)
+                    {
+                        // This is the currently active pixel buffer.  Make sure we stop drawing to it.
+                        mPixels = NULL;
+                        mTextureSegmentName.clear();
+                    }
+                    mSharedSegments.erase(iter);
+                }
+
+                // Send the response so it can be cleaned up.
+                LLPluginMessage message("base", "shm_remove_response");
+                message.setValue("name", name);
+                sendMessage(message);
+            }
+        }
+        else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+        {
+            if(message_name == "init")
+            {
+                // Plugin gets to decide the texture parameters to use.
+                LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
+                // lame to have to decide this now, it depends on the movie.  Oh well.
+                mDepth = 4;
+
+                mTextureWidth = 1;
+                mTextureHeight = 1;
+
+                message.setValueU32("format", GL_RGBA);
+                message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV);
+
+                message.setValueS32("depth", mDepth);
+                message.setValueS32("default_width", INTERNAL_TEXTURE_SIZE );
+                message.setValueS32("default_height", INTERNAL_TEXTURE_SIZE );
+                message.setValueU32("internalformat", GL_RGBA8);
+                message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left.
+                message.setValueBoolean("allow_downsample", true); // we respond with grace and performance if asked to downscale
+                sendMessage(message);
+            }
+            else if(message_name == "size_change")
+            {
+                std::string name = message_in.getValue("name");
+                S32 width = message_in.getValueS32("width");
+                S32 height = message_in.getValueS32("height");
+                S32 texture_width = message_in.getValueS32("texture_width");
+                S32 texture_height = message_in.getValueS32("texture_height");
+
+                LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
+                message.setValue("name", name);
+                message.setValueS32("width", width);
+                message.setValueS32("height", height);
+                message.setValueS32("texture_width", texture_width);
+                message.setValueS32("texture_height", texture_height);
+                sendMessage(message);
+
+                if(!name.empty())
+                {
+                    // Find the shared memory region with this name
+                    SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+                    if(iter != mSharedSegments.end())
+                    {
+                        mPixels = (unsigned char*)iter->second.mAddress;
+                        mTextureSegmentName = name;
+
+                        mTextureWidth = texture_width;
+                        mTextureHeight = texture_height;
+                        memset( mPixels, 0, mTextureWidth*mTextureHeight*mDepth );
+                    }
+                    
+                    LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request");
+                    message.setValue("name", mTextureSegmentName);
+                    message.setValueS32("width", INTERNAL_TEXTURE_SIZE );
+                    message.setValueS32("height", INTERNAL_TEXTURE_SIZE );
+                    sendMessage(message);
+
+                }
+            }
+            else if(message_name == "load_uri")
+            {
+                std::string uri = message_in.getValue("uri");
+                navigateTo( uri );
+                sendStatus();       
+            }
+            else if(message_name == "mouse_event")
+            {
+                std::string event = message_in.getValue("event");
+                S32 x = message_in.getValueS32("x");
+                S32 y = message_in.getValueS32("y");
+                
+                if(event == "down")
+                {
+                    mouseDown(x, y);
+                }
+                else if(event == "up")
+                {
+                    mouseUp(x, y);
+                }
+                else if(event == "move")
+                {
+                    mouseMove(x, y);
+                };
+            };
+        }
+        else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+        {
+            if(message_name == "stop")
+            {
+                stop();
+            }
+            else if(message_name == "start")
+            {
+                double rate = 0.0;
+                if(message_in.hasValue("rate"))
+                {
+                    rate = message_in.getValueReal("rate");
+                }
+                // NOTE: we don't actually support rate.
+                play(rate);
+            }
+            else if(message_name == "pause")
+            {
+                pause();
+            }
+            else if(message_name == "seek")
+            {
+                double time = message_in.getValueReal("time");
+                // defer the actual seek in case we haven't
+                // really truly started yet in which case there
+                // is nothing to seek upon
+                mSeekWanted = true;
+                mSeekDestination = time;
+            }
+            else if(message_name == "set_loop")
+            {
+                bool loop = message_in.getValueBoolean("loop");
+                mIsLooping = loop;
+            }
+            else if(message_name == "set_volume")
+            {
+                double volume = message_in.getValueReal("volume");
+                setVolume(volume);
+            }
+        }
+    }
+}
+
+int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
+{
+    if( MediaPluginGStreamer10::startup() )
+    {
+        MediaPluginGStreamer10 *self = new MediaPluginGStreamer10(host_send_func, host_user_data);
+        *plugin_send_func = MediaPluginGStreamer10::staticReceiveMessage;
+        *plugin_user_data = (void*)self;
+        
+        return 0; // okay
+    }
+    else 
+    {
+        return -1; // failed to init
+    }
+}
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 355f35c558..f359bebb17 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1432,7 +1432,6 @@ if (LINUX)
       PROPERTIES
       COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}"
       )
-    LIST(APPEND viewer_SOURCE_FILES llappviewerlinux_api_dbus.cpp)
     SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed")
 
 endif (LINUX)
diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp
index 9f58f90326..0e7610ebf3 100644
--- a/indra/newview/llappviewerlinux.cpp
+++ b/indra/newview/llappviewerlinux.cpp
@@ -40,17 +40,57 @@
 
 #include <exception>
 
-#if LL_DBUS_ENABLED
-# include "llappviewerlinux_api_dbus.h"
-
-// regrettable hacks to give us better runtime compatibility with older systems inside llappviewerlinux_api.h:
-#define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0)
-#undef g_return_if_fail
-#define g_return_if_fail(COND) llg_return_if_fail(COND)
-// The generated API
-# include "llappviewerlinux_api.h"
+#include <gio/gio.h>
+#include <resolv.h>
+
+#if (__GLIBC__*1000 + __GLIBC_MINOR__) >= 2034
+extern "C"
+{
+  int __res_nquery(res_state statep,
+                   const char *dname, int qclass, int type,
+                   unsigned char *answer, int anslen)
+  {
+    return res_nquery( statep, dname, qclass, type, answer, anslen );
+  }
+
+  int __dn_expand(const unsigned char *msg,
+                  const unsigned char *eomorig,
+                  const unsigned char *comp_dn, char *exp_dn,
+                  int length)
+  {
+    return dn_expand( msg,eomorig,comp_dn,exp_dn,length);
+  }
+}
+#endif
+
+#if LL_SEND_CRASH_REPORTS
+#include "breakpad/client/linux/handler/exception_handler.h"
+#include "breakpad/common/linux/http_upload.h"
+#include "lldir.h"
+#include "../llcrashlogger/llcrashlogger.h"
+#include "jsoncpp/reader.h" // JSON
+
 #endif
 
+#define VIEWERAPI_SERVICE "com.secondlife.ViewerAppAPIService"
+#define VIEWERAPI_PATH "/com/secondlife/ViewerAppAPI"
+#define VIEWERAPI_INTERFACE "com.secondlife.ViewerAppAPI"
+
+static const char * DBUS_SERVER = "<node name=\"/com/secondlife/ViewerAppAPI\">\n"
+                                  "  <interface name=\"com.secondlife.ViewerAppAPI\">\n"
+                                  "    <annotation name=\"org.freedesktop.DBus.GLib.CSymbol\" value=\"viewer_app_api\"/>\n"
+                                  "    <method name=\"GoSLURL\">\n"
+                                  "      <annotation name=\"org.freedesktop.DBus.GLib.CSymbol\" value=\"dispatchSLURL\"/>\n"
+                                  "      <arg type=\"s\" name=\"slurl\" direction=\"in\" />\n"
+                                  "    </method>\n"
+                                  "  </interface>\n"
+                                  "</node>";
+
+typedef struct
+{
+    GObject parent;
+} ViewerAppAPI;
+
 namespace
 {
 	int gArgC = 0;
@@ -81,6 +121,8 @@ int main( int argc, char **argv )
 	// install unexpected exception handler
 	gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler);
 
+	unsetenv( "LD_PRELOAD" ); // <FS:ND/> Get rid of any preloading, we do not want this to happen during startup of plugins.
+	
 	bool ok = viewer_app_ptr->init();
 	if(!ok)
 	{
@@ -114,22 +156,75 @@ LLAppViewerLinux::~LLAppViewerLinux()
 {
 }
 
-bool LLAppViewerLinux::init()
+#if LL_SEND_CRASH_REPORTS
+std::string gCrashLogger;
+std::string gVersion;
+std::string gBugsplatDB;
+std::string gCrashBehavior;
+
+static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded)
 {
-	// g_thread_init() must be called before *any* use of glib, *and*
-	// before any mutexes are held, *and* some of our third-party
-	// libraries likes to use glib functions; in short, do this here
-	// really early in app startup!
-	if (!g_thread_supported ()) g_thread_init (NULL);
+	if( fork() == 0 )
+		execl( gCrashLogger.c_str(), gCrashLogger.c_str(), descriptor.path(), gVersion.c_str(), gBugsplatDB.c_str(),  gCrashBehavior.c_str(), nullptr );
+    return succeeded;
+}
+
+void setupBreadpad()
+{
+    std::string build_data_fname(gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "build_data.json"));
+    gCrashLogger =  gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "linux-crash-logger.bin");
+
+    llifstream inf(build_data_fname.c_str());
+    if(!inf.is_open())
+    {
+        LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, can't read '" << build_data_fname << "'" << LL_ENDL;
+        return;
+    }
+
+    Json::Reader reader;
+    Json::Value build_data;
+    if(!reader.parse(inf, build_data, false))
+    {
+        LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, can't parse '" << build_data_fname << "': "
+                             << reader.getFormatedErrorMessages() << LL_ENDL;
+        return;
+    }
+
+    Json::Value BugSplat_DB = build_data["BugSplat DB"];
+    if(!BugSplat_DB)
+    {
+        LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, no 'BugSplat DB' entry in '" << build_data_fname
+                             << "'" << LL_ENDL;
+        return;
+    }
+    gVersion = STRINGIZE(
+            LL_VIEWER_VERSION_MAJOR << '.' << LL_VIEWER_VERSION_MINOR << '.' << LL_VIEWER_VERSION_PATCH
+                                    << '.' << LL_VIEWER_VERSION_BUILD);
+    gBugsplatDB = BugSplat_DB.asString();
+
+	LL_INFOS("BUGSPLAT") << "Initializing with crash logger: " << gCrashLogger << " database: " << gBugsplatDB << " version: " << gVersion << LL_ENDL;
 	
+    google_breakpad::MinidumpDescriptor *descriptor = new google_breakpad::MinidumpDescriptor(gDirUtilp->getExpandedFilename(LL_PATH_DUMP, ""));
+    google_breakpad::ExceptionHandler *eh = new google_breakpad::ExceptionHandler(*descriptor, NULL, dumpCallback, NULL, true, -1);
+}
+#endif
+
+bool LLAppViewerLinux::init()
+{
 	bool success = LLAppViewer::init();
 
 #if LL_SEND_CRASH_REPORTS
-    if (success)
-    {
-        LLAppViewer* pApp = LLAppViewer::instance();
-        pApp->initCrashReporting();
-    }
+    S32 nCrashSubmitBehavior = gCrashSettings.getS32("CrashSubmitBehavior");
+
+	// For the first version we just consider always send and create a nice dialog for CRASH_BEHAVIOR_ASK later.
+    if (success && nCrashSubmitBehavior != CRASH_BEHAVIOR_NEVER_SEND )
+	{
+		if( nCrashSubmitBehavior == CRASH_BEHAVIOR_ASK )
+			gCrashBehavior = "ask";
+		else
+			gCrashBehavior = "send";
+        setupBreadpad();
+	}
 #endif
 
 	return success;
@@ -143,7 +238,7 @@ bool LLAppViewerLinux::restoreErrorTrap()
 }
 
 /////////////////////////////////////////
-#if LL_DBUS_ENABLED
+#if LL_GLIB
 
 typedef struct
 {
@@ -153,101 +248,77 @@ typedef struct
 static void viewerappapi_init(ViewerAppAPI *server);
 static void viewerappapi_class_init(ViewerAppAPIClass *klass);
 
-///
-
-// regrettable hacks to give us better runtime compatibility with older systems in general
-static GType llg_type_register_static_simple_ONCE(GType parent_type,
-						  const gchar *type_name,
-						  guint class_size,
-						  GClassInitFunc class_init,
-						  guint instance_size,
-						  GInstanceInitFunc instance_init,
-						  GTypeFlags flags)
-{
-	static GTypeInfo type_info;
-	memset(&type_info, 0, sizeof(type_info));
-
-	type_info.class_size = class_size;
-	type_info.class_init = class_init;
-	type_info.instance_size = instance_size;
-	type_info.instance_init = instance_init;
-
-	return g_type_register_static(parent_type, type_name, &type_info, flags);
-}
-#define llg_intern_static_string(S) (S)
-#define g_intern_static_string(S) llg_intern_static_string(S)
-#define g_type_register_static_simple(parent_type, type_name, class_size, class_init, instance_size, instance_init, flags) llg_type_register_static_simple_ONCE(parent_type, type_name, class_size, class_init, instance_size, instance_init, flags)
-
 G_DEFINE_TYPE(ViewerAppAPI, viewerappapi, G_TYPE_OBJECT);
 
 void viewerappapi_class_init(ViewerAppAPIClass *klass)
 {
 }
 
-static bool dbus_server_init = false;
-
-void viewerappapi_init(ViewerAppAPI *server)
+static void dispatchSLURL(gchar const *slurl)
 {
-	// Connect to the default DBUS, register our service/API.
+    LL_INFOS() << "Was asked to go to slurl: " << slurl << LL_ENDL;
 
-	if (!dbus_server_init)
-	{
-		GError *error = NULL;
-		
-		server->connection = lldbus_g_bus_get(DBUS_BUS_SESSION, &error);
-		if (server->connection)
-		{
-			lldbus_g_object_type_install_info(viewerappapi_get_type(), &dbus_glib_viewerapp_object_info);
-			
-			lldbus_g_connection_register_g_object(server->connection, VIEWERAPI_PATH, G_OBJECT(server));
-			
-			DBusGProxy *serverproxy = lldbus_g_proxy_new_for_name(server->connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
+    std::string url = slurl;
+    LLMediaCtrl* web = NULL;
+    const bool trusted_browser = false;
+    LLURLDispatcher::dispatch(url, "", web, trusted_browser);
+}
 
-			guint request_name_ret_unused;
-			// akin to org_freedesktop_DBus_request_name
-			if (lldbus_g_proxy_call(serverproxy, "RequestName", &error, G_TYPE_STRING, VIEWERAPI_SERVICE, G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT, &request_name_ret_unused, G_TYPE_INVALID))
-			{
-				// total success.
-				dbus_server_init = true;
-			}
-			else 
-			{
-				LL_WARNS() << "Unable to register service name: " << error->message << LL_ENDL;
-			}
-	
-			g_object_unref(serverproxy);
-		}
-		else
-		{
-			g_warning("Unable to connect to dbus: %s", error->message);
-		}
+static void DoMethodeCall (GDBusConnection       *connection,
+                                const gchar           *sender,
+                                const gchar           *object_path,
+                                const gchar           *interface_name,
+                                const gchar           *method_name,
+                                GVariant              *parameters,
+                                GDBusMethodInvocation *invocation,
+                                gpointer               user_data)
+{
+    LL_INFOS() << "DBUS message " << method_name << "  from: " << sender << " interface: " << interface_name << LL_ENDL;
+    const gchar *slurl;
 
-		if (error)
-			g_error_free(error);
-	}
+    g_variant_get (parameters, "(&s)", &slurl);
+    dispatchSLURL(slurl);
 }
 
-gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean **success_rtn, GError **error)
+GDBusNodeInfo *gBusNodeInfo = nullptr;
+static const GDBusInterfaceVTable interface_vtable =
+        {
+                DoMethodeCall
+        };
+static void busAcquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
 {
-	bool success = false;
+    auto id = g_dbus_connection_register_object(connection,
+                                                VIEWERAPI_PATH,
+                                                gBusNodeInfo->interfaces[0],
+                                                &interface_vtable,
+                                                NULL,  /* user_data */
+                                                             NULL,  /* user_data_free_func */
+                                                             NULL); /* GError** */
+    g_assert (id > 0);
+}
 
-	LL_INFOS() << "Was asked to go to slurl: " << slurl << LL_ENDL;
+static void nameAcquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
+{
+}
 
-	std::string url = slurl;
-	LLMediaCtrl* web = NULL;
-	const bool trusted_browser = false;
-	if (LLURLDispatcher::dispatch(url, "", web, trusted_browser))
-	{
-		// bring window to foreground, as it has just been "launched" from a URL
-		// todo: hmm, how to get there from here?
-		//xxx->mWindow->bringToFront();
-		success = true;
-	}		
+static void nameLost(GDBusConnection *connection, const gchar *name, gpointer user_data)
+{
 
-	*success_rtn = g_new (gboolean, 1);
-	(*success_rtn)[0] = (gboolean)success;
+}
+void viewerappapi_init(ViewerAppAPI *server)
+{
+    gBusNodeInfo = g_dbus_node_info_new_for_xml (DBUS_SERVER, NULL);
+    g_assert (gBusNodeInfo != NULL);
+
+    g_bus_own_name(G_BUS_TYPE_SESSION,
+                   VIEWERAPI_SERVICE,
+                   G_BUS_NAME_OWNER_FLAGS_NONE,
+                   busAcquired,
+                   nameAcquired,
+                   nameLost,
+                   NULL,
+                   NULL);
 
-	return TRUE; // the invokation succeeded, even if the actual dispatch didn't.
 }
 
 ///
@@ -255,13 +326,6 @@ gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean **succ
 //virtual
 bool LLAppViewerLinux::initSLURLHandler()
 {
-	if (!grab_dbus_syms(DBUSGLIB_DYLIB_DEFAULT_NAME))
-	{
-		return false; // failed
-	}
-
-	g_type_init();
-
 	//ViewerAppAPI *api_server = (ViewerAppAPI*)
 	g_object_new(viewerappapi_get_type(), NULL);
 
@@ -271,49 +335,49 @@ bool LLAppViewerLinux::initSLURLHandler()
 //virtual
 bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url)
 {
-	if (!grab_dbus_syms(DBUSGLIB_DYLIB_DEFAULT_NAME))
-	{
-		return false; // failed
-	}
+	auto *pBus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, nullptr);
 
-	bool success = false;
-	DBusGConnection *bus;
-	GError *error = NULL;
+    if( !pBus )
+    {
+        LL_WARNS() << "Getting dbus failed." << LL_ENDL;
+        return false;
+    }
 
-	g_type_init();
-	
-	bus = lldbus_g_bus_get (DBUS_BUS_SESSION, &error);
-	if (bus)
-	{
-		gboolean rtn = FALSE;
-		DBusGProxy *remote_object =
-			lldbus_g_proxy_new_for_name(bus, VIEWERAPI_SERVICE, VIEWERAPI_PATH, VIEWERAPI_INTERFACE);
+    auto pProxy = g_dbus_proxy_new_sync(pBus, G_DBUS_PROXY_FLAGS_NONE, nullptr,
+                                        VIEWERAPI_SERVICE, VIEWERAPI_PATH,
+                                        VIEWERAPI_INTERFACE, nullptr, nullptr);
 
-		if (lldbus_g_proxy_call(remote_object, "GoSLURL", &error,
-					G_TYPE_STRING, url.c_str(), G_TYPE_INVALID,
-				       G_TYPE_BOOLEAN, &rtn, G_TYPE_INVALID))
-		{
-			success = rtn;
-		}
-		else
-		{
-			LL_INFOS() << "Call-out to other instance failed (perhaps not running): " << error->message << LL_ENDL;
-		}
+    if( !pProxy )
+    {
+        LL_WARNS() << "Cannot create new dbus proxy." << LL_ENDL;
+        g_object_unref( pBus );
+        return false;
+    }
 
-		g_object_unref(G_OBJECT(remote_object));
-	}
-	else
-	{
-		LL_WARNS() << "Couldn't connect to session bus: " << error->message << LL_ENDL;
-	}
+    auto *pArgs = g_variant_new( "(s)", url.c_str() );
+    if( !pArgs )
+    {
+        LL_WARNS() << "Cannot create new variant." << LL_ENDL;
+        g_object_unref( pBus );
+        return false;
+    }
 
-	if (error)
-		g_error_free(error);
-	
-	return success;
+    auto pRes  = g_dbus_proxy_call_sync(pProxy,
+                                        "GoSLURL",
+                                        pArgs,
+                                        G_DBUS_CALL_FLAGS_NONE,
+                                        -1, nullptr, nullptr);
+
+
+
+    if( pRes )
+        g_variant_unref( pRes );
+    g_object_unref( pProxy );
+    g_object_unref( pBus );
+    return true;
 }
 
-#else // LL_DBUS_ENABLED
+#else // LL_GLIB
 bool LLAppViewerLinux::initSLURLHandler()
 {
 	return false; // not implemented without dbus
@@ -322,7 +386,7 @@ bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url)
 {
 	return false; // not implemented without dbus
 }
-#endif // LL_DBUS_ENABLED
+#endif // LL_GLIB
 
 void LLAppViewerLinux::initCrashReporting(bool reportFreeze)
 {
@@ -338,15 +402,18 @@ void LLAppViewerLinux::initCrashReporting(bool reportFreeze)
     pid_str <<  LLApp::getPid();
     std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
     std::string appname = gDirUtilp->getExecutableFilename();
+	std::string grid{ LLGridManager::getInstance()->getGridId() };
+	std::string title{ LLAppViewer::instance()->getSecondLifeTitle() };
+	std::string pidstr{ pid_str.str() };
 	// launch the actual crash logger
 	const char * cmdargv[] =
 		{cmd.c_str(),
 		 "-user",
-		 (char*)LLGridManager::getInstance()->getGridId().c_str(),
+		 grid.c_str(),
 		 "-name",
-		 LLAppViewer::instance()->getSecondLifeTitle().c_str(),
+		 title.c_str(),
 		 "-pid", 
-		 pid_str.str().c_str(),
+		 pidstr.c_str(),
 		 "-dumpdir",
 		 logdir.c_str(),
 		 "-procname",
diff --git a/indra/newview/llappviewerlinux.h b/indra/newview/llappviewerlinux.h
index 0289c43043..abe62c9289 100644
--- a/indra/newview/llappviewerlinux.h
+++ b/indra/newview/llappviewerlinux.h
@@ -27,17 +27,6 @@
 #ifndef LL_LLAPPVIEWERLINUX_H
 #define LL_LLAPPVIEWERLINUX_H
 
-extern "C" {
-# include <glib.h>
-}
-
-#if LL_DBUS_ENABLED
-extern "C" {
-# include <glib-object.h>
-# include <dbus/dbus-glib.h>
-}
-#endif
-
 #ifndef LL_LLAPPVIEWER_H
 #include "llappviewer.h"
 #endif
@@ -70,21 +59,4 @@ protected:
 	virtual bool sendURLToOtherInstance(const std::string& url);
 };
 
-#if LL_DBUS_ENABLED
-typedef struct
-{
-        GObject parent;
-        DBusGConnection *connection;
-} ViewerAppAPI;
-
-extern "C" {
-	gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean **success_rtn, GError **error);
-}
-
-#define VIEWERAPI_SERVICE "com.secondlife.ViewerAppAPIService"
-#define VIEWERAPI_PATH "/com/secondlife/ViewerAppAPI"
-#define VIEWERAPI_INTERFACE "com.secondlife.ViewerAppAPI"
-
-#endif // LL_DBUS_ENABLED
-
 #endif // LL_LLAPPVIEWERLINUX_H
diff --git a/indra/newview/llappviewerlinux_api.h b/indra/newview/llappviewerlinux_api.h
deleted file mode 100644
index 5d5fcaa3d6..0000000000
--- a/indra/newview/llappviewerlinux_api.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/* Generated by dbus-binding-tool; do not edit! */
-/**
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */ 
-
-#ifndef __dbus_glib_marshal_viewerapp_MARSHAL_H__
-#define __dbus_glib_marshal_viewerapp_MARSHAL_H__
-
-#include	<glib-object.h>
-
-G_BEGIN_DECLS
-
-#ifdef G_ENABLE_DEBUG
-#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
-#define g_marshal_value_peek_char(v)     g_value_get_char (v)
-#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
-#define g_marshal_value_peek_int(v)      g_value_get_int (v)
-#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
-#define g_marshal_value_peek_long(v)     g_value_get_long (v)
-#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
-#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
-#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
-#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
-#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
-#define g_marshal_value_peek_float(v)    g_value_get_float (v)
-#define g_marshal_value_peek_double(v)   g_value_get_double (v)
-#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
-#define g_marshal_value_peek_param(v)    g_value_get_param (v)
-#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
-#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
-#define g_marshal_value_peek_object(v)   g_value_get_object (v)
-#else /* !G_ENABLE_DEBUG */
-/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
- *          Do not access GValues directly in your code. Instead, use the
- *          g_value_get_*() functions
- */
-#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
-#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
-#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
-#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
-#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
-#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
-#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
-#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
-#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
-#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
-#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
-#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
-#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
-#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
-#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
-#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
-#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
-#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
-#endif /* !G_ENABLE_DEBUG */
-
-
-/* BOOLEAN:STRING,POINTER,POINTER (/tmp/dbus-binding-tool-c-marshallers.5XXD8T:1) */
-extern void dbus_glib_marshal_viewerapp_BOOLEAN__STRING_POINTER_POINTER (GClosure     *closure,
-                                                                         GValue       *return_value,
-                                                                         guint         n_param_values,
-                                                                         const GValue *param_values,
-                                                                         gpointer      invocation_hint,
-                                                                         gpointer      marshal_data);
-void
-dbus_glib_marshal_viewerapp_BOOLEAN__STRING_POINTER_POINTER (GClosure     *closure,
-                                                             GValue       *return_value,
-                                                             guint         n_param_values,
-                                                             const GValue *param_values,
-                                                             gpointer      invocation_hint,
-                                                             gpointer      marshal_data)
-{
-  typedef gboolean (*GMarshalFunc_BOOLEAN__STRING_POINTER_POINTER) (gpointer     data1,
-                                                                    gpointer     arg_1,
-                                                                    gpointer     arg_2,
-                                                                    gpointer     arg_3,
-                                                                    gpointer     data2);
-  register GMarshalFunc_BOOLEAN__STRING_POINTER_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-  gboolean v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 4);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_BOOLEAN__STRING_POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_string (param_values + 1),
-                       g_marshal_value_peek_pointer (param_values + 2),
-                       g_marshal_value_peek_pointer (param_values + 3),
-                       data2);
-
-  g_value_set_boolean (return_value, v_return);
-}
-
-G_END_DECLS
-
-#endif /* __dbus_glib_marshal_viewerapp_MARSHAL_H__ */
-
-#include <dbus/dbus-glib.h>
-static const DBusGMethodInfo dbus_glib_viewerapp_methods[] = {
-  { (GCallback) viewer_app_api_GoSLURL, dbus_glib_marshal_viewerapp_BOOLEAN__STRING_POINTER_POINTER, 0 },
-};
-
-const DBusGObjectInfo dbus_glib_viewerapp_object_info = {
-  0,
-  dbus_glib_viewerapp_methods,
-  1,
-"com.secondlife.ViewerAppAPI\0GoSLURL\0S\0slurl\0I\0s\0success_ret\0O\0F\0N\0b\0\0\0",
-"\0",
-"\0"
-};
-
diff --git a/indra/newview/llappviewerlinux_api.xml b/indra/newview/llappviewerlinux_api.xml
deleted file mode 100644
index fac35b7adc..0000000000
--- a/indra/newview/llappviewerlinux_api.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<!-- dbus-binding-tool -mode=glib-server llappviewerlinux_api.xml -prefix=viewerapp -output=llappviewerlinux_api.h -->
-
-<node name="/com/secondlife/ViewerAppAPI">
-  <interface name="com.secondlife.ViewerAppAPI">
-    <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="viewer_app_api"/>
-    <method name="GoSLURL">
-      <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="viewer_app_api_GoSLURL"/>
-      <arg type="s" name="slurl" direction="in" />
-      <arg type="b" name="success_ret" direction="out" />
-    </method>
-  </interface>
-</node>
diff --git a/indra/newview/llappviewerlinux_api_dbus.cpp b/indra/newview/llappviewerlinux_api_dbus.cpp
deleted file mode 100644
index 6ac30bd9b8..0000000000
--- a/indra/newview/llappviewerlinux_api_dbus.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/** 
- * @file llappviewerlinux_api_dbus.cpp
- * @brief dynamic DBus symbol-grabbing code
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#if LL_DBUS_ENABLED
-
-#include "linden_common.h"
-
-extern "C" {
-#include <dbus/dbus-glib.h>
-
-#include "apr_pools.h"
-#include "apr_dso.h"
-}
-
-#define DEBUGMSG(...) do { LL_DEBUGS() << llformat(__VA_ARGS__) << LL_ENDL; } while(0)
-#define INFOMSG(...) do { LL_INFOS() << llformat(__VA_ARGS__) << LL_ENDL; } while(0)
-#define WARNMSG(...) do { LL_WARNS() << llformat(__VA_ARGS__) << LL_ENDL; } while(0)
-
-#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) RTN (*ll##DBUSSYM)(__VA_ARGS__) = NULL
-#include "llappviewerlinux_api_dbus_syms_raw.inc"
-#undef LL_DBUS_SYM
-
-static bool sSymsGrabbed = false;
-static apr_pool_t *sSymDBUSDSOMemoryPool = NULL;
-static apr_dso_handle_t *sSymDBUSDSOHandleG = NULL;
-
-bool grab_dbus_syms(std::string dbus_dso_name)
-{
-	if (sSymsGrabbed)
-	{
-		// already have grabbed good syms
-		return TRUE;
-	}
-
-	bool sym_error = false;
-	bool rtn = false;
-	apr_status_t rv;
-	apr_dso_handle_t *sSymDBUSDSOHandle = NULL;
-
-#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##DBUSSYM, sSymDBUSDSOHandle, #DBUSSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #DBUSSYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #DBUSSYM, (void*)ll##DBUSSYM);}while(0)
-
-	//attempt to load the shared library
-	apr_pool_create(&sSymDBUSDSOMemoryPool, NULL);
-  
-	if ( APR_SUCCESS == (rv = apr_dso_load(&sSymDBUSDSOHandle,
-					       dbus_dso_name.c_str(),
-					       sSymDBUSDSOMemoryPool) ))
-	{
-		INFOMSG("Found DSO: %s", dbus_dso_name.c_str());
-
-#include "llappviewerlinux_api_dbus_syms_raw.inc"
-      
-		if ( sSymDBUSDSOHandle )
-		{
-			sSymDBUSDSOHandleG = sSymDBUSDSOHandle;
-			sSymDBUSDSOHandle = NULL;
-		}
-      
-		rtn = !sym_error;
-	}
-	else
-	{
-		INFOMSG("Couldn't load DSO: %s", dbus_dso_name.c_str());
-		rtn = false; // failure
-	}
-
-	if (sym_error)
-	{
-		WARNMSG("Failed to find necessary symbols in DBUS-GLIB libraries.");
-	}
-#undef LL_DBUS_SYM
-
-	sSymsGrabbed = rtn;
-	return rtn;
-}
-
-
-void ungrab_dbus_syms()
-{ 
-	// should be safe to call regardless of whether we've
-	// actually grabbed syms.
-
-	if ( sSymDBUSDSOHandleG )
-	{
-		apr_dso_unload(sSymDBUSDSOHandleG);
-		sSymDBUSDSOHandleG = NULL;
-	}
-	
-	if ( sSymDBUSDSOMemoryPool )
-	{
-		apr_pool_destroy(sSymDBUSDSOMemoryPool);
-		sSymDBUSDSOMemoryPool = NULL;
-	}
-	
-	// NULL-out all of the symbols we'd grabbed
-#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) do{ll##DBUSSYM = NULL;}while(0)
-#include "llappviewerlinux_api_dbus_syms_raw.inc"
-#undef LL_DBUS_SYM
-
-	sSymsGrabbed = false;
-}
-
-#endif // LL_DBUS_ENABLED
diff --git a/indra/newview/llappviewerlinux_api_dbus.h b/indra/newview/llappviewerlinux_api_dbus.h
deleted file mode 100644
index 3eee25b53d..0000000000
--- a/indra/newview/llappviewerlinux_api_dbus.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/** 
- * @file llappviewerlinux_api_dbus.h
- * @brief DBus-glib symbol handling
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#if LL_DBUS_ENABLED
-
-extern "C" {
-#include <dbus/dbus-glib.h>
-}
-
-#define DBUSGLIB_DYLIB_DEFAULT_NAME "libdbus-glib-1.so.2"
-
-bool grab_dbus_syms(std::string dbus_dso_name);
-void ungrab_dbus_syms();
-
-#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) extern RTN (*ll##DBUSSYM)(__VA_ARGS__)
-#include "llappviewerlinux_api_dbus_syms_raw.inc"
-#undef LL_DBUS_SYM
-
-#endif // LL_DBUS_ENABLED
diff --git a/indra/newview/llappviewerlinux_api_dbus_syms_raw.inc b/indra/newview/llappviewerlinux_api_dbus_syms_raw.inc
deleted file mode 100644
index c0548e2fba..0000000000
--- a/indra/newview/llappviewerlinux_api_dbus_syms_raw.inc
+++ /dev/null
@@ -1,9 +0,0 @@
-
-// required symbols to grab
-LL_DBUS_SYM(true, dbus_g_bus_get, DBusGConnection*, DBusBusType, GError**);
-LL_DBUS_SYM(true, dbus_g_proxy_new_for_name, DBusGProxy*, DBusGConnection*, const char *, const char*, const char*);
-LL_DBUS_SYM(true, dbus_g_proxy_call, gboolean, DBusGProxy*, const char*, GError**, GType, ...);
-LL_DBUS_SYM(true, dbus_g_object_type_install_info, void, GType, const DBusGObjectInfo*);
-LL_DBUS_SYM(true, dbus_g_connection_register_g_object, void, DBusGConnection*, const char*, GObject*);
-
-// optional symbols to grab
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index b9bf432581..eddae953a7 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -1190,7 +1190,7 @@ LLView* LLChatHistory::getHeader(const LLChat& chat,const LLStyle::Params& style
 	LLChatHistoryHeader* header = LLChatHistoryHeader::createInstance(mMessageHeaderFilename);
     if (header)
         header->setup(chat, style_params, args);
-	return header;
+    return header;
 }
 
 void LLChatHistory::onClickMoreText()
diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp
index 97b16a5e93..e027ddaeb0 100644
--- a/indra/newview/llconversationloglist.cpp
+++ b/indra/newview/llconversationloglist.cpp
@@ -93,9 +93,10 @@ BOOL LLConversationLogList::handleRightMouseDown(S32 x, S32 y, MASK mask)
 	LLToggleableMenu* context_menu = mContextMenu.get();
 	{
 		context_menu->buildDrawLabels();
-	if (context_menu && size())
-		context_menu->updateParent(LLMenuGL::sMenuContainer);
-		LLMenuGL::showPopup(this, context_menu, x, y);
+        if (context_menu && size())
+            context_menu->updateParent(LLMenuGL::sMenuContainer);
+
+        LLMenuGL::showPopup(this, context_menu, x, y);
 	}
 
 	return handled;
diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp
index 01790ad19e..e541d2ab00 100644
--- a/indra/newview/lldirpicker.cpp
+++ b/indra/newview/lldirpicker.cpp
@@ -41,6 +41,10 @@
 # include "llfilepicker.h"
 #endif
 
+#ifdef LL_FLTK
+  #include "FL/Fl.H"
+  #include "FL/Fl_Native_File_Chooser.H"
+#endif
 //
 // Globals
 //
@@ -193,20 +197,28 @@ LLDirPicker::LLDirPicker() :
 	mFileName(NULL),
 	mLocked(false)
 {
+#ifndef LL_FLTK
 	mFilePicker = new LLFilePicker();
+#endif
 	reset();
 }
 
 LLDirPicker::~LLDirPicker()
 {
+#ifndef LL_FLTK
 	delete mFilePicker;
+#endif
 }
 
 
 void LLDirPicker::reset()
 {
+#ifndef LL_FLTK
 	if (mFilePicker)
 		mFilePicker->reset();
+#else
+	mDir = "";
+#endif
 }
 
 BOOL LLDirPicker::getDir(std::string* filename, bool blocking)
@@ -219,6 +231,7 @@ BOOL LLDirPicker::getDir(std::string* filename, bool blocking)
 		return FALSE;
 	}
 
+#ifndef LL_FLTK
 #if !LL_MESA_HEADLESS
 
 	if (mFilePicker)
@@ -237,15 +250,38 @@ BOOL LLDirPicker::getDir(std::string* filename, bool blocking)
 #endif // !LL_MESA_HEADLESS
 
 	return FALSE;
+#else
+    gViewerWindow->getWindow()->beforeDialog();
+	Fl_Native_File_Chooser flDlg;
+	flDlg.title(LLTrans::getString("choose_the_directory").c_str());
+	flDlg.type(Fl_Native_File_Chooser::BROWSE_DIRECTORY );
+	int res = flDlg.show();
+    gViewerWindow->getWindow()->afterDialog();
+	if( res == 0 )
+	{
+		char const *pDir = flDlg.filename(0);
+		if( pDir )
+			mDir = pDir;
+	}
+	else if( res == -1 )
+	{
+		LL_WARNS() << "FLTK failed: " <<  flDlg.errmsg() << LL_ENDL;
+	}
+	return !mDir.empty();
+#endif
 }
 
 std::string LLDirPicker::getDirName()
 {
+#ifndef LL_FLTK
 	if (mFilePicker)
 	{
 		return mFilePicker->getFirstFile();
 	}
 	return "";
+#else
+	return mDir;
+#endif
 }
 
 #else // not implemented
diff --git a/indra/newview/lldirpicker.h b/indra/newview/lldirpicker.h
index 52febe4523..a1571bcb16 100644
--- a/indra/newview/lldirpicker.h
+++ b/indra/newview/lldirpicker.h
@@ -80,8 +80,10 @@ private:
 
 #if LL_LINUX || LL_DARWIN
 	// On Linux we just implement LLDirPicker on top of LLFilePicker
+#ifndef LL_FLTK
 	LLFilePicker *mFilePicker;
 #endif
+#endif
 
 
 	std::string* mFileName;
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index c1776705f9..b6405df1ff 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -839,7 +839,6 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
 		//VECTORIZE THIS
 		LLMatrix4a mat_vert;
 		mat_vert.loadu(mat_vert_in);
-        LLVector4a new_extents[2];
 
 		llassert(less_than_max_mag(face.mExtents[0]));
 		llassert(less_than_max_mag(face.mExtents[1]));
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index 5b8ca6c49c..a7998f6e9e 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -947,7 +947,7 @@ void LLFastTimerView::printLineStats()
 	{
 		std::string legend_stat;
 		bool first = true;
-		for(block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME);
+		for(LLTrace::block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME);
 			it != LLTrace::end_block_timer_tree_df();
 			++it)
 		{
@@ -969,7 +969,7 @@ void LLFastTimerView::printLineStats()
 
 		std::string timer_stat;
 		first = true;
-		for(block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME);
+		for(LLTrace::block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME);
 			it != LLTrace::end_block_timer_tree_df();
 			++it)
 		{
@@ -1046,7 +1046,7 @@ void LLFastTimerView::drawLineGraph()
 	F32Seconds cur_max(0);
 	U32 cur_max_calls = 0;
 
-	for(block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME);
+	for(LLTrace::block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME);
 		it != LLTrace::end_block_timer_tree_df();
 		++it)
 	{
@@ -1195,8 +1195,8 @@ void LLFastTimerView::drawLegend()
 		S32 scroll_offset = 0; // element's y offset from top of the inner scroll's rect
 		ft_display_idx.clear();
 		std::map<BlockTimerStatHandle*, S32> display_line;
-		for (block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME);
-			it != block_timer_tree_df_iterator_t();
+		for (LLTrace::block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME);
+			it != LLTrace::end_block_timer_tree_df();
 			++it)
 		{
 			BlockTimerStatHandle* idp = (*it);
@@ -1311,8 +1311,8 @@ void LLFastTimerView::generateUniqueColors()
 
 		F32 hue = 0.f;
 
-		for (block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME);
-			it != block_timer_tree_df_iterator_t();
+		for (LLTrace::block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME);
+			it != LLTrace::end_block_timer_tree_df();
 			++it)
 		{
 			BlockTimerStatHandle* idp = (*it);
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index 38daff9937..5686627776 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -33,6 +33,12 @@
 #ifndef LL_LLFILEPICKER_H
 #define LL_LLFILEPICKER_H
 
+#if LL_FLTK
+  #if LL_GTK
+    #undef LL_GTK
+  #endif
+#endif
+
 #include "stdtypes.h"
 
 #if LL_DARWIN
@@ -58,6 +64,7 @@ extern "C" {
 // mostly for Linux, possible on others
 #if LL_GTK
 # include "gtk/gtk.h"
+#error "Direct use of GTK is deprecated"
 #endif // LL_GTK
 }
 
@@ -192,6 +199,13 @@ private:
 	// we also remember the extension of the last added file.
 	std::string mCurrentExtension;
 #endif
+#if LL_FLTK
+    enum EType
+    {
+     eSaveFile, eOpenFile, eOpenMultiple
+    };
+    bool openFileDialog( int32_t filter, bool blocking, EType aType );
+#endif
 
 	std::vector<std::string> mFiles;
 	S32 mCurrentFile;
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index d4eb40ff92..fdfc5b08cb 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -3850,15 +3850,14 @@ void LLPanelRegionEnvironment::onChkAllowOverride(bool value)
     mAllowOverrideRestore = mAllowOverride;
     mAllowOverride = value;
 
-
     std::string notification("EstateParcelEnvironmentOverride");
     if (LLPanelEstateInfo::isLindenEstate())
         notification = "ChangeLindenEstate";
 
-	LLSD args;
-	args["ESTATENAME"] = LLEstateInfoModel::instance().getName();
-	LLNotification::Params params(notification);
-	params.substitutions(args);
+    LLSD args;
+    args["ESTATENAME"] = LLEstateInfoModel::instance().getName();
+    LLNotification::Params params(notification);
+    params.substitutions(args);
     params.functor.function([this](const LLSD& notification, const LLSD& response) { confirmUpdateEstateEnvironment(notification, response); });
 
     if (!value || LLPanelEstateInfo::isLindenEstate())
diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp
index 6a2daeeb90..1f6ad85be7 100644
--- a/indra/newview/llhttpretrypolicy.cpp
+++ b/indra/newview/llhttpretrypolicy.cpp
@@ -91,14 +91,14 @@ void LLAdaptiveRetryPolicy::onSuccess()
 
 void LLAdaptiveRetryPolicy::onFailure(S32 status, const LLSD& headers)
 {
-	F32 retry_header_time;
+	F32 retry_header_time{};
 	bool has_retry_header_time = getRetryAfter(headers,retry_header_time);
 	onFailureCommon(status, has_retry_header_time, retry_header_time);
 }
   
 void LLAdaptiveRetryPolicy::onFailure(const LLCore::HttpResponse *response)
 {
-	F32 retry_header_time;
+	F32 retry_header_time{};
 	const LLCore::HttpHeaders::ptr_t headers = response->getHeaders();
 	bool has_retry_header_time = getRetryAfter(headers,retry_header_time);
 	onFailureCommon(response->getStatus().getType(), has_retry_header_time, retry_header_time);
@@ -184,4 +184,3 @@ bool LLAdaptiveRetryPolicy::getSecondsUntilRetryAfter(const std::string& retry_a
 
     return true;
 }
-
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 7b4283e94d..6091488c53 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -621,13 +621,13 @@ bool LLInventoryFilter::checkAgainstSearchVisibility(const LLFolderViewModelItem
     if (listener->isItemInOutfits() && ((mFilterOps.mSearchVisibility & VISIBILITY_OUTFITS) == 0))
         return FALSE;
 
-	if (listener->isItemInTrash() && ((mFilterOps.mSearchVisibility & VISIBILITY_TRASH) == 0))
-		return FALSE;
+    if (listener->isItemInTrash() && ((mFilterOps.mSearchVisibility & VISIBILITY_TRASH) == 0))
+        return FALSE;
 
-	if (!listener->isAgentInventory() && ((mFilterOps.mSearchVisibility & VISIBILITY_LIBRARY) == 0))
-		return FALSE;
+    if (!listener->isAgentInventory() && ((mFilterOps.mSearchVisibility & VISIBILITY_LIBRARY) == 0))
+        return FALSE;
 
-	return TRUE;
+    return TRUE;
 }
 
 const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const
diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp
index 5f4b816b99..bfa87a9834 100644
--- a/indra/newview/llinventorygallerymenu.cpp
+++ b/indra/newview/llinventorygallerymenu.cpp
@@ -564,7 +564,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
             items.push_back(std::string("Copy Asset UUID"));
             items.push_back(std::string("Copy Separator"));
 
-            bool is_asset_knowable = is_asset_knowable = LLAssetType::lookupIsAssetIDKnowable(obj->getType());
+            bool is_asset_knowable = LLAssetType::lookupIsAssetIDKnowable(obj->getType());
             if ( !is_asset_knowable // disable menu item for Inventory items with unknown asset. EXT-5308
                  || (! ( is_full_perm_item || gAgent.isGodlike())))
             {
diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp
index feb691520f..98c1019f03 100644
--- a/indra/newview/llmanip.cpp
+++ b/indra/newview/llmanip.cpp
@@ -568,9 +568,6 @@ void LLManip::renderTickValue(const LLVector3& pos, F32 value, const std::string
 			gGL.scalef(inv_zoom_amt, inv_zoom_amt, inv_zoom_amt);
 		}
 
-		LLColor4 shadow_color = LLColor4::black;
-		shadow_color.mV[VALPHA] = color.mV[VALPHA] * 0.5f;
-
 		if (fractional_portion != 0)
 		{
 			fraction_string = llformat("%c%02d%s", LLResMgr::getInstance()->getDecimalPoint(), fractional_portion, suffix.c_str());
diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp
index d3b981e205..b0953f929c 100644
--- a/indra/newview/llmediadataclient.cpp
+++ b/indra/newview/llmediadataclient.cpp
@@ -204,7 +204,7 @@ bool LLMediaDataClient::isInQueue(const LLMediaDataClientObject::ptr_t &object)
     if (std::find_if(mUnQueuedRequests.begin(), mUnQueuedRequests.end(), upred) != mUnQueuedRequests.end())
         return true;
     
-	return false;
+    return false;
 }
 
 void LLMediaDataClient::removeFromQueue(const LLMediaDataClientObject::ptr_t &object)
@@ -829,7 +829,7 @@ bool LLObjectMediaDataClient::isInQueue(const LLMediaDataClientObject::ptr_t &ob
     if (std::find_if(mRoundRobinQueue.begin(), mRoundRobinQueue.end(), PredicateMatchRequest(object->getID())) != mRoundRobinQueue.end())
         return true;
 
-	return false;
+    return false;
 }
 
 void LLObjectMediaDataClient::removeFromQueue(const LLMediaDataClientObject::ptr_t &object)
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index a527ebe47f..a72d7f2773 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -5229,7 +5229,7 @@ void LLPanelFace::LLSelectedTE::getFace(LLFace*& face_to_return, bool& identical
 
 void LLPanelFace::LLSelectedTE::getImageFormat(LLGLenum& image_format_to_return, bool& identical_face)
 {
-	LLGLenum image_format;
+	LLGLenum image_format{};
 	struct LLSelectedTEGetImageFormat : public LLSelectedTEGetFunctor<LLGLenum>
 	{
 		LLGLenum get(LLViewerObject* object, S32 te_index)
@@ -5495,4 +5495,3 @@ void LLPanelFace::LLSelectedTE::getMaxDiffuseRepeats(F32& repeats, bool& identic
 	} max_diff_repeats_func;
 	identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_diff_repeats_func, repeats );
 }
-
diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h
index a64b85815f..2c466d4698 100644
--- a/indra/newview/llpanelface.h
+++ b/indra/newview/llpanelface.h
@@ -395,7 +395,7 @@ private:
 		ReturnType (LLMaterial::* const MaterialGetFunc)() const  >
 	static void getTEMaterialValue(DataType& data_to_return, bool& identical,DataType default_value, bool has_tolerance = false, DataType tolerance = DataType())
 	{
-		DataType data_value;
+		DataType data_value{};
 		struct GetTEMaterialVal : public LLSelectedTEGetFunctor<DataType>
 		{
 			GetTEMaterialVal(DataType default_value) : _default(default_value) {}
@@ -428,7 +428,7 @@ private:
 		ReturnType (LLTextureEntry::* const TEGetFunc)() const >
 	static void getTEValue(DataType& data_to_return, bool& identical, DataType default_value, bool has_tolerance = false, DataType tolerance = DataType())
 	{
-		DataType data_value;
+		DataType data_value {};
 		struct GetTEVal : public LLSelectedTEGetFunctor<DataType>
 		{
 			GetTEVal(DataType default_value) : _default(default_value) {}
@@ -621,4 +621,3 @@ public:
 };
 
 #endif
-
diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h
index bd34e40642..9f7be28277 100644
--- a/indra/newview/lltoastalertpanel.h
+++ b/indra/newview/lltoastalertpanel.h
@@ -82,14 +82,10 @@ private:
 
 	struct ButtonData
 	{
-		ButtonData()
-		: mWidth(0)
-		{}
-		
-		LLButton* mButton;
+		LLButton* mButton = nullptr;
 		std::string mURL;
-		U32 mURLExternal;
-		S32 mWidth;
+		U32 mURLExternal = 0;
+		S32 mWidth = 0;
 	};
 	std::vector<ButtonData> mButtonData;
 
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 6ac94fe4c4..c1f4f858c1 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -67,6 +67,11 @@
 #include "lluiusage.h"
 #include "lltranslate.h"
 
+#if LL_LINUX
+#pragma GCC diagnostic ignored "-Wunused-value" // Happens due to LL_DEBUGS("LogViewerStatsPacket"); Does that even do anything?
+#endif
+
+
 // "Minimal Vulkan" to get max API Version
 
 // Calls
@@ -827,6 +832,8 @@ void send_viewer_stats(bool include_preferences)
 
 
 	LL_INFOS("LogViewerStatsPacket") << "Sending viewer statistics: " << body << LL_ENDL;
+
+    // <ND> Do those lines even do anything sane in regard of debug logging?
 	LL_DEBUGS("LogViewerStatsPacket");
 	std::string filename("viewer_stats_packet.xml");
 	llofstream of(filename.c_str());
diff --git a/indra/newview/llviewerstatsrecorder.cpp b/indra/newview/llviewerstatsrecorder.cpp
index 6372679a07..aa55c9791e 100644
--- a/indra/newview/llviewerstatsrecorder.cpp
+++ b/indra/newview/llviewerstatsrecorder.cpp
@@ -154,26 +154,26 @@ void LLViewerStatsRecorder::recordCacheFullUpdate(LLViewerRegion::eCacheUpdateRe
 void LLViewerStatsRecorder::writeToLog( F32 interval )
 {
     if (!mEnableStatsLogging || !mEnableStatsRecording)
-	{
-		return;
-	}
+    {
+        return;
+    }
 
-	size_t data_size = 0;
-	F64 delta_time = LLFrameTimer::getTotalSeconds() - mLastSnapshotTime;
+    size_t data_size = 0;
+    F64 delta_time = LLFrameTimer::getTotalSeconds() - mLastSnapshotTime;
     if (delta_time < interval)
         return;
 
-	if (mSkipSaveIfZeros)
-	{
+    if (mSkipSaveIfZeros)
+    {
         S32 total_events = mObjectCacheHitCount + mObjectCacheMissCrcCount + mObjectCacheMissFullCount + mObjectFullUpdates +
                             mObjectTerseUpdates + mObjectCacheMissRequests + mObjectCacheUpdateDupes +
                             mObjectCacheUpdateChanges + mObjectCacheUpdateAdds + mObjectCacheUpdateReplacements + mObjectUpdateFailures;
-		if (total_events == 0)
-		{
+        if (total_events == 0)
+        {
             LL_DEBUGS("ILXZeroData") << "ILX: not saving zero data" << LL_ENDL;
             return;
         }
-	}
+    }
 
 	mLastSnapshotTime = LLFrameTimer::getTotalSeconds();
     LL_DEBUGS("ILX") << "ILX: "
@@ -317,5 +317,3 @@ F32 LLViewerStatsRecorder::getTimeSinceStart()
 {
 	return (F32) (LLFrameTimer::getTotalSeconds() - mFileOpenTime);
 }
-
-
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index bda8c35702..b422de8f9c 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -5995,7 +5995,7 @@ LLVivoxVoiceClient::sessionState::~sessionState()
     if (mMyIterator != mSession.end())
         mSession.erase(mMyIterator);
 
-	removeAllParticipants();
+    removeAllParticipants();
 }
 
 bool LLVivoxVoiceClient::sessionState::isCallBackPossible()
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 716a65dbcf..e5067132fd 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -5765,8 +5765,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
                     {
                         type = LLDrawPool::POOL_GLTF_PBR;
                     }
-                    else
-					if (type != LLDrawPool::POOL_ALPHA && force_simple)
+                    else if (type != LLDrawPool::POOL_ALPHA && force_simple)
 					{
 						type = LLDrawPool::POOL_SIMPLE;
 					}
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index ba7e8d7298..c3835bd60e 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -384,7 +384,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip, const
 	mCertStore = gSavedSettings.getString("CertStore");
 
 	httpOpts->setSSLVerifyPeer( vefifySSLCert );
-	httpOpts->setSSLVerifyHost( vefifySSLCert ? 2 : 0);
+	httpOpts->setSSLVerifyHost( vefifySSLCert );
 
 	// LLRefCounted starts with a 1 ref, so don't add a ref in the smart pointer
 	httpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders());
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index c7f32d0da9..3de57c6bf4 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -1202,6 +1202,9 @@ class LinuxManifest(ViewerManifest):
         super(LinuxManifest, self).construct()
 
         pkgdir = os.path.join(self.args['build'], os.pardir, 'packages')
+        if "package_dir" in self.args:
+            pkgdir = self.args['package_dir']
+        
         relpkgdir = os.path.join(pkgdir, "lib", "release")
         debpkgdir = os.path.join(pkgdir, "lib", "debug")
 
@@ -1220,44 +1223,121 @@ class LinuxManifest(ViewerManifest):
 
         with self.prefix(dst="bin"):
             self.path("secondlife-bin","do-not-directly-run-secondlife-bin")
-            self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin")
+            #self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin")
             self.path2basename("../llplugin/slplugin", "SLPlugin")
             #this copies over the python wrapper script, associated utilities and required libraries, see SL-321, SL-322 and SL-323
-            with self.prefix(src="../viewer_components/manager", dst=""):
-                self.path("*.py")
+            #with self.prefix(src="../viewer_components/manager", dst=""):
+            #    self.path("*.py")
 
         # recurses, packaged again
         self.path("res-sdl")
 
+        # We  copy ll_icon.BMP in CMakeLists.txt to newview/res-sdl and this will let the above self.path step take  care of copying
+        # the correct branded icon
         # Get the icons based on the channel type
         icon_path = self.icon_path()
-        print("DEBUG: icon_path '%s'" % icon_path)
+        #print("DEBUG: icon_path '%s'" % icon_path)
         with self.prefix(src=icon_path) :
             self.path("secondlife_256.png","secondlife_icon.png")
             with self.prefix(dst="res-sdl") :
                 self.path("secondlife_256.BMP","ll_icon.BMP")
 
         # plugins
-        with self.prefix(src="../media_plugins", dst="bin/llplugin"):
-            self.path("gstreamer010/libmedia_plugin_gstreamer010.so",
-                      "libmedia_plugin_gstreamer.so")
-            self.path2basename("libvlc", "libmedia_plugin_libvlc.so")
-
-        with self.prefix(src=os.path.join(pkgdir, 'lib', 'vlc', 'plugins'), dst="bin/llplugin/vlc/plugins"):
-            self.path( "plugins.dat" )
-            self.path( "*/*.so" )
+        #with self.prefix(src=os.path.join(self.args['build'], os.pardir, 'media_plugins'), dst="bin/llplugin"):
+        #    self.path("gstreamer10/libmedia_plugin_gstreamer10.so", "libmedia_plugin_gstreamer.so")
 
-        with self.prefix(src=os.path.join(pkgdir, 'lib' ), dst="lib"):
-            self.path( "libvlc*.so*" )
 
-        # llcommon
-        if not self.path("../llcommon/libllcommon.so", "lib/libllcommon.so"):
-            print("Skipping llcommon.so (assuming llcommon was linked statically)")
+        """
+        Once we got CEF enable this
+        with self.prefix(src=os.path.join(self.args['build'], os.pardir, 'media_plugins'), dst="bin/llplugin"):
+            self.path("cef/libmedia_plugin_cef.so", "libmedia_plugin_cef.so" )
+        with self.prefix(src=os.path.join(pkgdir, 'lib', 'release'), dst="lib"):
+            self.path( "libcef.so" )
+        with self.prefix(src=os.path.join(pkgdir, 'lib', 'release', 'swiftshader'), dst=os.path.join("bin", "swiftshader") ):
+            self.path( "*.so" )
+        with self.prefix(src=os.path.join(pkgdir, 'lib', 'release', 'swiftshader'), dst=os.path.join("lib", "swiftshader") ):
+            self.path( "*.so" )
+
+        with self.prefix(src=os.path.join(pkgdir, 'bin', 'release'), dst="bin"):
+            self.path( "chrome-sandbox" )
+            self.path( "dullahan_host" )
+            self.path( "snapshot_blob.bin" )
+            self.path( "v8_context_snapshot.bin" )
+        with self.prefix(src=os.path.join(pkgdir, 'bin', 'release'), dst="lib"):
+            self.path( "snapshot_blob.bin" )
+            self.path( "v8_context_snapshot.bin" )
+
+        with self.prefix(src=os.path.join(pkgdir, 'resources'), dst="bin"):
+            self.path( "chrome_100_percent.pak" )
+            self.path( "chrome_200_percent.pak" )
+            self.path( "resources.pak" )
+            self.path( "icudtl.dat" )
+        with self.prefix(src=os.path.join(pkgdir, 'resources'), dst="lib"):
+            self.path( "chrome_100_percent.pak" )
+            self.path( "chrome_200_percent.pak" )
+            self.path( "resources.pak" )
+            self.path( "icudtl.dat" )
+
+        with self.prefix(src=os.path.join(pkgdir, 'resources', 'locales'), dst=os.path.join('bin', 'locales')):
+            self.path("am.pak")
+            self.path("ar.pak")
+            self.path("bg.pak")
+            self.path("bn.pak")
+            self.path("ca.pak")
+            self.path("cs.pak")
+            self.path("da.pak")
+            self.path("de.pak")
+            self.path("el.pak")
+            self.path("en-GB.pak")
+            self.path("en-US.pak")
+            self.path("es-419.pak")
+            self.path("es.pak")
+            self.path("et.pak")
+            self.path("fa.pak")
+            self.path("fi.pak")
+            self.path("fil.pak")
+            self.path("fr.pak")
+            self.path("gu.pak")
+            self.path("he.pak")
+            self.path("hi.pak")
+            self.path("hr.pak")
+            self.path("hu.pak")
+            self.path("id.pak")
+            self.path("it.pak")
+            self.path("ja.pak")
+            self.path("kn.pak")
+            self.path("ko.pak")
+            self.path("lt.pak")
+            self.path("lv.pak")
+            self.path("ml.pak")
+            self.path("mr.pak")
+            self.path("ms.pak")
+            self.path("nb.pak")
+            self.path("nl.pak")
+            self.path("pl.pak")
+            self.path("pt-BR.pak")
+            self.path("pt-PT.pak")
+            self.path("ro.pak")
+            self.path("ru.pak")
+            self.path("sk.pak")
+            self.path("sl.pak")
+            self.path("sr.pak")
+            self.path("sv.pak")
+            self.path("sw.pak")
+            self.path("ta.pak")
+            self.path("te.pak")
+            self.path("th.pak")
+            self.path("tr.pak")
+            self.path("uk.pak")
+            self.path("vi.pak")
+            self.path("zh-CN.pak")
+            self.path("zh-TW.pak")
+        """
 
         self.path("featuretable_linux.txt")
         self.path("cube.dae")
 
-        with self.prefix(src=pkgdir):
+        with self.prefix(src=pkgdir, dst="bin"):
             self.path("ca-bundle.crt")
 
     def package_finish(self):
@@ -1294,76 +1374,53 @@ class LinuxManifest(ViewerManifest):
             self.run_command(["mv", tempname, realname])
 
     def strip_binaries(self):
+        doStrip = False
         if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer():
-            print("* Going strip-crazy on the packaged binaries, since this is a RELEASE build")
+            doStrip = True
+        # In case of flatpak flatpak-build will call strip, disable doStrip here to get a flatpak symbol package. Increases flatpak size by about 1G
+        if "FLATPAK_DEST" in os.environ:
+            doStrip = True
+
+        if doStrip:
+            print("* Going strip-crazy on the packaged binaries, since this is a Release build")
             # makes some small assumptions about our packaged dir structure
             self.run_command(
                 ["find"] +
                 [os.path.join(self.get_dst_prefix(), dir) for dir in ('bin', 'lib')] +
                 ['-type', 'f', '!', '-name', '*.py',
+                 '!', '-name', '*.pak',
+                 '!', '-name', '*.bin',
+                 '!', '-name', '*.dat',
+                 '!', '-name', '*.crt',
+                 '!', '-name', '*.dll',
+                 '!', '-name', '*.lib',
                  '!', '-name', 'update_install', '-exec', 'strip', '-S', '{}', ';'])
 
-class Linux_i686_Manifest(LinuxManifest):
-    address_size = 32
+class Linux_x86_64_Manifest(LinuxManifest):
+    address_size = 64
 
     def construct(self):
-        super(Linux_i686_Manifest, self).construct()
+        super(Linux_x86_64_Manifest, self).construct()
 
         pkgdir = os.path.join(self.args['build'], os.pardir, 'packages')
+        if "package_dir" in self.args:
+            pkgdir = self.args['package_dir']
+
         relpkgdir = os.path.join(pkgdir, "lib", "release")
         debpkgdir = os.path.join(pkgdir, "lib", "debug")
 
         with self.prefix(src=relpkgdir, dst="lib"):
-            self.path("libapr-1.so")
-            self.path("libapr-1.so.0")
-            self.path("libapr-1.so.0.4.5")
-            self.path("libaprutil-1.so")
-            self.path("libaprutil-1.so.0")
-            self.path("libaprutil-1.so.0.4.1")
-            self.path("libdb*.so")
+            self.path("libapr-1.so*")
+            self.path("libaprutil-1.so*")
             self.path("libexpat.so.*")
-            self.path("libuuid.so*")
-            self.path("libSDL-1.2.so.*")
-            self.path("libdirectfb-1.*.so.*")
-            self.path("libfusion-1.*.so.*")
-            self.path("libdirect-1.*.so.*")
-            self.path("libopenjp2.so*")
-            self.path("libdirectfb-1.4.so.5")
-            self.path("libfusion-1.4.so.5")
-            self.path("libdirect-1.4.so.5*")
-            self.path("libhunspell-1.3.so*")
-            self.path("libalut.so*")
-            self.path("libopenal.so*")
-            self.path("libopenal.so", "libvivoxoal.so.1") # vivox's sdk expects this soname
-            # KLUDGE: As of 2012-04-11, the 'fontconfig' package installs
-            # libfontconfig.so.1.4.4, along with symlinks libfontconfig.so.1
-            # and libfontconfig.so. Before we added support for library-file
-            # wildcards, though, this self.path() call specifically named
-            # libfontconfig.so.1.4.4 WITHOUT also copying the symlinks. When I
-            # (nat) changed the call to self.path("libfontconfig.so.*"), we
-            # ended up with the libfontconfig.so.1 symlink in the target
-            # directory as well. But guess what! At least on Ubuntu 10.04,
-            # certain viewer fonts look terrible with libfontconfig.so.1
-            # present in the target directory. Removing that symlink suffices
-            # to improve them. I suspect that means we actually do better when
-            # the viewer fails to find our packaged libfontconfig.so*, falling
-            # back on the system one instead -- but diagnosing and fixing that
-            # is a bit out of scope for the present project. Meanwhile, this
-            # particular wildcard specification gets us exactly what the
-            # previous call did, without having to explicitly state the
-            # version number.
-            self.path("libfontconfig.so.*.*")
-
-            # Include libfreetype.so. but have it work as libfontconfig does.
-            self.path("libfreetype.so.*.*")
+            self.path_optional("libSDL*.so.*")
 
-            try:
-                self.path("libtcmalloc.so*") #formerly called google perf tools
-                pass
-            except:
-                print("tcmalloc files not found, skipping")
-                pass
+            self.path_optional("libjemalloc*.so")
 
+            self.path("libhunspell-1.3.so*")
+            self.path_optional("libalut.so*")
+            self.path_optional("libopenal.so*")
+            self.path_optional("libopenal.so", "libvivoxoal.so.1") # vivox's sdk expects this soname
             if self.args['fmodstudio'] == 'ON':
                 try:
                     self.path("libfmod.so.11.7")
@@ -1384,17 +1441,6 @@ class Linux_i686_Manifest(LinuxManifest):
             self.path("libvivoxsdk.so")
 
         self.strip_binaries()
-
-
-class Linux_x86_64_Manifest(LinuxManifest):
-    address_size = 64
-
-    def construct(self):
-        super(Linux_x86_64_Manifest, self).construct()
-
-        # support file for valgrind debug tool
-        self.path("secondlife-i686.supp")
-
 ################################################################
 
 if __name__ == "__main__":
-- 
cgit v1.2.3


From e79c32eee89c31e730ac0562d680e6e0ebfd4a68 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 8 Apr 2024 22:41:34 +0300
Subject: triage#163 'Create folder from selected' misbehaves in marketplace

Marketplace deliberately doesn't allow creating folders and the "New
folder from selected" is a way of creating a new folder then moving
selected items inside, therefore shouldn't be allowed.
---
 indra/newview/llinventorybridge.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 0ed89292a5..1783c4c9db 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -852,7 +852,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
 			disabled_items.push_back(std::string("Copy"));
 		}
 
-        if (isAgentInventory() && !single_folder_root)
+        if (isAgentInventory() && !single_folder_root && !isMarketplaceListingsFolder())
         {
             items.push_back(std::string("New folder from selected"));
             items.push_back(std::string("Subfolder Separator"));
-- 
cgit v1.2.3


From bbd6dfc21a1a6c07824fc81e0659a2c200581d3b Mon Sep 17 00:00:00 2001
From: AiraYumi <aira.youme@airanyumi.net>
Date: Tue, 9 Apr 2024 05:38:01 +0900
Subject: Some fixes to linux builds (#1144)

* compile flag cleanup for linux
* rollback indra/llcommon/llprofiler.h
* use 3p fltk package
* fix build gcc 13 (dangling-pointer)
---
 indra/cmake/00-Common.cmake |  2 +-
 indra/cmake/UI.cmake        | 16 +++-------------
 indra/llcommon/llprofiler.h |  5 +----
 3 files changed, 5 insertions(+), 18 deletions(-)

(limited to 'indra')

diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 486071a2df..419ebebe3b 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -198,7 +198,7 @@ if (LINUX OR DARWIN)
   list(APPEND GCC_WARNINGS -Wno-reorder -Wno-non-virtual-dtor )
 
   if(LINUX)
-    list(APPEND GCC_WARNINGS -Wno-maybe-uninitialized -Wno-misleading-indentation -Wno-stringop-truncation -Wno-unused-value )
+    list(APPEND GCC_WARNINGS -Wno-maybe-uninitialized -Wno-dangling-pointer )
   endif()
 
   add_compile_options(${GCC_WARNINGS})
diff --git a/indra/cmake/UI.cmake b/indra/cmake/UI.cmake
index 0eb9af6dcf..0df62808e7 100644
--- a/indra/cmake/UI.cmake
+++ b/indra/cmake/UI.cmake
@@ -6,25 +6,15 @@ include(GLIB)
 add_library( ll::uilibraries INTERFACE IMPORTED )
 
 if (LINUX)
-  target_compile_definitions(ll::uilibraries INTERFACE LL_X11=1 )
+  use_prebuilt_binary(fltk)
+  target_compile_definitions(ll::uilibraries INTERFACE LL_FLTK=1 LL_X11=1 )
 
   if( USE_CONAN )
     return()
   endif()
 
-  find_package(FLTK REQUIRED )
-  find_library(ND_FLTK_STATIC_LIBRARY libfltk.a PATH_SUFFIXES fltk )
-
-  if( NOT ND_FLTK_STATIC_LIBRARY )
-    message(FATAL_ERROR "libfltk.a not found")
-  else()
-    message("libfltk.a found ${ND_FLTK_STATIC_LIBRARY}")
-  endif()
-
-  target_include_directories( ll::uilibraries SYSTEM INTERFACE   ${FLTK_INCLUDE_DIR})
-  target_compile_definitions( ll::uilibraries INTERFACE LL_FLTK=1 )
   target_link_libraries( ll::uilibraries INTERFACE
-          ${ND_FLTK_STATIC_LIBRARY}
+          fltk
           Xrender
           Xcursor
           Xfixes
diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h
index 0297bbe592..af5e5777bf 100644
--- a/indra/llcommon/llprofiler.h
+++ b/indra/llcommon/llprofiler.h
@@ -74,10 +74,6 @@
 #define LL_PROFILER_CONFIGURATION           LL_PROFILER_CONFIG_FAST_TIMER
 #endif
 
-#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER
-    #include "Tracy.hpp"
-#endif
-
 extern thread_local bool gProfilerEnabled;
 
 #if defined(LL_PROFILER_CONFIGURATION) && (LL_PROFILER_CONFIGURATION > LL_PROFILER_CONFIG_NONE)
@@ -88,6 +84,7 @@ extern thread_local bool gProfilerEnabled;
 //      #define TRACY_NO_BROADCAST   1
 //      #define TRACY_ONLY_LOCALHOST 1
         #define TRACY_ONLY_IPV4      1
+        #include "Tracy.hpp"
 
         // Enable OpenGL profiling
         #define LL_PROFILER_ENABLE_TRACY_OPENGL 0
-- 
cgit v1.2.3


From 6b4b33cc129e9482342c9280ae79c9c5ce427ef1 Mon Sep 17 00:00:00 2001
From: Nicky Dasmijn <nicky.dasmijn@posteo.nl>
Date: Mon, 8 Apr 2024 22:39:20 +0200
Subject: Linux GHA builds (#1147)

* Linux GHA builds

Add Ubuntu 22.04 runner and Linux dependencies

Do not even try to touch ReleaseFS for Linux yet (this needs KDU, Havok, FMOD)

* Lets play a game of 'guess the havok source url'

* Move to linux-large runner.

* ReleaseOS used OpenAL, not fmod studio (which otherwise is the default)

* - Correction for Linux build dir
- HAVOK / CrashReporting wrestling. HAVOK is always turned on, even for OS builds Turn this off for Linux-ReleaseOS
Same with crashreporting, we need it off for now

* Add missing brace

* When doing a GHA build pack right into RUNNER_TEMP and then signal the created archive as our "viewer_app"

* Upload Linux-ReleaseOS after build

* - Need to use os.path.join and not hyst join
- set_github_output_path can be called unconditionally

* Remove Linux GHA build example.
---
 indra/newview/viewer_manifest.py | 50 +++++++++++++++++++++++++---------------
 1 file changed, 31 insertions(+), 19 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 3de57c6bf4..c97d421504 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -59,7 +59,7 @@ class ViewerManifest(LLManifest):
         # files during the build (see copy_w_viewer_manifest
         # and copy_l_viewer_manifest targets)
         return 'package' in self.args['actions']
-    
+
     def construct(self):
         super(ViewerManifest, self).construct()
         self.path(src="../../scripts/messages/message_template.msg", dst="app_settings/message_template.msg")
@@ -87,7 +87,7 @@ class ViewerManifest(LLManifest):
 
                 # ... and the entire image filters directory
                 self.path("filters")
-            
+
                 # ... and the included spell checking dictionaries
                 pkgdir = os.path.join(self.args['build'], os.pardir, 'packages')
                 with self.prefix(src=pkgdir):
@@ -260,14 +260,14 @@ class ViewerManifest(LLManifest):
 
     def app_name_oneword(self):
         return ''.join(self.app_name().split())
-    
+
     def icon_path(self):
         return "icons/" + self.channel_type()
 
     def extract_names(self,src):
         """Extract contributor names from source file, returns string"""
         try:
-            with open(src, 'r') as contrib_file: 
+            with open(src, 'r') as contrib_file:
                 lines = contrib_file.readlines()
         except IOError:
             print("Failed to open '%s'" % src)
@@ -491,7 +491,7 @@ class Windows_x86_64_Manifest(ViewerManifest):
                 raise Exception("Directories are not supported by test_CRT_and_copy_action()")
         else:
             print("Doesn't exist:", src)
-        
+
     def construct(self):
         super().construct()
 
@@ -543,7 +543,7 @@ class Windows_x86_64_Manifest(ViewerManifest):
         self.path2basename(os.path.join(os.pardir,
                                         'llplugin', 'slplugin', self.args['configuration']),
                            "slplugin.exe")
-        
+
         # Get shared libs from the shared libs staging directory
         with self.prefix(src=os.path.join(self.args['build'], os.pardir,
                                           'sharedlibs', self.args['buildtype'])):
@@ -582,7 +582,7 @@ class Windows_x86_64_Manifest(ViewerManifest):
             # Vivox libraries
             self.path("vivoxsdk_x64.dll")
             self.path("ortp_x64.dll")
-            
+
             # OpenSSL
             self.path("libcrypto-1_1-x64.dll")
             self.path("libssl-1_1-x64.dll")
@@ -709,7 +709,7 @@ class Windows_x86_64_Manifest(ViewerManifest):
                 self.path("plugins/")
 
         if not self.is_packaging_viewer():
-            self.package_file = "copied_deps"    
+            self.package_file = "copied_deps"
 
     def nsi_file_commands(self, install=True):
         def INSTDIR(path):
@@ -768,7 +768,7 @@ class Windows_x86_64_Manifest(ViewerManifest):
 
         installer_file = self.installer_base_name() + '_Setup.exe'
         substitution_strings['installer_file'] = installer_file
-        
+
         version_vars = """
         !define INSTEXE "SLVersionChecker.exe"
         !define VERSION "%(version_short)s"
@@ -777,7 +777,7 @@ class Windows_x86_64_Manifest(ViewerManifest):
         !define VERSION_REGISTRY "%(version_registry)s"
         !define VIEWER_EXE "%(final_exe)s"
         """ % substitution_strings
-        
+
         if self.channel_type() == 'release':
             substitution_strings['caption'] = CHANNEL_VENDOR_BASE
         else:
@@ -908,7 +908,7 @@ class Darwin_x86_64_Manifest(ViewerManifest):
                 # yields a slightly smaller binary but makes crash
                 # logs mostly useless. This may be desirable for the
                 # final release. Or not.
-                if ("package" in self.args['actions'] or 
+                if ("package" in self.args['actions'] or
                     "unpacked" in self.args['actions']):
                     self.run_command(
                         ['strip', '-S', executable])
@@ -933,7 +933,7 @@ class Darwin_x86_64_Manifest(ViewerManifest):
 
                 with self.prefix(src=relpkgdir, dst=""):
                     self.path("libndofdev.dylib")
-                    self.path("libhunspell-*.dylib")   
+                    self.path("libhunspell-*.dylib")
 
                 with self.prefix(src_dst="cursors_mac"):
                     self.path("*.tif")
@@ -1204,7 +1204,7 @@ class LinuxManifest(ViewerManifest):
         pkgdir = os.path.join(self.args['build'], os.pardir, 'packages')
         if "package_dir" in self.args:
             pkgdir = self.args['package_dir']
-        
+
         relpkgdir = os.path.join(pkgdir, "lib", "release")
         debpkgdir = os.path.join(pkgdir, "lib", "debug")
 
@@ -1343,6 +1343,9 @@ class LinuxManifest(ViewerManifest):
     def package_finish(self):
         installer_name = self.installer_base_name()
 
+        # When running as a GitHub Action job, RUNNER_TEMP is defined as the tmp dir
+        RUNNER_TEMP = os.getenv('RUNNER_TEMP')
+
         self.strip_binaries()
 
         # Fix access permissions
@@ -1357,21 +1360,30 @@ class LinuxManifest(ViewerManifest):
         # temporarily move directory tree so that it has the right
         # name in the tarfile
         realname = self.get_dst_prefix()
-        tempname = self.build_path_of(installer_name)
-        self.run_command(["mv", realname, tempname])
+        versionedName = self.build_path_of(installer_name)
+
+        tarName = versionedName + ".tar.bz2"
+
+        # If using a github runner we divert packaging a little. Considering this wil be a VM/docker image
+        # we can just pack the final installer into RUNNER_TEMP and not into the usual stop we'd pick when
+        # not building a GHA release
+        if RUNNER_TEMP:
+            tarName = os.path.join(RUNNER_TEMP, self.package_file)
+
+        self.run_command(["mv", realname, versionedName])
+
         try:
             # only create tarball if it's a release build.
             if self.args['buildtype'].lower() == 'release':
-                # --numeric-owner hides the username of the builder for
-                # security etc.
                 self.run_command(['tar', '-C', self.get_build_prefix(),
                                   '--numeric-owner', '-cjf',
-                                 tempname + '.tar.bz2', installer_name])
+                                 tarName, installer_name])
+                self.set_github_output_path('viewer_app', tarName)
             else:
                 print("Skipping %s.tar.bz2 for non-Release build (%s)" % \
                       (installer_name, self.args['buildtype']))
         finally:
-            self.run_command(["mv", tempname, realname])
+            self.run_command(["mv", versionedName, realname])
 
     def strip_binaries(self):
         doStrip = False
-- 
cgit v1.2.3


From 37392be4171303db08a4842b7882b4cb758a8f8d Mon Sep 17 00:00:00 2001
From: Nicky Dasmijn <nicky.dasmijn@posteo.nl>
Date: Tue, 9 Apr 2024 20:26:06 +0200
Subject: Update Linux media handling (#1146)

* Enable CEF browser for Linux

* Disable the update for Linux, we don't have that one right now

* Update build_linux.yaml

We need  libpulse-dev for volume_catcher Linux

* Add linux_volum_catcher* files

* Enable OpenAL for Linux-ReleaseOS

* Linux: Update OpenAL

* Update SDL2

* Add libsndio-dev to the dependencies.

* Update CEF to an official LL version

* Remove dupe of emoji_shortcodes

* Reording autobuild does because it can and wants to

* Linux: Disable NDOF for the time being. After updating the ndof 3P needs to be rebuilt and we do not have a fresh one from LL yet.
Forcefully undefine LIB_NDOF, it gets defined in the build variables no matter if it is safe to define.

* Remove wrestling with mutliarch and LIBGL_DRIVERS_PATH

* Remove tcmalloc snippet, tcmalloc is a very faint bad dream of the past

* Putting out a warning this viewer ran on a x64 arch and then suggesting to install 32 bit compat packages makes no sense at all

* CEF resources need to be in lib

* It;'s okay to warn about missing plugins

* Linux: CEF keyboard handling

* Remove old gstreamer 0.10 implementation

* Linux DSO loading always had been very peculiar due to macro magic.
At least now it is peculiar shared magic with only one implementation.

* Remove -fPIC. We get that one from LL_BUILD

* /proc/cpuinfo is not reliable to detrmine the max CPU clock. Try to determine this by reading "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq".

Only if this fails go back to /proc/cpuinfo

* Cleanup

* Cleanup common linker and compiler flags, make it more obvious which flags are for which OS/compiler

* Switch to correct plugin file

* Install libpulse-dev for volume catcher.

* And the runner needs libsndio-dev as well.

* check for runner.os=='linux'. matrix.os is the full name of the image (limux-large).
---
 indra/cmake/00-Common.cmake                        |   38 +-
 indra/cmake/CEFPlugin.cmake                        |    5 +
 indra/cmake/LLWindow.cmake                         |    2 +-
 indra/cmake/NDOF.cmake                             |    4 +-
 indra/llcommon/llprocessor.cpp                     |   83 +-
 indra/llplugin/CMakeLists.txt                      |    8 -
 indra/media_plugins/CMakeLists.txt                 |    3 +-
 indra/media_plugins/base/CMakeLists.txt            |    7 -
 indra/media_plugins/base/media_plugin_base.cpp     |   50 +
 indra/media_plugins/base/media_plugin_base.h       |   29 +-
 indra/media_plugins/cef/CMakeLists.txt             |   28 +-
 indra/media_plugins/cef/linux_volume_catcher.cpp   |  424 +++++++
 .../cef/linux_volume_catcher_pa_syms.inc           |   21 +
 .../cef/linux_volume_catcher_paglib_syms.inc       |    6 +
 indra/media_plugins/cef/media_plugin_cef.cpp       |   34 +-
 indra/media_plugins/example/CMakeLists.txt         |    8 -
 indra/media_plugins/gstreamer010/CMakeLists.txt    |   46 -
 .../gstreamer010/llmediaimplgstreamer.h            |   53 -
 .../gstreamer010/llmediaimplgstreamer_syms.cpp     |  167 ---
 .../gstreamer010/llmediaimplgstreamer_syms.h       |   74 --
 .../gstreamer010/llmediaimplgstreamer_syms_raw.inc |   51 -
 .../llmediaimplgstreamer_syms_rawv.inc             |    5 -
 .../llmediaimplgstreamertriviallogging.h           |   55 -
 .../gstreamer010/llmediaimplgstreamervidplug.cpp   |  526 --------
 .../gstreamer010/llmediaimplgstreamervidplug.h     |  105 --
 .../gstreamer010/media_plugin_gstreamer010.cpp     | 1266 --------------------
 indra/media_plugins/gstreamer10/CMakeLists.txt     |    5 -
 .../gstreamer10/llmediaimplgstreamer_syms.cpp      |  197 ---
 .../gstreamer10/llmediaimplgstreamer_syms.h        |   68 --
 .../gstreamer10/llmediaimplgstreamer_syms_raw.inc  |  119 +-
 .../gstreamer10/media_plugin_gstreamer10.cpp       |   86 +-
 indra/media_plugins/libvlc/CMakeLists.txt          |    7 -
 indra/newview/CMakeLists.txt                       |    1 -
 indra/newview/linux_tools/wrapper.sh               |   42 -
 indra/newview/llappviewer.cpp                      |    3 +-
 indra/newview/llviewermedia.cpp                    |    4 -
 .../skins/default/xui/en/mime_types_linux.xml      |   70 +-
 indra/newview/viewer_manifest.py                   |   24 +-
 38 files changed, 796 insertions(+), 2928 deletions(-)
 create mode 100755 indra/media_plugins/cef/linux_volume_catcher.cpp
 create mode 100755 indra/media_plugins/cef/linux_volume_catcher_pa_syms.inc
 create mode 100755 indra/media_plugins/cef/linux_volume_catcher_paglib_syms.inc
 delete mode 100644 indra/media_plugins/gstreamer010/CMakeLists.txt
 delete mode 100644 indra/media_plugins/gstreamer010/llmediaimplgstreamer.h
 delete mode 100644 indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp
 delete mode 100644 indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h
 delete mode 100644 indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc
 delete mode 100644 indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc
 delete mode 100644 indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h
 delete mode 100644 indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
 delete mode 100644 indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
 delete mode 100644 indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
 delete mode 100644 indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms.cpp
 delete mode 100644 indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms.h

(limited to 'indra')

diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 419ebebe3b..d46ebc4960 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -105,7 +105,6 @@ if (WINDOWS)
   endif()
 endif (WINDOWS)
 
-
 if (LINUX)
   set( CMAKE_BUILD_WITH_INSTALL_RPATH TRUE )
   set( CMAKE_INSTALL_RPATH $ORIGIN $ORIGIN/../lib )
@@ -117,18 +116,14 @@ if (LINUX)
     set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_EXE} )
   endif()
 
-   # EXTERNAL_TOS
-   # force this platform to accept TOS via external browser
-
-   # LL_IGNORE_SIGCHLD
-   # don't catch SIGCHLD in our base application class for the viewer - some of
-   # our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The
-   # viewer doesn't need to catch SIGCHLD anyway.
+  # LL_IGNORE_SIGCHLD
+  # don't catch SIGCHLD in our base application class for the viewer - some of
+  # our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The
+  # viewer doesn't need to catch SIGCHLD anyway.
 
   add_compile_definitions(
           _REENTRANT
           _FORTIFY_SOURCE=2
-          EXTERNAL_TOS
           APPID=secondlife
           LL_IGNORE_SIGCHLD
   )
@@ -146,22 +141,27 @@ if (LINUX)
           -Wno-pessimizing-move
           -Wno-stringop-overflow
           -Wno-stringop-truncation
+          -Wno-dangling-pointer
           -fvisibility=hidden
   )
   add_link_options(
-    -Wl,--no-keep-memory
-    -Wl,--build-id
+          -Wl,--no-keep-memory
+          -Wl,--build-id
+          -Wl,--no-undefined
   )
+  if (NOT GCC_DISABLE_FATAL_WARNINGS)
+    list(APPEND GCC_WARNINGS -Werror)
+  endif (NOT GCC_DISABLE_FATAL_WARNINGS)
 
   # this stops us requiring a really recent glibc at runtime
   add_compile_options(-fno-stack-protector)
-  # linking can be very memory-hungry, especially the final viewer link
-  set(CMAKE_CXX_LINK_FLAGS "-Wl,--no-keep-memory")
-  set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG}")
 
   # ND: clang is a bit more picky than GCC, the latter seems to auto include -lstdc++ and -lm. The former not so and thus fails to link
   if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
-    set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -lstdc++ -lm")
+    add_link_options(
+            -lstdc++
+            -lm
+    )
   endif()
 endif (LINUX)
 
@@ -186,15 +186,9 @@ if (DARWIN)
   # required for clang-15/xcode-15 since our boost package still uses deprecated std::unary_function/binary_function
   # see https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#C++-Standard-Library
   add_compile_definitions(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION)
-endif (DARWIN)
 
-if (LINUX OR DARWIN)
   set(GCC_WARNINGS -Wall -Wno-sign-compare -Wno-trigraphs)
 
-  if (NOT GCC_DISABLE_FATAL_WARNINGS)
-    list(APPEND GCC_WARNINGS -Werror)
-  endif (NOT GCC_DISABLE_FATAL_WARNINGS)
-
   list(APPEND GCC_WARNINGS -Wno-reorder -Wno-non-virtual-dtor )
 
   if(LINUX)
@@ -203,4 +197,4 @@ if (LINUX OR DARWIN)
 
   add_compile_options(${GCC_WARNINGS})
   add_compile_options(-m${ADDRESS_SIZE})
-endif (LINUX OR DARWIN)
+endif ()
diff --git a/indra/cmake/CEFPlugin.cmake b/indra/cmake/CEFPlugin.cmake
index 9b77becf29..555d2aebbf 100644
--- a/indra/cmake/CEFPlugin.cmake
+++ b/indra/cmake/CEFPlugin.cmake
@@ -33,4 +33,9 @@ elseif (DARWIN)
        )
 
 elseif (LINUX)
+    target_link_libraries( ll::cef INTERFACE
+            libdullahan.a
+            cef
+            cef_dll_wrapper.a
+    )
 endif (WINDOWS)
diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake
index 23f4115aeb..6c7b70461f 100644
--- a/indra/cmake/LLWindow.cmake
+++ b/indra/cmake/LLWindow.cmake
@@ -16,5 +16,5 @@ if (LINUX)
   #target_link_libraries( ll::SDL INTERFACE SDL2::SDL2 SDL2::SDL2main X11)
 
   use_prebuilt_binary(SDL2)
-  target_link_libraries( ll::SDL INTERFACE SDL2 X11)
+  target_link_libraries( ll::SDL INTERFACE SDL2 sndio X11)
 endif (LINUX)
diff --git a/indra/cmake/NDOF.cmake b/indra/cmake/NDOF.cmake
index b88fbccf2a..db9c8b1780 100644
--- a/indra/cmake/NDOF.cmake
+++ b/indra/cmake/NDOF.cmake
@@ -19,6 +19,6 @@ if (NDOF)
     target_link_libraries( ll::ndof INTERFACE ndofdev)
   endif (WINDOWS)
   target_compile_definitions( ll::ndof INTERFACE LIB_NDOF=1)
+else()
+  add_compile_options(-ULIB_NDOF)
 endif (NDOF)
-
-
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index ce3b1160c0..4cdc3d7519 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -793,19 +793,55 @@ private:
 };
 
 #elif LL_LINUX
+
+// *NOTE:Mani - eww, macros! srry.
+#define LLPI_SET_INFO_STRING(llpi_id, cpuinfo_id) \
+		if (!cpuinfo[cpuinfo_id].empty()) \
+		{ setInfo(llpi_id, cpuinfo[cpuinfo_id]);}
+
+#define LLPI_SET_INFO_INT(llpi_id, cpuinfo_id) \
+		{\
+			S32 result; \
+			if (!cpuinfo[cpuinfo_id].empty() \
+				&& LLStringUtil::convertToS32(cpuinfo[cpuinfo_id], result))	\
+		    { setInfo(llpi_id, result);} \
+		}
+
 const char CPUINFO_FILE[] = "/proc/cpuinfo";
 
-class LLProcessorInfoLinuxImpl : public LLProcessorInfoImpl
-{
+class LLProcessorInfoLinuxImpl : public LLProcessorInfoImpl {
 public:
-	LLProcessorInfoLinuxImpl() 
-	{
-		get_proc_cpuinfo();
-	}
+    LLProcessorInfoLinuxImpl() {
+        get_proc_cpuinfo();
+    }
+
+    virtual ~LLProcessorInfoLinuxImpl() {}
 
-	virtual ~LLProcessorInfoLinuxImpl() {}
 private:
 
+    F64 getCPUMaxMHZ()
+    {
+        // Nicky: We just look into cpu0. In theory we could iterate over all cores
+        // "/sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_max_freq"
+        // But those should not fluctuate that much?
+        std::ifstream fIn { "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq" };
+
+        if( !fIn.is_open() )
+            return 0.0;
+
+        std::string strLine;
+        fIn >> strLine;
+        if( strLine.empty() )
+            return 0.0l;
+
+        F64 mhz {};
+        if( !LLStringUtil::convertToF64(strLine, mhz ) )
+            return 0.0;
+
+        mhz = mhz / 1000.0;
+        return mhz;
+    }
+
 	void get_proc_cpuinfo()
 	{
 		std::map< std::string, std::string > cpuinfo;
@@ -834,31 +870,24 @@ private:
 				std::string llinename(linename);
 				LLStringUtil::toLower(llinename);
 				std::string lineval( spacespot + 1, nlspot );
-				cpuinfo[ llinename ] = lineval;
+                    cpuinfo[ llinename ] = lineval;
 			}
 			fclose(cpuinfo_fp);
 		}
 # if LL_X86
 
-// *NOTE:Mani - eww, macros! srry.
-#define LLPI_SET_INFO_STRING(llpi_id, cpuinfo_id) \
-		if (!cpuinfo[cpuinfo_id].empty()) \
-		{ setInfo(llpi_id, cpuinfo[cpuinfo_id]);}
-
-#define LLPI_SET_INFO_INT(llpi_id, cpuinfo_id) \
-		{\
-			S32 result; \
-			if (!cpuinfo[cpuinfo_id].empty() \
-				&& LLStringUtil::convertToS32(cpuinfo[cpuinfo_id], result))	\
-		    { setInfo(llpi_id, result);} \
-		}
-		
-		F64 mhz;
-		if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz)
-			&& 200.0 < mhz && mhz < 10000.0)
-		{
-		    setInfo(eFrequency,(F64)(mhz));
-		}
+        F64 mhzFromSys = getCPUMaxMHZ();
+        F64 mhzFromProc {};
+        if( !LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhzFromProc ) )
+            mhzFromProc = 0.0;
+        if (mhzFromSys > 1.0 && mhzFromSys > mhzFromProc )
+        {
+            setInfo( eFrequency, mhzFromSys );
+        }
+        else if (  200.0 < mhzFromProc && mhzFromProc < 10000.0)
+        {
+            setInfo(eFrequency,(F64)(mhzFromProc));
+        }
 
 		LLPI_SET_INFO_STRING(eBrandName, "model name");		
 		LLPI_SET_INFO_STRING(eVendor, "vendor_id");
diff --git a/indra/llplugin/CMakeLists.txt b/indra/llplugin/CMakeLists.txt
index 14a69afe6e..005426acde 100644
--- a/indra/llplugin/CMakeLists.txt
+++ b/indra/llplugin/CMakeLists.txt
@@ -31,14 +31,6 @@ set(llplugin_HEADER_FILES
     llpluginsharedmemory.h
     )
 
-if(NOT ADDRESS_SIZE EQUAL 32)
-  if(WINDOWS)
-    ##add_definitions(/FIXED:NO)
-  else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
-    add_definitions(-fPIC)
-  endif(WINDOWS)
-endif(NOT ADDRESS_SIZE EQUAL 32)
-
 list(APPEND llplugin_SOURCE_FILES ${llplugin_HEADER_FILES})
 
 add_library (llplugin ${llplugin_SOURCE_FILES})
diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt
index fe8fee5e7e..86c46cb476 100644
--- a/indra/media_plugins/CMakeLists.txt
+++ b/indra/media_plugins/CMakeLists.txt
@@ -3,8 +3,9 @@
 add_subdirectory(base)
 
 if (LINUX)
-    add_subdirectory(gstreamer10)
+    add_subdirectory(cef)
     add_subdirectory(example)
+    add_subdirectory(gstreamer10)
 endif (LINUX)
 
 if (DARWIN)
diff --git a/indra/media_plugins/base/CMakeLists.txt b/indra/media_plugins/base/CMakeLists.txt
index 64b6a4228d..5e635c6ca3 100644
--- a/indra/media_plugins/base/CMakeLists.txt
+++ b/indra/media_plugins/base/CMakeLists.txt
@@ -12,13 +12,6 @@ include(PluginAPI)
 
 ### media_plugin_base
 
-if(NOT ADDRESS_SIZE EQUAL 32)
-  if(WINDOWS)
-    ##add_definitions(/FIXED:NO)
-  else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
-    add_definitions(-fPIC)
-  endif(WINDOWS)
-endif(NOT ADDRESS_SIZE EQUAL 32)
 
 set(media_plugin_base_SOURCE_FILES
     media_plugin_base.cpp
diff --git a/indra/media_plugins/base/media_plugin_base.cpp b/indra/media_plugins/base/media_plugin_base.cpp
index 37c498664a..dbbc973f00 100644
--- a/indra/media_plugins/base/media_plugin_base.cpp
+++ b/indra/media_plugins/base/media_plugin_base.cpp
@@ -167,6 +167,56 @@ void MediaPluginBase::sendStatus()
 	sendMessage(message);
 }
 
+#if LL_LINUX
+
+size_t SymbolGrabber::registerSymbol( SymbolToGrab aSymbol )
+{
+    gSymbolsToGrab.emplace_back(aSymbol);
+    return gSymbolsToGrab.size();
+}
+
+bool SymbolGrabber::grabSymbols(std::vector< std::string > const &aDSONames)
+{
+    std::cerr << "SYMBOLS: " << gSymbolsToGrab.size() << std::endl;
+
+    if (sSymsGrabbed)
+        return true;
+
+    //attempt to load the shared libraries
+    apr_pool_create(&sSymPADSOMemoryPool, nullptr);
+
+    for( std::vector< std::string >::const_iterator itr = aDSONames.begin(); itr != aDSONames.end(); ++itr )
+    {
+        apr_dso_handle_t *pDSO(NULL);
+        std::string strDSO{ *itr };
+        if( APR_SUCCESS == apr_dso_load( &pDSO, strDSO.c_str(), sSymPADSOMemoryPool ))
+            sLoadedLibraries.push_back( pDSO );
+
+        for( auto i = 0; i < gSymbolsToGrab.size(); ++i )
+        {
+            if( !*gSymbolsToGrab[i].mPPFunc )
+                apr_dso_sym( gSymbolsToGrab[i].mPPFunc, pDSO, gSymbolsToGrab[i].mName );
+        }
+    }
+
+    bool sym_error = false;
+
+    for( auto i = 0; i < gSymbolsToGrab.size(); ++i )
+    {
+        if( gSymbolsToGrab[ i ].mRequired && ! *gSymbolsToGrab[ i ].mPPFunc )
+            sym_error = true;
+    }
+
+    sSymsGrabbed = !sym_error;
+    return sSymsGrabbed;
+}
+
+void SymbolGrabber::ungrabSymbols()
+{
+
+}
+#endif
+
 
 #if LL_WINDOWS
 # define LLSYMEXPORT __declspec(dllexport)
diff --git a/indra/media_plugins/base/media_plugin_base.h b/indra/media_plugins/base/media_plugin_base.h
index 38b8226bb3..2e975a5bf2 100644
--- a/indra/media_plugins/base/media_plugin_base.h
+++ b/indra/media_plugins/base/media_plugin_base.h
@@ -32,6 +32,34 @@
 #include "llpluginmessage.h"
 #include "llpluginmessageclasses.h"
 
+#if LL_LINUX
+
+struct SymbolToGrab
+{
+    bool mRequired;
+    char const *mName;
+    apr_dso_handle_sym_t *mPPFunc;
+};
+
+class SymbolGrabber
+{
+public:
+    size_t registerSymbol( SymbolToGrab aSymbol );
+    bool grabSymbols(std::vector< std::string > const &aDSONames);
+    void ungrabSymbols();
+
+private:
+    std::vector< SymbolToGrab > gSymbolsToGrab;
+
+    bool sSymsGrabbed = false;
+    apr_pool_t *sSymPADSOMemoryPool = nullptr;
+    std::vector<apr_dso_handle_t *> sLoadedLibraries;
+};
+
+extern SymbolGrabber gSymbolGrabber;
+#define LL_GRAB_SYM(REQUIRED, SYMBOL_NAME, RETURN, ...) RETURN (*ll##SYMBOL_NAME)(__VA_ARGS__) = nullptr; size_t gRegistered##SYMBOL_NAME = gSymbolGrabber.registerSymbol( { REQUIRED, #SYMBOL_NAME , (apr_dso_handle_sym_t*)&ll##SYMBOL_NAME} );
+
+#endif
 
 class MediaPluginBase
 {
@@ -46,7 +74,6 @@ public:
 	static void staticReceiveMessage(const char *message_string, void **user_data);
 
 protected:
-
    /** Plugin status. */
 	typedef enum 
 	{
diff --git a/indra/media_plugins/cef/CMakeLists.txt b/indra/media_plugins/cef/CMakeLists.txt
index 410778114d..bbd2eb222a 100644
--- a/indra/media_plugins/cef/CMakeLists.txt
+++ b/indra/media_plugins/cef/CMakeLists.txt
@@ -10,18 +10,10 @@ include(Linking)
 include(PluginAPI)
 
 include(CEFPlugin)
-
+include(GLIB)
 
 ### media_plugin_cef
 
-if(NOT ADDRESS_SIZE EQUAL 32)
-  if(WINDOWS)
-    ##add_definitions(/FIXED:NO)
-  else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
-    add_definitions(-fPIC)
-  endif(WINDOWS)
-endif(NOT ADDRESS_SIZE EQUAL 32)
-
 set(media_plugin_cef_SOURCE_FILES
     media_plugin_cef.cpp
     )
@@ -32,8 +24,21 @@ set(media_plugin_cef_HEADER_FILES
 
 # Select which VolumeCatcher implementation to use
 if (LINUX)
-  message(FATAL_ERROR "CEF plugin has been enabled for a Linux compile.\n"
-    "  Please create a volume_catcher implementation for this platform.")
+  foreach( PULSE_FILE pulse/introspect.h pulse/context.h pulse/subscribe.h pulse/glib-mainloop.h )
+    find_path( PULSE_FILE_${PULSE_FILE}_FOUND ${PULSE_FILE} NO_CACHE)
+    if( NOT PULSE_FILE_${PULSE_FILE}_FOUND )
+      message( "Looking for ${PULSE_FILE} ... not found")
+      message( FATAL_ERROR "Pulse header not found" )
+    else()
+      message( "Looking for ${PULSE_FILE} ... found")
+    endif()
+  endforeach()
+  message( "Building with linux volume catcher" )
+  set(LINUX_VOLUME_CATCHER linux_volume_catcher.cpp)
+
+  list(APPEND media_plugin_cef_SOURCE_FILES ${LINUX_VOLUME_CATCHER})
+  set(CMAKE_SHARED_LINKER_FLAGS  "-Wl,--build-id -Wl,-rpath,'$ORIGIN:$ORIGIN/../../lib'")
+  list(APPEND media_plugin_cef_LINK_LIBRARIES llwindow )
 elseif (DARWIN)
   list(APPEND media_plugin_cef_SOURCE_FILES mac_volume_catcher_null.cpp)
   find_library(CORESERVICES_LIBRARY CoreServices)
@@ -60,6 +65,7 @@ add_library(media_plugin_cef
 target_link_libraries(media_plugin_cef
         media_plugin_base
         ll::cef
+        ll::glib_headers
 )
 
 if (WINDOWS)
diff --git a/indra/media_plugins/cef/linux_volume_catcher.cpp b/indra/media_plugins/cef/linux_volume_catcher.cpp
new file mode 100755
index 0000000000..9e6fe461a6
--- /dev/null
+++ b/indra/media_plugins/cef/linux_volume_catcher.cpp
@@ -0,0 +1,424 @@
+/** 
+ * @file linux_volume_catcher.cpp
+ * @brief A Linux-specific, PulseAudio-specific hack to detect and volume-adjust new audio sources
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+/*
+  The high-level design is as follows:
+  1) Connect to the PulseAudio daemon
+  2) Watch for the creation of new audio players connecting to the daemon (this includes ALSA clients running on the PulseAudio emulation layer, such as Flash plugins)
+  3) Examine any new audio player's PID to see if it belongs to our own process
+  4) If so, tell PA to adjust the volume of that audio player ('sink input' in PA parlance)
+  5) Keep a list of all living audio players that we care about, adjust the volumes of all of them when we get a new setVolume() call
+ */
+
+#include "linden_common.h"
+
+#include "volume_catcher.h"
+#include <set>
+#include <map>
+#include <iostream>
+extern "C" {
+#include <glib.h>
+#include <glib-object.h>
+
+#include <pulse/introspect.h>
+#include <pulse/context.h>
+#include <pulse/subscribe.h>
+#include <pulse/glib-mainloop.h> // There's no special reason why we want the *glib* PA mainloop, but the generic polling implementation seems broken.
+
+#include "apr_pools.h"
+#include "apr_dso.h"
+}
+
+#include "media_plugin_base.h"
+
+SymbolGrabber gSymbolGrabber;
+
+#include "linux_volume_catcher_pa_syms.inc"
+#include "linux_volume_catcher_paglib_syms.inc"
+////////////////////////////////////////////////////
+
+// PulseAudio requires a chain of callbacks with C linkage
+extern "C" {
+	void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *i, int eol, void *userdata);
+	void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata);
+	void callback_context_state(pa_context *context, void *userdata);
+}
+
+class VolumeCatcherImpl
+{
+public:
+	VolumeCatcherImpl();
+	~VolumeCatcherImpl();
+
+	void setVolume(F32 volume);
+	void pump(void);
+
+	// for internal use - can't be private because used from our C callbacks
+
+	bool loadsyms(std::string pulse_dso_name);
+	void init();
+	void cleanup();
+
+	void update_all_volumes(F32 volume);
+	void update_index_volume(U32 index, F32 volume);
+	void connected_okay();
+
+	std::set<U32> mSinkInputIndices;
+	std::map<U32,U32> mSinkInputNumChannels;
+	F32 mDesiredVolume;
+	pa_glib_mainloop *mMainloop;
+	pa_context *mPAContext;
+	bool mConnected;
+	bool mGotSyms;
+};
+
+VolumeCatcherImpl::VolumeCatcherImpl()
+	: mDesiredVolume(0.0f),
+	  mMainloop(nullptr),
+	  mPAContext(nullptr),
+	  mConnected(false),
+	  mGotSyms(false)
+{
+	init();
+}
+
+VolumeCatcherImpl::~VolumeCatcherImpl()
+{
+	cleanup();
+}
+
+bool VolumeCatcherImpl::loadsyms(std::string pulse_dso_name)
+{
+	//return grab_pa_syms({pulse_dso_name});
+    return gSymbolGrabber.grabSymbols( { pulse_dso_name }) ;
+}
+
+void VolumeCatcherImpl::init()
+{
+	// try to be as defensive as possible because PA's interface is a
+	// bit fragile and (for our purposes) we'd rather simply not function
+	// than crash
+
+	// we cheat and rely upon libpulse-mainloop-glib.so.0 to pull-in
+	// libpulse.so.0 - this isn't a great assumption, and the two DSOs should
+	// probably be loaded separately.  Our Linux DSO framework needs refactoring,
+	// we do this sort of thing a lot with practically identical logic...
+	mGotSyms = loadsyms("libpulse-mainloop-glib.so.0");
+	if (!mGotSyms) return;
+
+	mMainloop = llpa_glib_mainloop_new(g_main_context_default());
+	
+	if (mMainloop)
+	{
+		pa_mainloop_api *api = llpa_glib_mainloop_get_api(mMainloop);
+
+		if (api)
+		{
+			pa_proplist *proplist = llpa_proplist_new();
+
+			if (proplist)
+			{
+				llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ICON_NAME, "multimedia-player");
+				llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ID, "com.secondlife.viewer.mediaplugvoladjust");
+				llpa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "SL Plugin Volume Adjuster");
+				llpa_proplist_sets(proplist, PA_PROP_APPLICATION_VERSION, "1");
+
+				// plain old pa_context_new() is broken!
+				mPAContext = llpa_context_new_with_proplist(api, nullptr, proplist);
+
+				llpa_proplist_free(proplist);
+			}
+		}
+	}
+
+	// Now we've set up a PA context and mainloop, try connecting the
+	// PA context to a PA daemon.
+	if (mPAContext)
+	{
+		llpa_context_set_state_callback(mPAContext, callback_context_state, this);
+		pa_context_flags_t cflags = (pa_context_flags)0; // maybe add PA_CONTEXT_NOAUTOSPAWN?
+		if (llpa_context_connect(mPAContext, nullptr, cflags, nullptr) >= 0)
+		{
+			// Okay!  We haven't definitely connected, but we
+			// haven't definitely failed yet.
+		}
+		else
+		{
+			// Failed to connect to PA manager... we'll leave
+			// things like that.  Perhaps we should try again later.
+		}
+	}
+}
+
+void VolumeCatcherImpl::cleanup()
+{
+	mConnected = false;
+
+	if (mGotSyms && mPAContext)
+	{
+		llpa_context_disconnect(mPAContext);
+		llpa_context_unref(mPAContext);
+	}
+
+	mPAContext = nullptr;
+
+	if (mGotSyms && mMainloop)
+		llpa_glib_mainloop_free(mMainloop);
+
+	mMainloop = nullptr;
+}
+
+void VolumeCatcherImpl::setVolume(F32 volume)
+{
+	mDesiredVolume = volume;
+	
+	if (!mGotSyms) return;
+
+	if (mConnected && mPAContext)
+	{
+		update_all_volumes(mDesiredVolume);
+	}
+
+	pump();
+}
+
+void VolumeCatcherImpl::pump()
+{
+	gboolean may_block = FALSE;
+	g_main_context_iteration(g_main_context_default(), may_block);
+}
+
+void VolumeCatcherImpl::connected_okay()
+{
+	pa_operation *op;
+
+	// fetch global list of existing sinkinputs
+	if ((op = llpa_context_get_sink_input_info_list(mPAContext,
+							callback_discovered_sinkinput,
+							this)))
+	{
+		llpa_operation_unref(op);
+	}
+
+	// subscribe to future global sinkinput changes
+	llpa_context_set_subscribe_callback(mPAContext,
+					    callback_subscription_alert,
+					    this);
+	if ((op = llpa_context_subscribe(mPAContext, (pa_subscription_mask_t)
+					 (PA_SUBSCRIPTION_MASK_SINK_INPUT),
+                                     nullptr, nullptr)))
+	{
+		llpa_operation_unref(op);
+	}
+}
+
+void VolumeCatcherImpl::update_all_volumes(F32 volume)
+{
+	for (std::set<U32>::iterator it = mSinkInputIndices.begin();
+	     it != mSinkInputIndices.end(); ++it)
+	{
+		update_index_volume(*it, volume);
+	}
+}
+
+void VolumeCatcherImpl::update_index_volume(U32 index, F32 volume)
+{
+	static pa_cvolume cvol;
+	llpa_cvolume_set(&cvol, mSinkInputNumChannels[index],
+			 llpa_sw_volume_from_linear(volume));
+	
+	pa_context *c = mPAContext;
+	uint32_t idx = index;
+	const pa_cvolume *cvolumep = &cvol;
+	pa_context_success_cb_t cb = nullptr; // okay as null
+	void *userdata = nullptr; // okay as null
+
+	pa_operation *op;
+	if ((op = llpa_context_set_sink_input_volume(c, idx, cvolumep, cb, userdata)))
+		llpa_operation_unref(op);
+}
+
+pid_t getParentPid( pid_t aPid )
+{
+	std::stringstream strm;
+	strm << "/proc/" << aPid << "/status";
+	std::ifstream in{ strm.str() };
+
+	if( !in.is_open() )
+		return 0;
+
+	pid_t res {0};
+	while( !in.eof() && res == 0 )
+	{
+		std::string line;
+		line.resize( 1024, 0 );
+		in.getline( &line[0], line.length() );	
+
+		auto i = line.find( "PPid:"  );
+		
+		if( i == std::string::npos )
+			continue;
+		
+		char const *pIn = line.c_str() + 5; // Skip over pid;
+		while( *pIn != 0 && isspace( *pIn ) )
+			   ++pIn;
+
+		if( *pIn )
+			res = atoll( pIn );
+	}
+ 	return res;
+}
+
+
+bool isPluginPid( pid_t aPid )
+{
+	auto myPid = getpid();
+
+	do
+	{
+		if( aPid == myPid )
+			return true;
+		aPid = getParentPid( aPid );
+	} while( aPid > 1 );
+
+	return false;
+}
+
+void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *sii, int eol, void *userdata)
+{
+	VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata);
+	llassert(impl);
+
+	if (0 == eol)
+	{
+		pa_proplist *proplist = sii->proplist;
+		pid_t sinkpid = atoll(llpa_proplist_gets(proplist, PA_PROP_APPLICATION_PROCESS_ID));
+
+		if (isPluginPid( sinkpid )) // does the discovered sinkinput belong to this process?
+		{
+			bool is_new = (impl->mSinkInputIndices.find(sii->index) == impl->mSinkInputIndices.end());
+			
+			impl->mSinkInputIndices.insert(sii->index);
+			impl->mSinkInputNumChannels[sii->index] = sii->channel_map.channels;
+			
+			if (is_new)
+			{
+				// new!
+				impl->update_index_volume(sii->index, impl->mDesiredVolume);
+			}
+			else
+			{
+				// seen it already, do nothing.
+			}
+		}
+	}
+}
+
+void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata)
+{
+	VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata);
+	llassert(impl);
+
+	switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)
+	{
+        case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
+			if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==  PA_SUBSCRIPTION_EVENT_REMOVE)
+			{
+				// forget this sinkinput, if we were caring about it
+				impl->mSinkInputIndices.erase(index);
+				impl->mSinkInputNumChannels.erase(index);
+			}
+			else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW)
+			{
+				// ask for more info about this new sinkinput
+				pa_operation *op;
+				if ((op = llpa_context_get_sink_input_info(impl->mPAContext, index, callback_discovered_sinkinput, impl)))
+				{
+					llpa_operation_unref(op);
+				}
+			}
+			else
+			{
+				// property change on this sinkinput - we don't care.
+			}
+			break;
+		
+		default:;
+	}
+}
+
+void callback_context_state(pa_context *context, void *userdata)
+{
+	VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata);
+	llassert(impl);
+	
+	switch (llpa_context_get_state(context))
+	{
+	case PA_CONTEXT_READY:
+		impl->mConnected = true;
+		impl->connected_okay();
+		break;
+	case PA_CONTEXT_TERMINATED:
+		impl->mConnected = false;
+		break;
+	case PA_CONTEXT_FAILED:
+		impl->mConnected = false;
+		break;
+	default:;
+	}
+}
+
+/////////////////////////////////////////////////////
+
+VolumeCatcher::VolumeCatcher()
+{
+	pimpl = new VolumeCatcherImpl();
+}
+
+VolumeCatcher::~VolumeCatcher()
+{
+	delete pimpl;
+	pimpl = nullptr;
+}
+
+void VolumeCatcher::setVolume(F32 volume)
+{
+	llassert(pimpl);
+	pimpl->setVolume(volume);
+}
+
+void VolumeCatcher::setPan(F32 pan)
+{
+	// TODO: implement this (if possible)
+}
+
+void VolumeCatcher::pump()
+{
+	llassert(pimpl);
+	pimpl->pump();
+}
diff --git a/indra/media_plugins/cef/linux_volume_catcher_pa_syms.inc b/indra/media_plugins/cef/linux_volume_catcher_pa_syms.inc
new file mode 100755
index 0000000000..4533362e61
--- /dev/null
+++ b/indra/media_plugins/cef/linux_volume_catcher_pa_syms.inc
@@ -0,0 +1,21 @@
+// required symbols to grab
+LL_GRAB_SYM(true, pa_context_connect, int, pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api)
+LL_GRAB_SYM(true, pa_context_disconnect, void, pa_context *c)
+LL_GRAB_SYM(true, pa_context_get_sink_input_info, pa_operation*, pa_context *c, uint32_t idx, pa_sink_input_info_cb_t cb, void *userdata)
+LL_GRAB_SYM(true, pa_context_get_sink_input_info_list, pa_operation*, pa_context *c, pa_sink_input_info_cb_t cb, void *userdata)
+LL_GRAB_SYM(true, pa_context_get_state, pa_context_state_t, pa_context *c)
+LL_GRAB_SYM(true, pa_context_new_with_proplist, pa_context*, pa_mainloop_api *mainloop, const char *name, pa_proplist *proplist)
+LL_GRAB_SYM(true, pa_context_set_sink_input_volume, pa_operation*, pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata)
+LL_GRAB_SYM(true, pa_context_set_state_callback, void, pa_context *c, pa_context_notify_cb_t cb, void *userdata)
+LL_GRAB_SYM(true, pa_context_set_subscribe_callback, void, pa_context *c, pa_context_subscribe_cb_t cb, void *userdata)
+LL_GRAB_SYM(true, pa_context_subscribe, pa_operation*, pa_context *c, pa_subscription_mask_t m, pa_context_success_cb_t cb, void *userdata)
+LL_GRAB_SYM(true, pa_context_unref, void, pa_context *c)
+LL_GRAB_SYM(true, pa_cvolume_set, pa_cvolume*, pa_cvolume *a, unsigned channels, pa_volume_t v)
+LL_GRAB_SYM(true, pa_operation_unref, void, pa_operation *o)
+LL_GRAB_SYM(true, pa_proplist_free, void, pa_proplist* p)
+LL_GRAB_SYM(true, pa_proplist_gets, const char*, pa_proplist *p, const char *key)
+LL_GRAB_SYM(true, pa_proplist_new, pa_proplist*, void)
+LL_GRAB_SYM(true, pa_proplist_sets, int, pa_proplist *p, const char *key, const char *value)
+LL_GRAB_SYM(true, pa_sw_volume_from_linear, pa_volume_t, double v)
+
+// optional symbols to grab
diff --git a/indra/media_plugins/cef/linux_volume_catcher_paglib_syms.inc b/indra/media_plugins/cef/linux_volume_catcher_paglib_syms.inc
new file mode 100755
index 0000000000..5fba60c188
--- /dev/null
+++ b/indra/media_plugins/cef/linux_volume_catcher_paglib_syms.inc
@@ -0,0 +1,6 @@
+// required symbols to grab
+LL_GRAB_SYM(true, pa_glib_mainloop_free, void, pa_glib_mainloop* g)
+LL_GRAB_SYM(true, pa_glib_mainloop_get_api, pa_mainloop_api*, pa_glib_mainloop* g)
+LL_GRAB_SYM(true, pa_glib_mainloop_new, pa_glib_mainloop *, GMainContext *c)
+
+// optional symbols to grab
diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp
index 43d3a32e64..60d91753d0 100644
--- a/indra/media_plugins/cef/media_plugin_cef.cpp
+++ b/indra/media_plugins/cef/media_plugin_cef.cpp
@@ -886,7 +886,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
 
                 keyEvent(key_event, native_key_data);
 
-#elif LL_WINDOWS
+#else
 				std::string event = message_in.getValue("event");
 				LLSD native_key_data = message_in.getValueLLSD("native_key_data");
 
@@ -1050,6 +1050,28 @@ void MediaPluginCEF::keyEvent(dullahan::EKeyEvent key_event, LLSD native_key_dat
 
 	mCEFLib->nativeKeyboardEventWin(msg, wparam, lparam);
 #endif
+
+#if LL_LINUX
+
+	uint32_t native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger());		// this is actually the SDL event.key.keysym.sym;
+	uint32_t native_virtual_key_win = (uint32_t)(native_key_data["virtual_key_win"].asInteger());
+	uint32_t native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger());
+
+	// only for non-printable keysyms, the actual text input is done in unicodeInput() below
+	if (native_virtual_key <= 0x1b || native_virtual_key >= 0x7f)
+	{
+		// set keypad flag, not sure if this even does anything
+		bool keypad = false;
+		if (native_virtual_key_win >= 0x60 && native_virtual_key_win <= 0x6f)
+		{
+			keypad = true;
+		}
+
+		// yes, we send native_virtual_key_win twice because native_virtual_key breaks it
+		mCEFLib->nativeKeyboardEventSDL2(key_event, native_virtual_key, native_modifiers, keypad);
+	}
+
+#endif // LL_LINUX
 };
 
 void MediaPluginCEF::unicodeInput(std::string event, LLSD native_key_data = LLSD::emptyMap())
@@ -1080,6 +1102,16 @@ void MediaPluginCEF::unicodeInput(std::string event, LLSD native_key_data = LLSD
 	U64 lparam = ll_U32_from_sd(native_key_data["l_param"]);
 	mCEFLib->nativeKeyboardEventWin(msg, wparam, lparam);
 #endif
+
+#if LL_LINUX
+
+	uint32_t native_scan_code = (uint32_t)(native_key_data["sdl_sym"].asInteger());
+	uint32_t native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger());
+	uint32_t native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger());
+
+	mCEFLib->nativeKeyboardEvent(dullahan::KE_KEY_DOWN, native_scan_code, native_virtual_key, native_modifiers);
+
+#endif // LL_LINUX
 };
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/media_plugins/example/CMakeLists.txt b/indra/media_plugins/example/CMakeLists.txt
index 7d3e7f663b..86e982fbb4 100644
--- a/indra/media_plugins/example/CMakeLists.txt
+++ b/indra/media_plugins/example/CMakeLists.txt
@@ -13,14 +13,6 @@ include(ExamplePlugin)
 
 ### media_plugin_example
 
-if(NOT ADDRESS_SIZE EQUAL 32)
-  if(WINDOWS)
-    ##add_definitions(/FIXED:NO)
-  else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
-    add_definitions(-fPIC)
-  endif(WINDOWS)
-endif(NOT ADDRESS_SIZE EQUAL 32)
-
 set(media_plugin_example_SOURCE_FILES
     media_plugin_example.cpp
     )
diff --git a/indra/media_plugins/gstreamer010/CMakeLists.txt b/indra/media_plugins/gstreamer010/CMakeLists.txt
deleted file mode 100644
index 38fc8201bf..0000000000
--- a/indra/media_plugins/gstreamer010/CMakeLists.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-# -*- cmake -*-
-
-project(media_plugin_gstreamer010)
-
-include(00-Common)
-include(LLCommon)
-include(LLImage)
-include(LLMath)
-include(LLWindow)
-include(Linking)
-include(PluginAPI)
-include(OpenGL)
-
-include(GStreamer010Plugin)
-
-### media_plugin_gstreamer010
-
-if(NOT ADDRESS_SIZE EQUAL 32)
-  if(WINDOWS)
-    ##add_definitions(/FIXED:NO)
-  else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
-    add_definitions(-fPIC)
-  endif(WINDOWS)
-endif(NOT ADDRESS_SIZE EQUAL 32)
-
-set(media_plugin_gstreamer010_SOURCE_FILES
-    media_plugin_gstreamer010.cpp
-    llmediaimplgstreamer_syms.cpp
-    llmediaimplgstreamervidplug.cpp
-    )
-
-set(media_plugin_gstreamer010_HEADER_FILES
-    llmediaimplgstreamervidplug.h
-    llmediaimplgstreamer_syms.h
-    llmediaimplgstreamertriviallogging.h
-    )
-
-add_library(media_plugin_gstreamer010
-    SHARED
-    ${media_plugin_gstreamer010_SOURCE_FILES}
-    )
-
-target_link_libraries(media_plugin_gstreamer010
-        media_plugin_base
-        ll::gstreamer
-  )
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h
deleted file mode 100644
index 6bc272c009..0000000000
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/** 
- * @file llmediaimplgstreamer.h
- * @author Tofu Linden
- * @brief implementation that supports media playback via GStreamer.
- *
- * @cond
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- * @endcond
- */
-
-// header guard
-#ifndef llmediaimplgstreamer_h
-#define llmediaimplgstreamer_h
-
-#if LL_GSTREAMER010_ENABLED
-
-extern "C" {
-#include <stdio.h>
-#include <gst/gst.h>
-
-#include "apr_pools.h"
-#include "apr_dso.h"
-}
-
-
-extern "C" {
-gboolean llmediaimplgstreamer_bus_callback (GstBus     *bus,
-					    GstMessage *message,
-					    gpointer    data);
-}
-
-#endif // LL_GSTREAMER010_ENABLED
-
-#endif // llmediaimplgstreamer_h
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp
deleted file mode 100644
index 2e4baaa9eb..0000000000
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-/** 
- * @file llmediaimplgstreamer_syms.cpp
- * @brief dynamic GStreamer symbol-grabbing code
- *
- * @cond
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- * @endcond
- */
-
-#if LL_GSTREAMER010_ENABLED
-
-#include <string>
-
-extern "C" {
-#include <gst/gst.h>
-
-#include "apr_pools.h"
-#include "apr_dso.h"
-}
-
-#include "llmediaimplgstreamertriviallogging.h"
-
-#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) RTN (*ll##GSTSYM)(__VA_ARGS__) = NULL
-#include "llmediaimplgstreamer_syms_raw.inc"
-#include "llmediaimplgstreamer_syms_rawv.inc"
-#undef LL_GST_SYM
-
-// a couple of stubs for disgusting reasons
-GstDebugCategory*
-ll_gst_debug_category_new(gchar *name, guint color, gchar *description)
-{
-	static GstDebugCategory dummy;
-	return &dummy;
-}
-void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname)
-{
-}
-
-static bool sSymsGrabbed = false;
-static apr_pool_t *sSymGSTDSOMemoryPool = NULL;
-static apr_dso_handle_t *sSymGSTDSOHandleG = NULL;
-static apr_dso_handle_t *sSymGSTDSOHandleV = NULL;
-
-
-bool grab_gst_syms(std::string gst_dso_name,
-		   std::string gst_dso_name_vid)
-{
-	if (sSymsGrabbed)
-	{
-		// already have grabbed good syms
-		return TRUE;
-	}
-
-	bool sym_error = false;
-	bool rtn = false;
-	apr_status_t rv;
-	apr_dso_handle_t *sSymGSTDSOHandle = NULL;
-
-#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##GSTSYM, sSymGSTDSOHandle, #GSTSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #GSTSYM); if (REQ) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #GSTSYM, (void*)ll##GSTSYM);}while(0)
-
-	//attempt to load the shared libraries
-	apr_pool_create(&sSymGSTDSOMemoryPool, NULL);
-  
-	if ( APR_SUCCESS == (rv = apr_dso_load(&sSymGSTDSOHandle,
-					       gst_dso_name.c_str(),
-					       sSymGSTDSOMemoryPool) ))
-	{
-		INFOMSG("Found DSO: %s", gst_dso_name.c_str());
-#include "llmediaimplgstreamer_syms_raw.inc"
-      
-		if ( sSymGSTDSOHandle )
-		{
-			sSymGSTDSOHandleG = sSymGSTDSOHandle;
-			sSymGSTDSOHandle = NULL;
-		}
-      
-		if ( APR_SUCCESS ==
-		     (rv = apr_dso_load(&sSymGSTDSOHandle,
-					gst_dso_name_vid.c_str(),
-					sSymGSTDSOMemoryPool) ))
-		{
-			INFOMSG("Found DSO: %s", gst_dso_name_vid.c_str());
-#include "llmediaimplgstreamer_syms_rawv.inc"
-			rtn = !sym_error;
-		}
-		else
-		{
-			INFOMSG("Couldn't load DSO: %s", gst_dso_name_vid.c_str());
-			rtn = false; // failure
-		}
-	}
-	else
-	{
-		INFOMSG("Couldn't load DSO: %s", gst_dso_name.c_str());
-		rtn = false; // failure
-	}
-
-	if (sym_error)
-	{
-		WARNMSG("Failed to find necessary symbols in GStreamer libraries.");
-	}
-	
-	if ( sSymGSTDSOHandle )
-	{
-		sSymGSTDSOHandleV = sSymGSTDSOHandle;
-		sSymGSTDSOHandle = NULL;
-	}
-#undef LL_GST_SYM
-
-	sSymsGrabbed = !!rtn;
-	return rtn;
-}
-
-
-void ungrab_gst_syms()
-{ 
-	// should be safe to call regardless of whether we've
-	// actually grabbed syms.
-
-	if ( sSymGSTDSOHandleG )
-	{
-		apr_dso_unload(sSymGSTDSOHandleG);
-		sSymGSTDSOHandleG = NULL;
-	}
-	
-	if ( sSymGSTDSOHandleV )
-	{
-		apr_dso_unload(sSymGSTDSOHandleV);
-		sSymGSTDSOHandleV = NULL;
-	}
-	
-	if ( sSymGSTDSOMemoryPool )
-	{
-		apr_pool_destroy(sSymGSTDSOMemoryPool);
-		sSymGSTDSOMemoryPool = NULL;
-	}
-	
-	// NULL-out all of the symbols we'd grabbed
-#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{ll##GSTSYM = NULL;}while(0)
-#include "llmediaimplgstreamer_syms_raw.inc"
-#include "llmediaimplgstreamer_syms_rawv.inc"
-#undef LL_GST_SYM
-
-	sSymsGrabbed = false;
-}
-
-
-#endif // LL_GSTREAMER010_ENABLED
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h
deleted file mode 100644
index d1559089c8..0000000000
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/** 
- * @file llmediaimplgstreamer_syms.h
- * @brief dynamic GStreamer symbol-grabbing code
- *
- * @cond
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- * @endcond
- */
-
-#include "linden_common.h"
-
-#if LL_GSTREAMER010_ENABLED
-
-extern "C" {
-#include <gst/gst.h>
-}
-
-bool grab_gst_syms(std::string gst_dso_name,
-		   std::string gst_dso_name_vid);
-void ungrab_gst_syms();
-
-#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) extern RTN (*ll##GSTSYM)(__VA_ARGS__)
-#include "llmediaimplgstreamer_syms_raw.inc"
-#include "llmediaimplgstreamer_syms_rawv.inc"
-#undef LL_GST_SYM
-
-// regrettable hacks to give us better runtime compatibility with older systems
-#define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0)
-#define llg_return_val_if_fail(COND,V) do{if (!(COND)) return V;}while(0)
-
-// regrettable hacks because GStreamer was not designed for runtime loading
-#undef GST_TYPE_MESSAGE
-#define GST_TYPE_MESSAGE (llgst_message_get_type())
-#undef GST_TYPE_OBJECT
-#define GST_TYPE_OBJECT (llgst_object_get_type())
-#undef GST_TYPE_PIPELINE
-#define GST_TYPE_PIPELINE (llgst_pipeline_get_type())
-#undef GST_TYPE_ELEMENT
-#define GST_TYPE_ELEMENT (llgst_element_get_type())
-#undef GST_TYPE_VIDEO_SINK
-#define GST_TYPE_VIDEO_SINK (llgst_video_sink_get_type())
-// more regrettable hacks to stub-out these .h-exposed GStreamer internals
-void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname);
-#undef _gst_debug_register_funcptr
-#define _gst_debug_register_funcptr ll_gst_debug_register_funcptr
-GstDebugCategory* ll_gst_debug_category_new(gchar *name, guint color, gchar *description);
-#undef _gst_debug_category_new
-#define _gst_debug_category_new ll_gst_debug_category_new
-#undef __gst_debug_enabled
-#define __gst_debug_enabled (0)
-
-// more hacks
-#define LLGST_MESSAGE_TYPE_NAME(M) (llgst_message_type_get_name(GST_MESSAGE_TYPE(M)))
-
-#endif // LL_GSTREAMER010_ENABLED
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc
deleted file mode 100644
index b33e59363d..0000000000
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc
+++ /dev/null
@@ -1,51 +0,0 @@
-
-// required symbols to grab
-LL_GST_SYM(true, gst_pad_peer_accept_caps, gboolean, GstPad *pad, GstCaps *caps);
-LL_GST_SYM(true, gst_buffer_new, GstBuffer*, void);
-LL_GST_SYM(true, gst_buffer_set_caps, void, GstBuffer*, GstCaps *);
-LL_GST_SYM(true, gst_structure_set_value, void, GstStructure *, const gchar *, const GValue*);
-LL_GST_SYM(true, gst_init_check, gboolean, int *argc, char **argv[], GError ** err);
-LL_GST_SYM(true, gst_message_get_type, GType, void);
-LL_GST_SYM(true, gst_message_type_get_name, const gchar*, GstMessageType type);
-LL_GST_SYM(true, gst_message_parse_error, void, GstMessage *message, GError **gerror, gchar **debug);
-LL_GST_SYM(true, gst_message_parse_warning, void, GstMessage *message, GError **gerror, gchar **debug);
-LL_GST_SYM(true, gst_message_parse_state_changed, void, GstMessage *message, GstState *oldstate, GstState *newstate, GstState *pending);
-LL_GST_SYM(true, gst_element_set_state, GstStateChangeReturn, GstElement *element, GstState state);
-LL_GST_SYM(true, gst_object_unref, void, gpointer object);
-LL_GST_SYM(true, gst_object_get_type, GType, void);
-LL_GST_SYM(true, gst_pipeline_get_type, GType, void);
-LL_GST_SYM(true, gst_pipeline_get_bus, GstBus*, GstPipeline *pipeline);
-LL_GST_SYM(true, gst_bus_add_watch, guint, GstBus * bus, GstBusFunc func, gpointer user_data);
-LL_GST_SYM(true, gst_element_factory_make, GstElement*, const gchar *factoryname, const gchar *name);
-LL_GST_SYM(true, gst_element_get_type, GType, void);
-LL_GST_SYM(true, gst_static_pad_template_get, GstPadTemplate*, GstStaticPadTemplate *pad_template);
-LL_GST_SYM(true, gst_element_class_add_pad_template, void, GstElementClass *klass, GstPadTemplate *temp);
-LL_GST_SYM(true, gst_element_class_set_details, void, GstElementClass *klass, const GstElementDetails *details);
-LL_GST_SYM(true, gst_caps_unref, void, GstCaps* caps);
-LL_GST_SYM(true, gst_caps_ref, GstCaps *, GstCaps* caps);
-//LL_GST_SYM(true, gst_caps_is_empty, gboolean, const GstCaps *caps);
-LL_GST_SYM(true, gst_caps_from_string, GstCaps *, const gchar *string);
-LL_GST_SYM(true, gst_caps_replace, void, GstCaps **caps, GstCaps *newcaps);
-LL_GST_SYM(true, gst_caps_get_structure, GstStructure *, const GstCaps *caps, guint index);
-LL_GST_SYM(true, gst_caps_copy, GstCaps *, const GstCaps * caps);
-//LL_GST_SYM(true, gst_caps_intersect, GstCaps *, const GstCaps *caps1, const GstCaps *caps2);
-LL_GST_SYM(true, gst_element_register, gboolean, GstPlugin *plugin, const gchar *name, guint rank, GType type);
-LL_GST_SYM(true, _gst_plugin_register_static, void, GstPluginDesc *desc);
-LL_GST_SYM(true, gst_structure_get_int, gboolean, const GstStructure *structure, const gchar *fieldname, gint *value);
-LL_GST_SYM(true, gst_structure_get_value, G_CONST_RETURN GValue *, const GstStructure *structure, const gchar *fieldname);
-LL_GST_SYM(true, gst_value_get_fraction_numerator, gint, const GValue *value);
-LL_GST_SYM(true, gst_value_get_fraction_denominator, gint, const GValue *value);
-LL_GST_SYM(true, gst_structure_get_name, G_CONST_RETURN gchar *, const GstStructure *structure);
-LL_GST_SYM(true, gst_element_seek, bool, GstElement *, gdouble, GstFormat, GstSeekFlags, GstSeekType, gint64, GstSeekType, gint64);
-
-// optional symbols to grab
-LL_GST_SYM(false, gst_registry_fork_set_enabled, void, gboolean enabled);
-LL_GST_SYM(false, gst_segtrap_set_enabled, void, gboolean enabled);
-LL_GST_SYM(false, gst_message_parse_buffering, void, GstMessage *message, gint *percent);
-LL_GST_SYM(false, gst_message_parse_info, void, GstMessage *message, GError **gerror, gchar **debug);
-LL_GST_SYM(false, gst_element_query_position, gboolean, GstElement *element, GstFormat *format, gint64 *cur);
-LL_GST_SYM(false, gst_version, void, guint *major, guint *minor, guint *micro, guint *nano);
-
-// GStreamer 'internal' symbols which may not be visible in some runtimes but are still used in expanded GStreamer header macros - yuck!  We'll substitute our own stubs for these.
-//LL_GST_SYM(true, _gst_debug_register_funcptr, void, GstDebugFuncPtr func, gchar* ptrname);
-//LL_GST_SYM(true, _gst_debug_category_new, GstDebugCategory *, gchar *name, guint color, gchar *description);
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc
deleted file mode 100644
index 14fbcb48b9..0000000000
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc
+++ /dev/null
@@ -1,5 +0,0 @@
-
-// required symbols to grab
-LL_GST_SYM(true, gst_video_sink_get_type, GType, void);
-
-// optional symbols to grab
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h
deleted file mode 100644
index e7b31bec94..0000000000
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * @file llmediaimplgstreamertriviallogging.h
- * @brief minimal logging utilities.
- *
- * @cond
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- * @endcond
- */
-
-#ifndef __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__
-#define __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__
-
-#include <cstdio>
-
-extern "C" {
-#include <sys/types.h>
-#include <unistd.h>
-}
-
-/////////////////////////////////////////////////////////////////////////
-// Debug/Info/Warning macros.
-#define MSGMODULEFOO "(media plugin)"
-#define STDERRMSG(...) do{\
-    fprintf(stderr, " pid:%d: ", (int)getpid());\
-    fprintf(stderr, MSGMODULEFOO " %s:%d: ", __FUNCTION__, __LINE__);\
-    fprintf(stderr, __VA_ARGS__);\
-    fputc('\n',stderr);\
-  }while(0)
-#define NULLMSG(...) do{}while(0)
-
-#define DEBUGMSG NULLMSG
-#define INFOMSG  STDERRMSG
-#define WARNMSG  STDERRMSG
-/////////////////////////////////////////////////////////////////////////
-
-#endif /* __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__ */
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
deleted file mode 100644
index 932aaffa1b..0000000000
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
+++ /dev/null
@@ -1,526 +0,0 @@
-/**
- * @file llmediaimplgstreamervidplug.h
- * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl
- *
- * @cond
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- * @endcond
- */
-
-#if LL_GSTREAMER010_ENABLED
-
-#include "linden_common.h"
-
-#include <gst/gst.h>
-#include <gst/video/video.h>
-#include <gst/video/gstvideosink.h>
-
-#include "llmediaimplgstreamer_syms.h"
-#include "llmediaimplgstreamertriviallogging.h"
-
-#include "llmediaimplgstreamervidplug.h"
-
-
-GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug);
-#define GST_CAT_DEFAULT gst_slvideo_debug
-
-
-#define SLV_SIZECAPS ", width=(int)[1,2048], height=(int)[1,2048] "
-#define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS
-
-static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE (
-    (gchar*)"sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (SLV_ALLCAPS)
-    );
-
-GST_BOILERPLATE (GstSLVideo, gst_slvideo, GstVideoSink,
-    GST_TYPE_VIDEO_SINK);
-
-static void gst_slvideo_set_property (GObject * object, guint prop_id,
-				      const GValue * value,
-				      GParamSpec * pspec);
-static void gst_slvideo_get_property (GObject * object, guint prop_id,
-				      GValue * value, GParamSpec * pspec);
-
-static void
-gst_slvideo_base_init (gpointer gclass)
-{
-	static GstElementDetails element_details = {
-		(gchar*)"PluginTemplate",
-		(gchar*)"Generic/PluginTemplate",
-		(gchar*)"Generic Template Element",
-		(gchar*)"Linden Lab"
-	};
-	GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
-	
-	llgst_element_class_add_pad_template (element_class,
-			      llgst_static_pad_template_get (&sink_factory));
-	llgst_element_class_set_details (element_class, &element_details);
-}
-
-
-static void
-gst_slvideo_finalize (GObject * object)
-{
-	GstSLVideo *slvideo;
-	slvideo = GST_SLVIDEO (object);
-	if (slvideo->caps)
-	{
-		llgst_caps_unref(slvideo->caps);
-	}
-
-	G_OBJECT_CLASS(parent_class)->finalize (object);
-}
-
-
-static GstFlowReturn
-gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf)
-{
-	GstSLVideo *slvideo;
-	llg_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
-	
-	slvideo = GST_SLVIDEO(bsink);
-	
-	DEBUGMSG("transferring a frame of %dx%d <- %p (%d)",
-		 slvideo->width, slvideo->height, GST_BUFFER_DATA(buf),
-		 slvideo->format);
-
-	if (GST_BUFFER_DATA(buf))
-	{
-		// copy frame and frame info into neutral territory
-		GST_OBJECT_LOCK(slvideo);
-		slvideo->retained_frame_ready = TRUE;
-		slvideo->retained_frame_width = slvideo->width;
-		slvideo->retained_frame_height = slvideo->height;
-		slvideo->retained_frame_format = slvideo->format;
-		int rowbytes = 
-			SLVPixelFormatBytes[slvideo->retained_frame_format] *
-			slvideo->retained_frame_width;
-		int needbytes = rowbytes * slvideo->retained_frame_width;
-		// resize retained frame hunk only if necessary
-		if (needbytes != slvideo->retained_frame_allocbytes)
-		{
-			delete[] slvideo->retained_frame_data;
-			slvideo->retained_frame_data = new unsigned char[needbytes];
-			slvideo->retained_frame_allocbytes = needbytes;
-			
-		}
-		// copy the actual frame data to neutral territory -
-		// flipped, for GL reasons
-		for (int ypos=0; ypos<slvideo->height; ++ypos)
-		{
-			memcpy(&slvideo->retained_frame_data[(slvideo->height-1-ypos)*rowbytes],
-			       &(((unsigned char*)GST_BUFFER_DATA(buf))[ypos*rowbytes]),
-			       rowbytes);
-		}
-		// done with the shared data
-		GST_OBJECT_UNLOCK(slvideo);
-	}
-
-	return GST_FLOW_OK;
-}
-
-
-static GstStateChangeReturn
-gst_slvideo_change_state(GstElement * element, GstStateChange transition)
-{
-	GstSLVideo *slvideo;
-	GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
-	
-	slvideo = GST_SLVIDEO (element);
-
-	switch (transition) {
-	case GST_STATE_CHANGE_NULL_TO_READY:
-		break;
-	case GST_STATE_CHANGE_READY_TO_PAUSED:
-		break;
-	case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-		break;
-	default:
-		break;
-	}
-
-	ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-	if (ret == GST_STATE_CHANGE_FAILURE)
-		return ret;
-
-	switch (transition) {
-	case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-		break;
-	case GST_STATE_CHANGE_PAUSED_TO_READY:
-		slvideo->fps_n = 0;
-		slvideo->fps_d = 1;
-		GST_VIDEO_SINK_WIDTH(slvideo) = 0;
-		GST_VIDEO_SINK_HEIGHT(slvideo) = 0;
-		break;
-	case GST_STATE_CHANGE_READY_TO_NULL:
-		break;
-	default:
-		break;
-	}
-
-	return ret;
-}
-
-
-static GstCaps *
-gst_slvideo_get_caps (GstBaseSink * bsink)
-{
-	GstSLVideo *slvideo;
-	slvideo = GST_SLVIDEO(bsink);
-	
-	return llgst_caps_ref (slvideo->caps);
-}
-
-
-/* this function handles the link with other elements */
-static gboolean
-gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps)
-{
-	GstSLVideo *filter;
-	GstStructure *structure;
-	
-	GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps);
-	
-	filter = GST_SLVIDEO(bsink);
-
-	int width, height;
-	gboolean ret;
-	const GValue *fps;
-	const GValue *par;
-	structure = llgst_caps_get_structure (caps, 0);
-	ret = llgst_structure_get_int (structure, "width", &width);
-	ret = ret && llgst_structure_get_int (structure, "height", &height);
-	fps = llgst_structure_get_value (structure, "framerate");
-	ret = ret && (fps != NULL);
-	par = llgst_structure_get_value (structure, "pixel-aspect-ratio");
-	if (!ret)
-		return FALSE;
-
-	INFOMSG("** filter caps set with width=%d, height=%d", width, height);
-
-	GST_OBJECT_LOCK(filter);
-
-	filter->width = width;
-	filter->height = height;
-
-	filter->fps_n = llgst_value_get_fraction_numerator(fps);
-	filter->fps_d = llgst_value_get_fraction_denominator(fps);
-	if (par)
-	{
-		filter->par_n = llgst_value_get_fraction_numerator(par);
-		filter->par_d = llgst_value_get_fraction_denominator(par);
-	}
-	else
-	{
-		filter->par_n = 1;
-		filter->par_d = 1;
-	}
-	GST_VIDEO_SINK_WIDTH(filter) = width;
-	GST_VIDEO_SINK_HEIGHT(filter) = height;
-	
-	// crufty lump - we *always* accept *only* RGBX now.
-	/*
-	filter->format = SLV_PF_UNKNOWN;
-	if (0 == strcmp(llgst_structure_get_name(structure),
-			"video/x-raw-rgb"))
-	{
-		int red_mask;
-		int green_mask;
-		int blue_mask;
-		llgst_structure_get_int(structure, "red_mask", &red_mask);
-		llgst_structure_get_int(structure, "green_mask", &green_mask);
-		llgst_structure_get_int(structure, "blue_mask", &blue_mask);
-		if ((unsigned int)red_mask   == 0xFF000000 &&
-		    (unsigned int)green_mask == 0x00FF0000 &&
-		    (unsigned int)blue_mask  == 0x0000FF00)
-		{
-			filter->format = SLV_PF_RGBX;
-			//fprintf(stderr, "\n\nPIXEL FORMAT RGB\n\n");
-		} else if ((unsigned int)red_mask   == 0x0000FF00 &&
-			   (unsigned int)green_mask == 0x00FF0000 &&
-			   (unsigned int)blue_mask  == 0xFF000000)
-		{
-			filter->format = SLV_PF_BGRX;
-			//fprintf(stderr, "\n\nPIXEL FORMAT BGR\n\n");
-		}
-		}*/
-	
-	filter->format = SLV_PF_RGBX;
-
-	GST_OBJECT_UNLOCK(filter);
-
-	return TRUE;
-}
-
-
-static gboolean
-gst_slvideo_start (GstBaseSink * bsink)
-{
-	gboolean ret = TRUE;
-	
-	GST_SLVIDEO(bsink);
-
-	return ret;
-}
-
-static gboolean
-gst_slvideo_stop (GstBaseSink * bsink)
-{
-	GstSLVideo *slvideo;
-	slvideo = GST_SLVIDEO(bsink);
-
-	// free-up retained frame buffer
-	GST_OBJECT_LOCK(slvideo);
-	slvideo->retained_frame_ready = FALSE;
-	delete[] slvideo->retained_frame_data;
-	slvideo->retained_frame_data = NULL;
-	slvideo->retained_frame_allocbytes = 0;
-	GST_OBJECT_UNLOCK(slvideo);
-
-	return TRUE;
-}
-
-
-static GstFlowReturn
-gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
-			  GstCaps * caps, GstBuffer ** buf)
-{
-	gint width, height;
-	GstStructure *structure = NULL;
-	GstSLVideo *slvideo;
-	slvideo = GST_SLVIDEO(bsink);
-
-	// caps == requested caps
-	// we can ignore these and reverse-negotiate our preferred dimensions with
-	// the peer if we like - we need to do this to obey dynamic resize requests
-	// flowing in from the app.
-	structure = llgst_caps_get_structure (caps, 0);
-	if (!llgst_structure_get_int(structure, "width", &width) ||
-	    !llgst_structure_get_int(structure, "height", &height))
-	{
-		GST_WARNING_OBJECT (slvideo, "no width/height in caps %" GST_PTR_FORMAT, caps);
-		return GST_FLOW_NOT_NEGOTIATED;
-	}
-
-	GstBuffer *newbuf = llgst_buffer_new();
-	bool made_bufferdata_ptr = false;
-#define MAXDEPTHHACK 4
-	
-	GST_OBJECT_LOCK(slvideo);
-	if (slvideo->resize_forced_always) // app is giving us a fixed size to work with
-	{
-		gint slwantwidth, slwantheight;
-		slwantwidth = slvideo->resize_try_width;
-		slwantheight = slvideo->resize_try_height;
-	
-		if (slwantwidth != width ||
-		    slwantheight != height)
-		{
-			// don't like requested caps, we will issue our own suggestion - copy
-			// the requested caps but substitute our own width and height and see
-			// if our peer is happy with that.
-		
-			GstCaps *desired_caps;
-			GstStructure *desired_struct;
-			desired_caps = llgst_caps_copy (caps);
-			desired_struct = llgst_caps_get_structure (desired_caps, 0);
-			
-			GValue value = {0};
-			g_value_init(&value, G_TYPE_INT);
-			g_value_set_int(&value, slwantwidth);
-			llgst_structure_set_value (desired_struct, "width", &value);
-			g_value_unset(&value);
-			g_value_init(&value, G_TYPE_INT);
-			g_value_set_int(&value, slwantheight);
-			llgst_structure_set_value (desired_struct, "height", &value);
-			
-			if (llgst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (slvideo),
-							desired_caps))
-			{
-				// todo: re-use buffers from a pool?
-				// todo: set MALLOCDATA to null, set DATA to point straight to shm?
-				
-				// peer likes our cap suggestion
-				DEBUGMSG("peer loves us :)");
-				GST_BUFFER_SIZE(newbuf) = slwantwidth * slwantheight * MAXDEPTHHACK;
-				GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf));
-				GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf);
-				llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), desired_caps);
-
-				made_bufferdata_ptr = true;
-			} else {
-				// peer hates our cap suggestion
-				INFOMSG("peer hates us :(");
-				llgst_caps_unref(desired_caps);
-			}
-		}
-	}
-
-	GST_OBJECT_UNLOCK(slvideo);
-
-	if (!made_bufferdata_ptr) // need to fallback to malloc at original size
-	{
-		GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK;
-		GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf));
-		GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf);
-		llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps);
-	}
-
-	*buf = GST_BUFFER_CAST(newbuf);
-
-	return GST_FLOW_OK;
-}
-
-
-/* initialize the plugin's class */
-static void
-gst_slvideo_class_init (GstSLVideoClass * klass)
-{
-	GObjectClass *gobject_class;
-	GstElementClass *gstelement_class;
-	GstBaseSinkClass *gstbasesink_class;
-	
-	gobject_class = (GObjectClass *) klass;
-	gstelement_class = (GstElementClass *) klass;
-	gstbasesink_class = (GstBaseSinkClass *) klass;
-	
-	gobject_class->finalize = gst_slvideo_finalize;
-	gobject_class->set_property = gst_slvideo_set_property;
-	gobject_class->get_property = gst_slvideo_get_property;
-	
-	gstelement_class->change_state = gst_slvideo_change_state;
-	
-#define LLGST_DEBUG_FUNCPTR(p) (p)
-	gstbasesink_class->get_caps = LLGST_DEBUG_FUNCPTR (gst_slvideo_get_caps);
-	gstbasesink_class->set_caps = LLGST_DEBUG_FUNCPTR( gst_slvideo_set_caps);
-	gstbasesink_class->buffer_alloc=LLGST_DEBUG_FUNCPTR(gst_slvideo_buffer_alloc);
-	//gstbasesink_class->get_times = LLGST_DEBUG_FUNCPTR (gst_slvideo_get_times);
-	gstbasesink_class->preroll = LLGST_DEBUG_FUNCPTR (gst_slvideo_show_frame);
-	gstbasesink_class->render = LLGST_DEBUG_FUNCPTR (gst_slvideo_show_frame);
-	
-	gstbasesink_class->start = LLGST_DEBUG_FUNCPTR (gst_slvideo_start);
-	gstbasesink_class->stop = LLGST_DEBUG_FUNCPTR (gst_slvideo_stop);
-	
-	//	gstbasesink_class->unlock = LLGST_DEBUG_FUNCPTR (gst_slvideo_unlock);
-#undef LLGST_DEBUG_FUNCPTR
-}
-
-
-/* initialize the new element
- * instantiate pads and add them to element
- * set functions
- * initialize structure
- */
-static void
-gst_slvideo_init (GstSLVideo * filter,
-		  GstSLVideoClass * gclass)
-{
-	filter->caps = NULL;
-	filter->width = -1;
-	filter->height = -1;
-
-	// this is the info we share with the client app
-	GST_OBJECT_LOCK(filter);
-	filter->retained_frame_ready = FALSE;
-	filter->retained_frame_data = NULL;
-	filter->retained_frame_allocbytes = 0;
-	filter->retained_frame_width = filter->width;
-	filter->retained_frame_height = filter->height;
-	filter->retained_frame_format = SLV_PF_UNKNOWN;
-	GstCaps *caps = llgst_caps_from_string (SLV_ALLCAPS);
-	llgst_caps_replace (&filter->caps, caps);
-	filter->resize_forced_always = false;
-	filter->resize_try_width = -1;
-	filter->resize_try_height = -1;
-	GST_OBJECT_UNLOCK(filter);
-}
-
-static void
-gst_slvideo_set_property (GObject * object, guint prop_id,
-			  const GValue * value, GParamSpec * pspec)
-{
-	llg_return_if_fail (GST_IS_SLVIDEO (object));
-	
-	switch (prop_id) {
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-static void
-gst_slvideo_get_property (GObject * object, guint prop_id,
-			  GValue * value, GParamSpec * pspec)
-{
-	llg_return_if_fail (GST_IS_SLVIDEO (object));
-
-	switch (prop_id) {
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-
-/* entry point to initialize the plug-in
- * initialize the plug-in itself
- * register the element factories and pad templates
- * register the features
- */
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-	DEBUGMSG("PLUGIN INIT");
-
-	GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin",
-				 0, (gchar*)"Second Life Video Sink");
-
-	return llgst_element_register (plugin, "private-slvideo",
-				       GST_RANK_NONE, GST_TYPE_SLVIDEO);
-}
-
-/* this is the structure that gstreamer looks for to register plugins
- */
-/* NOTE: Can't rely upon GST_PLUGIN_DEFINE_STATIC to self-register, since
-   some g++ versions buggily avoid __attribute__((constructor)) functions -
-   so we provide an explicit plugin init function.
- */
-#define PACKAGE (gchar*)"packagehack"
-// this macro quietly refers to PACKAGE internally
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-		   GST_VERSION_MINOR,
-		   (gchar*)"private-slvideoplugin", 
-		   (gchar*)"SL Video sink plugin",
-		   plugin_init, (gchar*)"1.0", (gchar*)"LGPL",
-		   (gchar*)"Second Life",
-		   (gchar*)"http://www.secondlife.com/");
-#undef PACKAGE
-void gst_slvideo_init_class (void)
-{
-	ll_gst_plugin_register_static (&gst_plugin_desc);
-	DEBUGMSG("CLASS INIT");
-}
-
-#endif // LL_GSTREAMER010_ENABLED
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
deleted file mode 100644
index 29d65fa4e9..0000000000
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- * @file llmediaimplgstreamervidplug.h
- * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl
- *
- * @cond
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- * @endcond
- */
-
-#ifndef __GST_SLVIDEO_H__
-#define __GST_SLVIDEO_H__
-
-#if LL_GSTREAMER010_ENABLED
-
-extern "C" {
-#include <gst/gst.h>
-#include <gst/video/video.h>
-#include <gst/video/gstvideosink.h>
-}
-
-G_BEGIN_DECLS
-
-/* #defines don't like whitespacey bits */
-#define GST_TYPE_SLVIDEO \
-  (gst_slvideo_get_type())
-#define GST_SLVIDEO(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SLVIDEO,GstSLVideo))
-#define GST_SLVIDEO_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SLVIDEO,GstSLVideoClass))
-#define GST_IS_SLVIDEO(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SLVIDEO))
-#define GST_IS_SLVIDEO_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SLVIDEO))
-
-typedef struct _GstSLVideo      GstSLVideo;
-typedef struct _GstSLVideoClass GstSLVideoClass;
-
-typedef enum {
-	SLV_PF_UNKNOWN = 0,
-	SLV_PF_RGBX    = 1,
-	SLV_PF_BGRX    = 2,
-	SLV__END       = 3
-} SLVPixelFormat;
-const int SLVPixelFormatBytes[SLV__END] = {1, 4, 4};
-
-struct _GstSLVideo
-{
-	GstVideoSink video_sink;
-
-	GstCaps *caps;
-
-	int fps_n, fps_d;
-	int par_n, par_d;
-	int height, width;
-	SLVPixelFormat format;
-
-	// SHARED WITH APPLICATION:
-	// Access to the following should be protected by GST_OBJECT_LOCK() on
-	// the GstSLVideo object, and should be totally consistent upon UNLOCK
-	// (i.e. all written at once to reflect the current retained frame info
-	// when the retained frame is updated.)
-	bool retained_frame_ready; // new frame ready since flag last reset. (*TODO: could get the writer to wait on a semaphore instead of having the reader poll, potentially making dropped frames somewhat cheaper.)
-	unsigned char*  retained_frame_data;
-	int retained_frame_allocbytes;
-	int retained_frame_width, retained_frame_height;
-	SLVPixelFormat retained_frame_format;
-	// sticky resize info
-	bool resize_forced_always;
-	int resize_try_width;
-	int resize_try_height;
-};
-
-struct _GstSLVideoClass 
-{
-	GstVideoSinkClass parent_class;
-};
-
-GType gst_slvideo_get_type (void);
-
-void gst_slvideo_init_class (void);
-
-G_END_DECLS
-
-#endif // LL_GSTREAMER010_ENABLED
-
-#endif /* __GST_SLVIDEO_H__ */
diff --git a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
deleted file mode 100644
index 352b63583e..0000000000
--- a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
+++ /dev/null
@@ -1,1266 +0,0 @@
-/** 
- * @file media_plugin_gstreamer010.cpp
- * @brief GStreamer-0.10 plugin for LLMedia API plugin system
- *
- * @cond
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- * @endcond
- */
-
-#include "linden_common.h"
-
-#include "llgl.h"
-
-#include "llplugininstance.h"
-#include "llpluginmessage.h"
-#include "llpluginmessageclasses.h"
-#include "media_plugin_base.h"
-
-#if LL_GSTREAMER010_ENABLED
-
-extern "C" {
-#include <gst/gst.h>
-}
-
-#include "llmediaimplgstreamer.h"
-#include "llmediaimplgstreamertriviallogging.h"
-
-#include "llmediaimplgstreamervidplug.h"
-
-#include "llmediaimplgstreamer_syms.h"
-
-//////////////////////////////////////////////////////////////////////////////
-//
-class MediaPluginGStreamer010 : public MediaPluginBase
-{
-public:
-	MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
-	~MediaPluginGStreamer010();
-
-	/* virtual */ void receiveMessage(const char *message_string);
-
-	static bool startup();
-	static bool closedown();
-
-	gboolean processGSTEvents(GstBus     *bus,
-				  GstMessage *message);
-
-private:
-	std::string getVersion();
-	bool navigateTo( const std::string urlIn );
-	bool seek( double time_sec );
-	bool setVolume( float volume );
-	
-	// misc
-	bool pause();
-	bool stop();
-	bool play(double rate);
-	bool getTimePos(double &sec_out);
-
-	static const double MIN_LOOP_SEC = 1.0F;
-
-	bool mIsLooping;
-
-	enum ECommand {
-		COMMAND_NONE,
-		COMMAND_STOP,
-		COMMAND_PLAY,
-		COMMAND_FAST_FORWARD,
-		COMMAND_FAST_REWIND,
-		COMMAND_PAUSE,
-		COMMAND_SEEK,
-	};
-	ECommand mCommand;
-
-private:
-	bool unload();
-	bool load();
-
-	bool update(int milliseconds);
-        void mouseDown( int x, int y );
-        void mouseUp( int x, int y );
-        void mouseMove( int x, int y );
-
-        void sizeChanged();
-	
-	static bool mDoneInit;
-	
-	guint mBusWatchID;
-	
-	float mVolume;
-
-	int mDepth;
-
-	// media NATURAL size
-	int mNaturalWidth;
-	int mNaturalHeight;
-	// media current size
-	int mCurrentWidth;
-	int mCurrentHeight;
-	int mCurrentRowbytes;
-	  // previous media size so we can detect changes
-	  int mPreviousWidth;
-	  int mPreviousHeight;
-	// desired render size from host
-	int mWidth;
-	int mHeight;
-	// padded texture size we need to write into
-	int mTextureWidth;
-	int mTextureHeight;
-	
-	int mTextureFormatPrimary;
-	int mTextureFormatType;
-
-	bool mSeekWanted;
-	double mSeekDestination;
-	
-	// Very GStreamer-specific
-	GMainLoop *mPump; // event pump for this media
-	GstElement *mPlaybin;
-	GstElement *mVisualizer;
-	GstSLVideo *mVideoSink;
-};
-
-//static
-bool MediaPluginGStreamer010::mDoneInit = false;
-
-MediaPluginGStreamer010::MediaPluginGStreamer010(
-	LLPluginInstance::sendMessageFunction host_send_func,
-	void *host_user_data ) :
-	MediaPluginBase(host_send_func, host_user_data),
-	mBusWatchID ( 0 ),
-	mCurrentRowbytes ( 4 ),
-	mTextureFormatPrimary ( GL_RGBA ),
-	mTextureFormatType ( GL_UNSIGNED_INT_8_8_8_8_REV ),
-	mSeekWanted(false),
-	mSeekDestination(0.0),
-	mPump ( NULL ),
-	mPlaybin ( NULL ),
-	mVisualizer ( NULL ),
-	mVideoSink ( NULL ),
-	mCommand ( COMMAND_NONE )
-{
-	std::ostringstream str;
-	INFOMSG("MediaPluginGStreamer010 constructor - my PID=%u", U32(getpid()));
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//
-//#define LL_GST_REPORT_STATE_CHANGES
-#ifdef LL_GST_REPORT_STATE_CHANGES
-static char* get_gst_state_name(GstState state)
-{
-	switch (state) {
-	case GST_STATE_VOID_PENDING: return "VOID_PENDING";
-	case GST_STATE_NULL: return "NULL";
-	case GST_STATE_READY: return "READY";
-	case GST_STATE_PAUSED: return "PAUSED";
-	case GST_STATE_PLAYING: return "PLAYING";
-	}
-	return "(unknown)";
-}
-#endif // LL_GST_REPORT_STATE_CHANGES
-
-gboolean
-MediaPluginGStreamer010::processGSTEvents(GstBus     *bus,
-					  GstMessage *message)
-{
-	if (!message) 
-		return TRUE; // shield against GStreamer bug
-
-	if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_STATE_CHANGED &&
-	    GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING)
-	{
-		DEBUGMSG("Got GST message type: %s",
-			LLGST_MESSAGE_TYPE_NAME (message));
-	}
-	else
-	{
-		// TODO: grok 'duration' message type
-		DEBUGMSG("Got GST message type: %s",
-			 LLGST_MESSAGE_TYPE_NAME (message));
-	}
-
-	switch (GST_MESSAGE_TYPE (message)) {
-	case GST_MESSAGE_BUFFERING: {
-		// NEEDS GST 0.10.11+
-		if (llgst_message_parse_buffering)
-		{
-			gint percent = 0;
-			llgst_message_parse_buffering(message, &percent);
-			DEBUGMSG("GST buffering: %d%%", percent);
-		}
-		break;
-	}
-	case GST_MESSAGE_STATE_CHANGED: {
-		GstState old_state;
-		GstState new_state;
-		GstState pending_state;
-		llgst_message_parse_state_changed(message,
-						&old_state,
-						&new_state,
-						&pending_state);
-#ifdef LL_GST_REPORT_STATE_CHANGES
-		// not generally very useful, and rather spammy.
-		DEBUGMSG("state change (old,<new>,pending): %s,<%s>,%s",
-			 get_gst_state_name(old_state),
-			 get_gst_state_name(new_state),
-			 get_gst_state_name(pending_state));
-#endif // LL_GST_REPORT_STATE_CHANGES
-
-		switch (new_state) {
-		case GST_STATE_VOID_PENDING:
-			break;
-		case GST_STATE_NULL:
-			break;
-		case GST_STATE_READY:
-			setStatus(STATUS_LOADED);
-			break;
-		case GST_STATE_PAUSED:
-			setStatus(STATUS_PAUSED);
-			break;
-		case GST_STATE_PLAYING:
-			setStatus(STATUS_PLAYING);
-			break;
-		}
-		break;
-	}
-	case GST_MESSAGE_ERROR: {
-		GError *err = NULL;
-		gchar *debug = NULL;
-
-		llgst_message_parse_error (message, &err, &debug);
-		WARNMSG("GST error: %s", err?err->message:"(unknown)");
-		if (err)
-			g_error_free (err);
-		g_free (debug);
-
-		mCommand = COMMAND_STOP;
-
-		setStatus(STATUS_ERROR);
-
-		break;
-	}
-	case GST_MESSAGE_INFO: {
-		if (llgst_message_parse_info)
-		{
-			GError *err = NULL;
-			gchar *debug = NULL;
-			
-			llgst_message_parse_info (message, &err, &debug);
-			INFOMSG("GST info: %s", err?err->message:"(unknown)");
-			if (err)
-				g_error_free (err);
-			g_free (debug);
-		}
-		break;
-	}
-	case GST_MESSAGE_WARNING: {
-		GError *err = NULL;
-		gchar *debug = NULL;
-
-		llgst_message_parse_warning (message, &err, &debug);
-		WARNMSG("GST warning: %s", err?err->message:"(unknown)");
-		if (err)
-			g_error_free (err);
-		g_free (debug);
-
-		break;
-	}
-	case GST_MESSAGE_EOS:
-		/* end-of-stream */
-		DEBUGMSG("GST end-of-stream.");
-		if (mIsLooping)
-		{
-			DEBUGMSG("looping media...");
-			double eos_pos_sec = 0.0F;
-			bool got_eos_position = getTimePos(eos_pos_sec);
-
-			if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC)
-			{
-				// if we know that the movie is really short, don't
-				// loop it else it can easily become a time-hog
-				// because of GStreamer spin-up overhead
-				DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec);
-				// inject a COMMAND_PAUSE
-				mCommand = COMMAND_PAUSE;
-			}
-			else
-			{
-#undef LLGST_LOOP_BY_SEEKING
-// loop with a stop-start instead of a seek, because it actually seems rather
-// faster than seeking on remote streams.
-#ifdef LLGST_LOOP_BY_SEEKING
-				// first, try looping by an explicit rewind
-				bool seeksuccess = seek(0.0);
-				if (seeksuccess)
-				{
-					play(1.0);
-				}
-				else
-#endif // LLGST_LOOP_BY_SEEKING
-				{  // use clumsy stop-start to loop
-					DEBUGMSG("didn't loop by rewinding - stopping and starting instead...");
-					stop();
-					play(1.0);
-				}
-			}
-		}
-		else // not a looping media
-		{
-			// inject a COMMAND_STOP
-			mCommand = COMMAND_STOP;
-		}
-		break;
-	default:
-		/* unhandled message */
-		break;
-	}
-
-	/* we want to be notified again the next time there is a message
-	 * on the bus, so return true (false means we want to stop watching
-	 * for messages on the bus and our callback should not be called again)
-	 */
-	return TRUE;
-}
-
-extern "C" {
-gboolean
-llmediaimplgstreamer_bus_callback (GstBus     *bus,
-				   GstMessage *message,
-				   gpointer    data)
-{
-	MediaPluginGStreamer010 *impl = (MediaPluginGStreamer010*)data;
-	return impl->processGSTEvents(bus, message);
-}
-} // extern "C"
-
-
-
-bool
-MediaPluginGStreamer010::navigateTo ( const std::string urlIn )
-{
-	if (!mDoneInit)
-		return false; // error
-
-	setStatus(STATUS_LOADING);
-
-	DEBUGMSG("Setting media URI: %s", urlIn.c_str());
-
-	mSeekWanted = false;
-
-	if (NULL == mPump ||
-	    NULL == mPlaybin)
-	{
-		setStatus(STATUS_ERROR);
-		return false; // error
-	}
-
-	// set URI
-	g_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), NULL);
-	//g_object_set (G_OBJECT (mPlaybin), "uri", "file:///tmp/movie", NULL);
-
-	// navigateTo implicitly plays, too.
-	play(1.0);
-
-	return true;
-}
-
-
-bool
-MediaPluginGStreamer010::update(int milliseconds)
-{
-	if (!mDoneInit)
-		return false; // error
-
-	DEBUGMSG("updating media...");
-	
-	// sanity check
-	if (NULL == mPump ||
-	    NULL == mPlaybin)
-	{
-		DEBUGMSG("dead media...");
-		return false;
-	}
-
-	// see if there's an outstanding seek wanted
-	if (mSeekWanted &&
-	    // bleh, GST has to be happy that the movie is really truly playing
-	    // or it may quietly ignore the seek (with rtsp:// at least).
-	    (GST_STATE(mPlaybin) == GST_STATE_PLAYING))
-	{
-		seek(mSeekDestination);
-		mSeekWanted = false;
-	}
-
-	// *TODO: time-limit - but there isn't a lot we can do here, most
-	// time is spent in gstreamer's own opaque worker-threads.  maybe
-	// we can do something sneaky like only unlock the video object
-	// for 'milliseconds' and otherwise hold the lock.
-	while (g_main_context_pending(g_main_loop_get_context(mPump)))
-	{
-	       g_main_context_iteration(g_main_loop_get_context(mPump), FALSE);
-	}
-
-	// check for availability of a new frame
-	
-	if (mVideoSink)
-	{
-	        GST_OBJECT_LOCK(mVideoSink);
-		if (mVideoSink->retained_frame_ready)
-		{
-			DEBUGMSG("NEW FRAME READY");
-
-			if (mVideoSink->retained_frame_width != mCurrentWidth ||
-			    mVideoSink->retained_frame_height != mCurrentHeight)
-				// *TODO: also check for change in format
-			{
-				// just resize container, don't consume frame
-				int neww = mVideoSink->retained_frame_width;
-				int newh = mVideoSink->retained_frame_height;
-
-				int newd = 4;
-				mTextureFormatPrimary = GL_RGBA;
-				mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV;
-
-				/*
-				int newd = SLVPixelFormatBytes[mVideoSink->retained_frame_format];
-				if (SLV_PF_BGRX == mVideoSink->retained_frame_format)
-				{
-					mTextureFormatPrimary = GL_BGRA;
-					mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV;
-				}
-				else
-				{
-					mTextureFormatPrimary = GL_RGBA;
-					mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV;
-				}
-				*/
-
-				GST_OBJECT_UNLOCK(mVideoSink);
-
-				mCurrentRowbytes = neww * newd;
-				DEBUGMSG("video container resized to %dx%d",
-					 neww, newh);
-
-				mDepth = newd;
-				mCurrentWidth = neww;
-				mCurrentHeight = newh;
-				sizeChanged();
-				return true;
-			}
-
-			if (mPixels &&
-			    mCurrentHeight <= mHeight &&
-			    mCurrentWidth <= mWidth &&
-			    !mTextureSegmentName.empty())
-			{
-				// we're gonna totally consume this frame - reset 'ready' flag
-				mVideoSink->retained_frame_ready = FALSE;
-				int destination_rowbytes = mWidth * mDepth;
-				for (int row=0; row<mCurrentHeight; ++row)
-				{
-					memcpy(&mPixels
-					        [destination_rowbytes * row],
-					       &mVideoSink->retained_frame_data
-					        [mCurrentRowbytes * row],
-					       mCurrentRowbytes);
-				}
-
-				GST_OBJECT_UNLOCK(mVideoSink);
-				DEBUGMSG("NEW FRAME REALLY TRULY CONSUMED, TELLING HOST");
-
-				setDirty(0,0,mCurrentWidth,mCurrentHeight);
-			}
-			else
-			{
-				// new frame ready, but we're not ready to
-				// consume it.
-
-				GST_OBJECT_UNLOCK(mVideoSink);
-
-				DEBUGMSG("NEW FRAME not consumed, still waiting for a shm segment and/or shm resize");
-			}
-
-			return true;
-		}
-		else
-		{
-			// nothing to do yet.
-			GST_OBJECT_UNLOCK(mVideoSink);
-			return true;
-		}
-	}
-
-	return true;
-}
-
-
-void
-MediaPluginGStreamer010::mouseDown( int x, int y )
-{
-  // do nothing
-}
-
-void
-MediaPluginGStreamer010::mouseUp( int x, int y )
-{
-  // do nothing
-}
-
-void
-MediaPluginGStreamer010::mouseMove( int x, int y )
-{
-  // do nothing
-}
-
-
-bool
-MediaPluginGStreamer010::pause()
-{
-	DEBUGMSG("pausing media...");
-	// todo: error-check this?
-	if (mDoneInit && mPlaybin)
-	{
-		llgst_element_set_state(mPlaybin, GST_STATE_PAUSED);
-		return true;
-	}
-	return false;
-}
-
-bool
-MediaPluginGStreamer010::stop()
-{
-	DEBUGMSG("stopping media...");
-	// todo: error-check this?
-	if (mDoneInit && mPlaybin)
-	{
-		llgst_element_set_state(mPlaybin, GST_STATE_READY);
-		return true;
-	}
-	return false;
-}
-
-bool
-MediaPluginGStreamer010::play(double rate)
-{
-	// NOTE: we don't actually support non-natural rate.
-
-        DEBUGMSG("playing media... rate=%f", rate);
-	// todo: error-check this?
-	if (mDoneInit && mPlaybin)
-	{
-		llgst_element_set_state(mPlaybin, GST_STATE_PLAYING);
-		return true;
-	}
-	return false;
-}
-
-bool
-MediaPluginGStreamer010::setVolume( float volume )
-{
-	// we try to only update volume as conservatively as
-	// possible, as many gst-plugins-base versions up to at least
-	// November 2008 have critical race-conditions in setting volume - sigh
-	if (mVolume == volume)
-		return true; // nothing to do, everything's fine
-
-	mVolume = volume;
-	if (mDoneInit && mPlaybin)
-	{
-		g_object_set(mPlaybin, "volume", mVolume, NULL);
-		return true;
-	}
-
-	return false;
-}
-
-bool
-MediaPluginGStreamer010::seek(double time_sec)
-{
-	bool success = false;
-	if (mDoneInit && mPlaybin)
-	{
-		success = llgst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME,
-				GstSeekFlags(GST_SEEK_FLAG_FLUSH |
-					     GST_SEEK_FLAG_KEY_UNIT),
-				GST_SEEK_TYPE_SET, gint64(time_sec*GST_SECOND),
-				GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
-	}
-	DEBUGMSG("MEDIA SEEK REQUEST to %fsec result was %d",
-		 float(time_sec), int(success));
-	return success;
-}
-
-bool
-MediaPluginGStreamer010::getTimePos(double &sec_out)
-{
-	bool got_position = false;
-	if (mDoneInit && mPlaybin)
-	{
-		gint64 pos;
-		GstFormat timefmt = GST_FORMAT_TIME;
-		got_position =
-			llgst_element_query_position &&
-			llgst_element_query_position(mPlaybin,
-						     &timefmt,
-						     &pos);
-		got_position = got_position
-			&& (timefmt == GST_FORMAT_TIME);
-		// GStreamer may have other ideas, but we consider the current position
-		// undefined if not PLAYING or PAUSED
-		got_position = got_position &&
-			(GST_STATE(mPlaybin) == GST_STATE_PLAYING ||
-			 GST_STATE(mPlaybin) == GST_STATE_PAUSED);
-		if (got_position && !GST_CLOCK_TIME_IS_VALID(pos))
-		{
-			if (GST_STATE(mPlaybin) == GST_STATE_PLAYING)
-			{
-				// if we're playing then we treat an invalid clock time
-				// as 0, for complicated reasons (insert reason here)
-				pos = 0;
-			}
-			else
-			{
-				got_position = false;
-			}
-			
-		}
-		// If all the preconditions succeeded... we can trust the result.
-		if (got_position)
-		{
-			sec_out = double(pos) / double(GST_SECOND); // gst to sec
-		}
-	}
-	return got_position;
-}
-
-bool
-MediaPluginGStreamer010::load()
-{
-	if (!mDoneInit)
-		return false; // error
-
-	setStatus(STATUS_LOADING);
-
-	DEBUGMSG("setting up media...");
-
-	mIsLooping = false;
-	mVolume = 0.1234567; // minor hack to force an initial volume update
-
-	// Create a pumpable main-loop for this media
-	mPump = g_main_loop_new (NULL, FALSE);
-	if (!mPump)
-	{
-		setStatus(STATUS_ERROR);
-		return false; // error
-	}
-
-	// instantiate a playbin element to do the hard work
-	mPlaybin = llgst_element_factory_make ("playbin", "play");
-	if (!mPlaybin)
-	{
-		setStatus(STATUS_ERROR);
-		return false; // error
-	}
-
-	// get playbin's bus
-	GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin));
-	if (!bus)
-	{
-		setStatus(STATUS_ERROR);
-		return false; // error
-	}
-	mBusWatchID = llgst_bus_add_watch (bus,
-					   llmediaimplgstreamer_bus_callback,
-					   this);
-	llgst_object_unref (bus);
-
-#if 0 // not quite stable/correct yet
-	// get a visualizer element (bonus feature!)
-	char* vis_name = getenv("LL_GST_VIS_NAME");
-	if (!vis_name ||
-	    (vis_name && std::string(vis_name)!="none"))
-	{
-		if (vis_name)
-		{
-			mVisualizer = llgst_element_factory_make (vis_name, "vis");
-		}
-		if (!mVisualizer)
-		{
-			mVisualizer = llgst_element_factory_make ("libvisual_jess", "vis");
-			if (!mVisualizer)
-			{
-				mVisualizer = llgst_element_factory_make ("goom", "vis");
-				if (!mVisualizer)
-				{
-					mVisualizer = llgst_element_factory_make ("libvisual_lv_scope", "vis");
-					if (!mVisualizer)
-					{
-						// That's okay, we don't NEED this.
-					}
-				}
-			}
-		}
-	}
-#endif
-
-	if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) {
-		// instantiate a custom video sink
-		mVideoSink =
-			GST_SLVIDEO(llgst_element_factory_make ("private-slvideo", "slvideo"));
-		if (!mVideoSink)
-		{
-			WARNMSG("Could not instantiate private-slvideo element.");
-			// todo: cleanup.
-			setStatus(STATUS_ERROR);
-			return false; // error
-		}
-
-		// connect the pieces
-		g_object_set(mPlaybin, "video-sink", mVideoSink, NULL);
-	}
-
-	if (mVisualizer)
-	{
-		g_object_set(mPlaybin, "vis-plugin", mVisualizer, NULL);
-	}
-
-	return true;
-}
-
-bool
-MediaPluginGStreamer010::unload ()
-{
-	if (!mDoneInit)
-		return false; // error
-
-	DEBUGMSG("unloading media...");
-	
-	// stop getting callbacks for this bus
-	g_source_remove(mBusWatchID);
-	mBusWatchID = 0;
-
-	if (mPlaybin)
-	{
-		llgst_element_set_state (mPlaybin, GST_STATE_NULL);
-		llgst_object_unref (GST_OBJECT (mPlaybin));
-		mPlaybin = NULL;
-	}
-
-	if (mVisualizer)
-	{
-		llgst_object_unref (GST_OBJECT (mVisualizer));
-		mVisualizer = NULL;
-	}
-
-	if (mPump)
-	{
-		g_main_loop_quit(mPump);
-		mPump = NULL;
-	}
-
-	mVideoSink = NULL;
-
-	setStatus(STATUS_NONE);
-
-	return true;
-}
-
-
-//static
-bool
-MediaPluginGStreamer010::startup()
-{
-	// first - check if GStreamer is explicitly disabled
-	if (NULL != getenv("LL_DISABLE_GSTREAMER"))
-		return false;
-
-	// only do global GStreamer initialization once.
-	if (!mDoneInit)
-	{
-		g_thread_init(NULL);
-
-		// Init the glib type system - we need it.
-		g_type_init();
-
-		// Get symbols!
-#if LL_DARWIN
-		if (! grab_gst_syms("libgstreamer-0.10.dylib",
-				    "libgstvideo-0.10.dylib") )
-#elseif LL_WINDOWS
-		if (! grab_gst_syms("libgstreamer-0.10.dll",
-				    "libgstvideo-0.10.dll") )
-#else // linux or other ELFy unixoid
-		if (! grab_gst_syms("libgstreamer-0.10.so.0",
-				    "libgstvideo-0.10.so.0") )
-#endif
-		{
-			WARNMSG("Couldn't find suitable GStreamer 0.10 support on this system - video playback disabled.");
-			return false;
-		}
-
-		if (llgst_segtrap_set_enabled)
-		{
-			llgst_segtrap_set_enabled(FALSE);
-		}
-		else
-		{
-			WARNMSG("gst_segtrap_set_enabled() is not available; plugin crashes won't be caught.");
-		}
-
-#if LL_LINUX
-		// Gstreamer tries a fork during init, waitpid-ing on it,
-		// which conflicts with any installed SIGCHLD handler...
-		struct sigaction tmpact, oldact;
-		if (llgst_registry_fork_set_enabled) {
-			// if we can disable SIGCHLD-using forking behaviour,
-			// do it.
-			llgst_registry_fork_set_enabled(false);
-		}
-		else {
-			// else temporarily install default SIGCHLD handler
-			// while GStreamer initialises
-			tmpact.sa_handler = SIG_DFL;
-			sigemptyset( &tmpact.sa_mask );
-			tmpact.sa_flags = SA_SIGINFO;
-			sigaction(SIGCHLD, &tmpact, &oldact);
-		}
-#endif // LL_LINUX
-
-		// Protect against GStreamer resetting the locale, yuck.
-		static std::string saved_locale;
-		saved_locale = setlocale(LC_ALL, NULL);
-
-		// finally, try to initialize GStreamer!
-		GError *err = NULL;
-		gboolean init_gst_success = llgst_init_check(NULL, NULL, &err);
-
-		// restore old locale
-		setlocale(LC_ALL, saved_locale.c_str() );
-
-#if LL_LINUX
-		// restore old SIGCHLD handler
-		if (!llgst_registry_fork_set_enabled)
-			sigaction(SIGCHLD, &oldact, NULL);
-#endif // LL_LINUX
-
-		if (!init_gst_success) // fail
-		{
-			if (err)
-			{
-				WARNMSG("GST init failed: %s", err->message);
-				g_error_free(err);
-			}
-			else
-			{
-				WARNMSG("GST init failed for unspecified reason.");
-			}
-			return false;
-		}
-		
-		// Init our custom plugins - only really need do this once.
-		gst_slvideo_init_class();
-
-		mDoneInit = true;
-	}
-
-	return true;
-}
-
-
-void
-MediaPluginGStreamer010::sizeChanged()
-{
-	// the shared writing space has possibly changed size/location/whatever
-
-	// Check to see whether the movie's NATURAL size has been set yet
-	if (1 == mNaturalWidth &&
-	    1 == mNaturalHeight)
-	{
-		mNaturalWidth = mCurrentWidth;
-		mNaturalHeight = mCurrentHeight;
-		DEBUGMSG("Media NATURAL size better detected as %dx%d",
-			 mNaturalWidth, mNaturalHeight);
-	}
-
-	// if the size has changed then the shm has changed and the app needs telling
-	if (mCurrentWidth != mPreviousWidth ||
-	    mCurrentHeight != mPreviousHeight)
-	{
-		mPreviousWidth = mCurrentWidth;
-		mPreviousHeight = mCurrentHeight;
-
-		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request");
-		message.setValue("name", mTextureSegmentName);
-		message.setValueS32("width", mNaturalWidth);
-		message.setValueS32("height", mNaturalHeight);
-		DEBUGMSG("<--- Sending size change request to application with name: '%s' - natural size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight);
-		sendMessage(message);
-	}
-}
-
-
-
-//static
-bool
-MediaPluginGStreamer010::closedown()
-{
-	if (!mDoneInit)
-		return false; // error
-
-	ungrab_gst_syms();
-
-	mDoneInit = false;
-
-	return true;
-}
-
-MediaPluginGStreamer010::~MediaPluginGStreamer010()
-{
-	DEBUGMSG("MediaPluginGStreamer010 destructor");
-
-	closedown();
-
-	DEBUGMSG("GStreamer010 closing down");
-}
-
-
-std::string
-MediaPluginGStreamer010::getVersion()
-{
-	std::string plugin_version = "GStreamer010 media plugin, GStreamer version ";
-	if (mDoneInit &&
-	    llgst_version)
-	{
-		guint major, minor, micro, nano;
-		llgst_version(&major, &minor, &micro, &nano);
-		plugin_version += llformat("%u.%u.%u.%u (runtime), %u.%u.%u.%u (headers)", (unsigned int)major, (unsigned int)minor, (unsigned int)micro, (unsigned int)nano, (unsigned int)GST_VERSION_MAJOR, (unsigned int)GST_VERSION_MINOR, (unsigned int)GST_VERSION_MICRO, (unsigned int)GST_VERSION_NANO);
-	}
-	else
-	{
-		plugin_version += "(unknown)";
-	}
-	return plugin_version;
-}
-
-void MediaPluginGStreamer010::receiveMessage(const char *message_string)
-{
-	//std::cerr << "MediaPluginGStreamer010::receiveMessage: received message: \"" << message_string << "\"" << std::endl;
-
-	LLPluginMessage message_in;
-
-	if(message_in.parse(message_string) >= 0)
-	{
-		std::string message_class = message_in.getClass();
-		std::string message_name = message_in.getName();
-		if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
-		{
-			if(message_name == "init")
-			{
-				LLPluginMessage message("base", "init_response");
-				LLSD versions = LLSD::emptyMap();
-				versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
-				versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
-				versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
-				message.setValueLLSD("versions", versions);
-
-				if ( load() )
-				{
-					DEBUGMSG("GStreamer010 media instance set up");
-				}
-				else
-				{
-					WARNMSG("GStreamer010 media instance failed to set up");
-				}
-
-				message.setValue("plugin_version", getVersion());
-				sendMessage(message);
-			}
-			else if(message_name == "idle")
-			{
-				// no response is necessary here.
-				double time = message_in.getValueReal("time");
-				
-				// Convert time to milliseconds for update()
-				update((int)(time * 1000.0f));
-			}
-			else if(message_name == "cleanup")
-			{
-				unload();
-				closedown();
-			}
-			else if(message_name == "shm_added")
-			{
-				SharedSegmentInfo info;
-				info.mAddress = message_in.getValuePointer("address");
-				info.mSize = (size_t)message_in.getValueS32("size");
-				std::string name = message_in.getValue("name");
-
-				std::ostringstream str;
-				INFOMSG("MediaPluginGStreamer010::receiveMessage: shared memory added, name: %s, size: %d, address: %p", name.c_str(), int(info.mSize), info.mAddress);
-
-				mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
-			}
-			else if(message_name == "shm_remove")
-			{
-				std::string name = message_in.getValue("name");
-
-				DEBUGMSG("MediaPluginGStreamer010::receiveMessage: shared memory remove, name = %s", name.c_str());
-				
-				SharedSegmentMap::iterator iter = mSharedSegments.find(name);
-				if(iter != mSharedSegments.end())
-				{
-					if(mPixels == iter->second.mAddress)
-					{
-						// This is the currently active pixel buffer.  Make sure we stop drawing to it.
-						mPixels = NULL;
-						mTextureSegmentName.clear();
-						
-						// Make sure the movie decoder is no longer pointed at the shared segment.
-						sizeChanged();						
-					}
-					mSharedSegments.erase(iter);
-				}
-				else
-				{
-					WARNMSG("MediaPluginGStreamer010::receiveMessage: unknown shared memory region!");
-				}
-
-				// Send the response so it can be cleaned up.
-				LLPluginMessage message("base", "shm_remove_response");
-				message.setValue("name", name);
-				sendMessage(message);
-			}
-			else
-			{
-				std::ostringstream str;
-				INFOMSG("MediaPluginGStreamer010::receiveMessage: unknown base message: %s", message_name.c_str());
-			}
-		}
-		else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
-		{
-			if(message_name == "init")
-			{
-				// Plugin gets to decide the texture parameters to use.
-				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
-				// lame to have to decide this now, it depends on the movie.  Oh well.
-				mDepth = 4;
-
-				mCurrentWidth = 1;
-				mCurrentHeight = 1;
-				mPreviousWidth = 1;
-				mPreviousHeight = 1;
-				mNaturalWidth = 1;
-				mNaturalHeight = 1;
-				mWidth = 1;
-				mHeight = 1;
-				mTextureWidth = 1;
-				mTextureHeight = 1;
-
-				message.setValueU32("format", GL_RGBA);
-				message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV);
-
-				message.setValueS32("depth", mDepth);
-				message.setValueS32("default_width", mWidth);
-				message.setValueS32("default_height", mHeight);
-				message.setValueU32("internalformat", GL_RGBA8);
-				message.setValueBoolean("coords_opengl", true);	// true == use OpenGL-style coordinates, false == (0,0) is upper left.
-				message.setValueBoolean("allow_downsample", true); // we respond with grace and performance if asked to downscale
-				sendMessage(message);
-			}
-			else if(message_name == "size_change")
-			{
-				std::string name = message_in.getValue("name");
-				S32 width = message_in.getValueS32("width");
-				S32 height = message_in.getValueS32("height");
-				S32 texture_width = message_in.getValueS32("texture_width");
-				S32 texture_height = message_in.getValueS32("texture_height");
-
-				std::ostringstream str;
-				INFOMSG("---->Got size change instruction from application with shm name: %s - size is %d x %d", name.c_str(), width, height);
-
-				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
-				message.setValue("name", name);
-				message.setValueS32("width", width);
-				message.setValueS32("height", height);
-				message.setValueS32("texture_width", texture_width);
-				message.setValueS32("texture_height", texture_height);
-				sendMessage(message);
-
-				if(!name.empty())
-				{
-					// Find the shared memory region with this name
-					SharedSegmentMap::iterator iter = mSharedSegments.find(name);
-					if(iter != mSharedSegments.end())
-					{
-						INFOMSG("*** Got size change with matching shm, new size is %d x %d", width, height);
-						INFOMSG("*** Got size change with matching shm, texture size size is %d x %d", texture_width, texture_height);
-
-						mPixels = (unsigned char*)iter->second.mAddress;
-						mTextureSegmentName = name;
-						mWidth = width;
-						mHeight = height;
-
-						if (texture_width > 1 ||
-						    texture_height > 1) // not a dummy size from the app, a real explicit forced size
-						{
-							INFOMSG("**** = REAL RESIZE REQUEST FROM APP");
-							
-							GST_OBJECT_LOCK(mVideoSink);
-							mVideoSink->resize_forced_always = true;
-							mVideoSink->resize_try_width = texture_width;
-							mVideoSink->resize_try_height = texture_height;
-							GST_OBJECT_UNLOCK(mVideoSink);
- 						}
-
-						mTextureWidth = texture_width;
-						mTextureHeight = texture_height;
-					}
-				}
-			}
-			else if(message_name == "load_uri")
-			{
-				std::string uri = message_in.getValue("uri");
-				navigateTo( uri );
-				sendStatus();		
-			}
-			else if(message_name == "mouse_event")
-			{
-				std::string event = message_in.getValue("event");
-				S32 x = message_in.getValueS32("x");
-				S32 y = message_in.getValueS32("y");
-				
-				if(event == "down")
-				{
-					mouseDown(x, y);
-				}
-				else if(event == "up")
-				{
-					mouseUp(x, y);
-				}
-				else if(event == "move")
-				{
-					mouseMove(x, y);
-				};
-			};
-		}
-		else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
-		{
-			if(message_name == "stop")
-			{
-				stop();
-			}
-			else if(message_name == "start")
-			{
-				double rate = 0.0;
-				if(message_in.hasValue("rate"))
-				{
-					rate = message_in.getValueReal("rate");
-				}
-				// NOTE: we don't actually support rate.
-				play(rate);
-			}
-			else if(message_name == "pause")
-			{
-				pause();
-			}
-			else if(message_name == "seek")
-			{
-				double time = message_in.getValueReal("time");
-				// defer the actual seek in case we haven't
-				// really truly started yet in which case there
-				// is nothing to seek upon
-				mSeekWanted = true;
-				mSeekDestination = time;
-			}
-			else if(message_name == "set_loop")
-			{
-				bool loop = message_in.getValueBoolean("loop");
-				mIsLooping = loop;
-			}
-			else if(message_name == "set_volume")
-			{
-				double volume = message_in.getValueReal("volume");
-				setVolume(volume);
-			}
-		}
-		else
-		{
-			INFOMSG("MediaPluginGStreamer010::receiveMessage: unknown message class: %s", message_class.c_str());
-		}
-	}
-}
-
-int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
-{
-	if (MediaPluginGStreamer010::startup())
-	{
-		MediaPluginGStreamer010 *self = new MediaPluginGStreamer010(host_send_func, host_user_data);
-		*plugin_send_func = MediaPluginGStreamer010::staticReceiveMessage;
-		*plugin_user_data = (void*)self;
-		
-		return 0; // okay
-	}
-	else 
-	{
-		return -1; // failed to init
-	}
-}
-
-#else // LL_GSTREAMER010_ENABLED
-
-// Stubbed-out class with constructor/destructor (necessary or windows linker
-// will just think its dead code and optimize it all out)
-class MediaPluginGStreamer010 : public MediaPluginBase
-{
-public:
-	MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
-	~MediaPluginGStreamer010();
-	/* virtual */ void receiveMessage(const char *message_string);
-};
-
-MediaPluginGStreamer010::MediaPluginGStreamer010(
-	LLPluginInstance::sendMessageFunction host_send_func,
-	void *host_user_data ) :
-	MediaPluginBase(host_send_func, host_user_data)
-{
-    // no-op
-}
-
-MediaPluginGStreamer010::~MediaPluginGStreamer010()
-{
-    // no-op
-}
-
-void MediaPluginGStreamer010::receiveMessage(const char *message_string)
-{
-    // no-op 
-}
-
-// We're building without GStreamer enabled.  Just refuse to initialize.
-int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
-{
-    return -1;
-}
-
-#endif // LL_GSTREAMER010_ENABLED
diff --git a/indra/media_plugins/gstreamer10/CMakeLists.txt b/indra/media_plugins/gstreamer10/CMakeLists.txt
index ffa3c30519..14ce5bfaa1 100644
--- a/indra/media_plugins/gstreamer10/CMakeLists.txt
+++ b/indra/media_plugins/gstreamer10/CMakeLists.txt
@@ -16,13 +16,8 @@ include(GStreamer10Plugin)
 
 ### media_plugin_gstreamer10
 
-if(NOT WINDOWS) # not windows therefore gcc LINUX and DARWIN
-add_definitions(-fPIC)
-endif()
-
 set(media_plugin_gstreamer10_SOURCE_FILES
     media_plugin_gstreamer10.cpp
-    llmediaimplgstreamer_syms.cpp
     )
 
 set(media_plugin_gstreamer10_HEADER_FILES
diff --git a/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms.cpp b/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms.cpp
deleted file mode 100644
index e5e5c1c9a3..0000000000
--- a/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-/** 
- * @file llmediaimplgstreamer_syms.cpp
- * @brief dynamic GStreamer symbol-grabbing code
- *
- * @cond
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- * @endcond
- */
-
-#include <string>
-#include <iostream>
-#include <vector>
-
-#ifdef LL_WINDOWS
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0502
-#include <Windows.h>
-#endif
-
-#include "linden_common.h"
-
-extern "C" {
-#include <gst/gst.h>
-#include <gst/app/gstappsink.h>
-}
-
-#include "apr_pools.h"
-#include "apr_dso.h"
-
-#ifdef LL_WINDOWS
-
-#ifndef _M_AMD64
-#define GSTREAMER_REG_KEY "Software\\GStreamer1.0\\x86"
-#define GSTREAMER_DIR_SUFFIX "1.0\\x86\\bin\\"
-#else
-#define GSTREAMER_REG_KEY "Software\\GStreamer1.0\\x86_64"
-#define GSTREAMER_DIR_SUFFIX "1.0\\x86_64\\bin\\"
-#endif
-
-bool openRegKey( HKEY &aKey )
-{
-	// Try native (32 bit view/64 bit view) of registry first.
-	if( ERROR_SUCCESS == ::RegOpenKeyExA( HKEY_LOCAL_MACHINE, GSTREAMER_REG_KEY, 0, KEY_QUERY_VALUE, &aKey ) )
-		return true;
-
-	// If native view fails, use 32 bit view or registry.
-	if( ERROR_SUCCESS == ::RegOpenKeyExA( HKEY_LOCAL_MACHINE, GSTREAMER_REG_KEY, 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &aKey ) )
-		return true;
-
-	return false;
-}
-
-std::string getGStreamerDir()
-{
-	std::string ret;
-	HKEY hKey;
-
-	if( openRegKey( hKey ) )
-	{
-		DWORD dwLen(0);
-		::RegQueryValueExA( hKey, "InstallDir", nullptr, nullptr, nullptr, &dwLen );
-
-		if( dwLen > 0 )
-		{
-			std::vector< char > vctBuffer;
-			vctBuffer.resize( dwLen );
-			::RegQueryValueExA( hKey, "InstallDir", nullptr, nullptr, reinterpret_cast< LPBYTE>(&vctBuffer[ 0 ]), &dwLen );
-			ret = &vctBuffer[0];
-
-			if( ret[ dwLen-1 ] != '\\' )
-				ret += "\\";
-			ret += GSTREAMER_DIR_SUFFIX;
-
-			SetDllDirectoryA( ret.c_str() );
-		}
-		::RegCloseKey( hKey );
-	}
-	return ret;
-}
-#else
-std::string getGStreamerDir() { return ""; }
-#endif
-
-#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) RTN (*ll##GSTSYM)(__VA_ARGS__) = NULL;
-#include "llmediaimplgstreamer_syms_raw.inc"
-#undef LL_GST_SYM
-
-struct Symloader
-{
-	bool mRequired;
-	char const *mName;
-	apr_dso_handle_sym_t *mPPFunc;
-};
-
-#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) { REQ, #GSTSYM , (apr_dso_handle_sym_t*)&ll##GSTSYM}, 
-Symloader sSyms[] = {
-#include "llmediaimplgstreamer_syms_raw.inc"
-{ false, 0, 0 } };
-#undef LL_GST_SYM
-
-// a couple of stubs for disgusting reasons
-GstDebugCategory*
-ll_gst_debug_category_new(gchar *name, guint color, gchar *description)
-{
-	static GstDebugCategory dummy;
-	return &dummy;
-}
-void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname)
-{
-}
-
-static bool sSymsGrabbed = false;
-static apr_pool_t *sSymGSTDSOMemoryPool = NULL;
-
-std::vector< apr_dso_handle_t* > sLoadedLibraries;
-
-bool grab_gst_syms( std::vector< std::string > const &aDSONames )
-{
-	if (sSymsGrabbed)
-		return true;
-
-	//attempt to load the shared libraries
-	apr_pool_create(&sSymGSTDSOMemoryPool, NULL);
-  
-	for( std::vector< std::string >::const_iterator itr = aDSONames.begin(); itr != aDSONames.end(); ++itr )
-	{
-		apr_dso_handle_t *pDSO(NULL);
-		std::string strDSO = getGStreamerDir() + *itr;
-		if( APR_SUCCESS == apr_dso_load( &pDSO, strDSO.c_str(), sSymGSTDSOMemoryPool ))
-			sLoadedLibraries.push_back( pDSO );
-		
-		for( int i = 0; sSyms[ i ].mName; ++i )
-		{
-			if( !*sSyms[ i ].mPPFunc )
-			{
-				apr_dso_sym( sSyms[ i ].mPPFunc, pDSO, sSyms[ i ].mName );
-			}
-		}
-	}
-
-	std::stringstream strm;
-	bool sym_error = false;
-	for( int i = 0; sSyms[ i ].mName; ++i )
-	{
-		if( sSyms[ i ].mRequired && ! *sSyms[ i ].mPPFunc )
-		{
-			sym_error = true;
-			strm << sSyms[ i ].mName << std::endl;
-		}
-	}
-
-	sSymsGrabbed = !sym_error;
-	return sSymsGrabbed;
-}
-
-
-void ungrab_gst_syms()
-{ 
-	// should be safe to call regardless of whether we've
-	// actually grabbed syms.
-
-	for( std::vector< apr_dso_handle_t* >::iterator itr = sLoadedLibraries.begin(); itr != sLoadedLibraries.end(); ++itr )
-		apr_dso_unload( *itr );
-
-	sLoadedLibraries.clear();
-
-	if ( sSymGSTDSOMemoryPool )
-	{
-		apr_pool_destroy(sSymGSTDSOMemoryPool);
-		sSymGSTDSOMemoryPool = NULL;
-	}
-
-	for( int i = 0; sSyms[ i ].mName; ++i )
-		*sSyms[ i ].mPPFunc = NULL;
-
-	sSymsGrabbed = false;
-}
-
diff --git a/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms.h b/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms.h
deleted file mode 100644
index 0874644ee6..0000000000
--- a/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/** 
- * @file llmediaimplgstreamer_syms.h
- * @brief dynamic GStreamer symbol-grabbing code
- *
- * @cond
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- * @endcond
- */
-
-#include "linden_common.h"
-#include <vector>
-extern "C" {
-#include <gst/gst.h>
-}
-
-bool grab_gst_syms( std::vector< std::string > const&);
-void ungrab_gst_syms();
-
-#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) extern RTN (*ll##GSTSYM)(__VA_ARGS__);
-#include "llmediaimplgstreamer_syms_raw.inc"
-#undef LL_GST_SYM
-
-// regrettable hacks to give us better runtime compatibility with older systems
-#define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0)
-#define llg_return_val_if_fail(COND,V) do{if (!(COND)) return V;}while(0)
-
-// regrettable hacks because GStreamer was not designed for runtime loading
-#undef GST_TYPE_MESSAGE
-#define GST_TYPE_MESSAGE (llgst_message_get_type())
-#undef GST_TYPE_OBJECT
-#define GST_TYPE_OBJECT (llgst_object_get_type())
-#undef GST_TYPE_PIPELINE
-#define GST_TYPE_PIPELINE (llgst_pipeline_get_type())
-#undef GST_TYPE_ELEMENT
-#define GST_TYPE_ELEMENT (llgst_element_get_type())
-#undef GST_TYPE_VIDEO_SINK
-#define GST_TYPE_VIDEO_SINK (llgst_video_sink_get_type())
-// more regrettable hacks to stub-out these .h-exposed GStreamer internals
-void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname);
-#undef _gst_debug_register_funcptr
-#define _gst_debug_register_funcptr ll_gst_debug_register_funcptr
-GstDebugCategory* ll_gst_debug_category_new(gchar *name, guint color, gchar *description);
-#undef _gst_debug_category_new
-#define _gst_debug_category_new ll_gst_debug_category_new
-#undef __gst_debug_enabled
-#define __gst_debug_enabled (0)
-
-// more hacks
-#define LLGST_MESSAGE_TYPE_NAME(M) (llgst_message_type_get_name(GST_MESSAGE_TYPE(M)))
diff --git a/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms_raw.inc b/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms_raw.inc
index 155eeb6809..e5abf22203 100644
--- a/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms_raw.inc
+++ b/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms_raw.inc
@@ -1,68 +1,67 @@
-LL_GST_SYM(true, gst_buffer_new, GstBuffer*, void)
-LL_GST_SYM(true, gst_structure_set_value, void, GstStructure *, const gchar *, const GValue*)
-LL_GST_SYM(true, gst_init_check, gboolean, int *argc, char **argv[], GError ** err)
-LL_GST_SYM(true, gst_message_get_type, GType, void)
-LL_GST_SYM(true, gst_message_type_get_name, const gchar*, GstMessageType type)
-LL_GST_SYM(true, gst_message_parse_error, void, GstMessage *message, GError **gerror, gchar **debug)
-LL_GST_SYM(true, gst_message_parse_warning, void, GstMessage *message, GError **gerror, gchar **debug)
-LL_GST_SYM(true, gst_message_parse_state_changed, void, GstMessage *message, GstState *oldstate, GstState *newstate, GstState *pending)
-LL_GST_SYM(true, gst_element_set_state, GstStateChangeReturn, GstElement *element, GstState state)
-LL_GST_SYM(true, gst_object_unref, void, gpointer object)
-LL_GST_SYM(true, gst_object_get_type, GType, void)
-LL_GST_SYM(true, gst_pipeline_get_type, GType, void)
-LL_GST_SYM(true, gst_pipeline_get_bus, GstBus*, GstPipeline *pipeline)
-LL_GST_SYM(true, gst_bus_add_watch, guint, GstBus * bus, GstBusFunc func, gpointer user_data)
-LL_GST_SYM(true, gst_element_factory_make, GstElement*, const gchar *factoryname, const gchar *name)
-LL_GST_SYM(true, gst_element_get_type, GType, void)
-LL_GST_SYM(true, gst_static_pad_template_get, GstPadTemplate*, GstStaticPadTemplate *pad_template)
-LL_GST_SYM(true, gst_element_class_add_pad_template, void, GstElementClass *klass, GstPadTemplate *temp)
-LL_GST_SYM(true, gst_caps_from_string, GstCaps *, const gchar *string)
-LL_GST_SYM(true, gst_caps_get_structure, GstStructure *, const GstCaps *caps, guint index)
-LL_GST_SYM(true, gst_element_register, gboolean, GstPlugin *plugin, const gchar *name, guint rank, GType type)
-LL_GST_SYM(true, gst_structure_get_int, gboolean, const GstStructure *structure, const gchar *fieldname, gint *value)
-LL_GST_SYM(true, gst_structure_get_value, const GValue *, const GstStructure *structure, const gchar *fieldname)
-LL_GST_SYM(true, gst_value_get_fraction_numerator, gint, const GValue *value)
-LL_GST_SYM(true, gst_value_get_fraction_denominator, gint, const GValue *value)
-LL_GST_SYM(true, gst_structure_get_name, const gchar *, const GstStructure *structure)
-LL_GST_SYM(true, gst_element_seek, bool, GstElement *, gdouble, GstFormat, GstSeekFlags, GstSeekType, gint64, GstSeekType, gint64)
+LL_GRAB_SYM(true, gst_buffer_new, GstBuffer*, void)
+LL_GRAB_SYM(true, gst_structure_set_value, void, GstStructure *, const gchar *, const GValue*)
+LL_GRAB_SYM(true, gst_init_check, gboolean, int *argc, char **argv[], GError ** err)
+LL_GRAB_SYM(true, gst_message_get_type, GType, void)
+LL_GRAB_SYM(true, gst_message_type_get_name, const gchar*, GstMessageType type)
+LL_GRAB_SYM(true, gst_message_parse_error, void, GstMessage *message, GError **gerror, gchar **debug)
+LL_GRAB_SYM(true, gst_message_parse_warning, void, GstMessage *message, GError **gerror, gchar **debug)
+LL_GRAB_SYM(true, gst_message_parse_state_changed, void, GstMessage *message, GstState *oldstate, GstState *newstate, GstState *pending)
+LL_GRAB_SYM(true, gst_element_set_state, GstStateChangeReturn, GstElement *element, GstState state)
+LL_GRAB_SYM(true, gst_object_unref, void, gpointer object)
+LL_GRAB_SYM(true, gst_object_get_type, GType, void)
+LL_GRAB_SYM(true, gst_pipeline_get_type, GType, void)
+LL_GRAB_SYM(true, gst_pipeline_get_bus, GstBus*, GstPipeline *pipeline)
+LL_GRAB_SYM(true, gst_bus_add_watch, guint, GstBus * bus, GstBusFunc func, gpointer user_data)
+LL_GRAB_SYM(true, gst_element_factory_make, GstElement*, const gchar *factoryname, const gchar *name)
+LL_GRAB_SYM(true, gst_element_get_type, GType, void)
+LL_GRAB_SYM(true, gst_static_pad_template_get, GstPadTemplate*, GstStaticPadTemplate *pad_template)
+LL_GRAB_SYM(true, gst_element_class_add_pad_template, void, GstElementClass *klass, GstPadTemplate *temp)
+LL_GRAB_SYM(true, gst_caps_from_string, GstCaps *, const gchar *string)
+LL_GRAB_SYM(true, gst_caps_get_structure, GstStructure *, const GstCaps *caps, guint index)
+LL_GRAB_SYM(true, gst_element_register, gboolean, GstPlugin *plugin, const gchar *name, guint rank, GType type)
+LL_GRAB_SYM(true, gst_structure_get_int, gboolean, const GstStructure *structure, const gchar *fieldname, gint *value)
+LL_GRAB_SYM(true, gst_structure_get_value, const GValue *, const GstStructure *structure, const gchar *fieldname)
+LL_GRAB_SYM(true, gst_value_get_fraction_numerator, gint, const GValue *value)
+LL_GRAB_SYM(true, gst_value_get_fraction_denominator, gint, const GValue *value)
+LL_GRAB_SYM(true, gst_structure_get_name, const gchar *, const GstStructure *structure)
+LL_GRAB_SYM(true, gst_element_seek, bool, GstElement *, gdouble, GstFormat, GstSeekFlags, GstSeekType, gint64, GstSeekType, gint64)
 
-LL_GST_SYM(false, gst_registry_fork_set_enabled, void, gboolean enabled)
-LL_GST_SYM(false, gst_segtrap_set_enabled, void, gboolean enabled)
-LL_GST_SYM(false, gst_message_parse_buffering, void, GstMessage *message, gint *percent)
-LL_GST_SYM(false, gst_message_parse_info, void, GstMessage *message, GError **gerror, gchar **debug)
-LL_GST_SYM(false, gst_element_query_position, gboolean, GstElement *element, GstFormat *format, gint64 *cur)
-LL_GST_SYM(false, gst_version, void, guint *major, guint *minor, guint *micro, guint *nano)
+LL_GRAB_SYM(false, gst_registry_fork_set_enabled, void, gboolean enabled)
+LL_GRAB_SYM(false, gst_segtrap_set_enabled, void, gboolean enabled)
+LL_GRAB_SYM(false, gst_message_parse_buffering, void, GstMessage *message, gint *percent)
+LL_GRAB_SYM(false, gst_message_parse_info, void, GstMessage *message, GError **gerror, gchar **debug)
+LL_GRAB_SYM(false, gst_element_query_position, gboolean, GstElement *element, GstFormat *format, gint64 *cur)
+LL_GRAB_SYM(false, gst_version, void, guint *major, guint *minor, guint *micro, guint *nano)
 
-LL_GST_SYM( true, gst_message_parse_tag, void, GstMessage *, GstTagList **)
-LL_GST_SYM( true, gst_tag_list_foreach, void, const GstTagList *, GstTagForeachFunc, gpointer)
-LL_GST_SYM( true, gst_tag_list_get_tag_size, guint, const GstTagList *, const gchar *)
-LL_GST_SYM( true, gst_tag_list_get_value_index, const GValue *, const GstTagList *, const gchar *, guint)
+LL_GRAB_SYM( true, gst_message_parse_tag, void, GstMessage *, GstTagList **)
+LL_GRAB_SYM( true, gst_tag_list_foreach, void, const GstTagList *, GstTagForeachFunc, gpointer)
+LL_GRAB_SYM( true, gst_tag_list_get_tag_size, guint, const GstTagList *, const gchar *)
+LL_GRAB_SYM( true, gst_tag_list_get_value_index, const GValue *, const GstTagList *, const gchar *, guint)
 
-LL_GST_SYM( true, gst_caps_new_simple, GstCaps*, const char *, const char*, ... )
+LL_GRAB_SYM( true, gst_caps_new_simple, GstCaps*, const char *, const char*, ... )
 
-LL_GST_SYM( true, gst_sample_get_caps, GstCaps*, GstSample* )
-LL_GST_SYM( true, gst_sample_get_buffer, GstBuffer*, GstSample* )
-LL_GST_SYM( true, gst_buffer_map, gboolean, GstBuffer*, GstMapInfo*, GstMapFlags )
-LL_GST_SYM( true, gst_buffer_unmap, void, GstBuffer*, GstMapInfo* )
+LL_GRAB_SYM( true, gst_sample_get_caps, GstCaps*, GstSample* )
+LL_GRAB_SYM( true, gst_sample_get_buffer, GstBuffer*, GstSample* )
+LL_GRAB_SYM( true, gst_buffer_map, gboolean, GstBuffer*, GstMapInfo*, GstMapFlags )
+LL_GRAB_SYM( true, gst_buffer_unmap, void, GstBuffer*, GstMapInfo* )
 
-LL_GST_SYM( true, gst_app_sink_set_caps, void, GstAppSink*, GstCaps const* )
-LL_GST_SYM( true, gst_app_sink_pull_sample, GstSample*, GstAppSink* )
+LL_GRAB_SYM( true, gst_app_sink_set_caps, void, GstAppSink*, GstCaps const* )
+LL_GRAB_SYM( true, gst_app_sink_pull_sample, GstSample*, GstAppSink* )
 
-LL_GST_SYM( true, g_free, void, gpointer )
-LL_GST_SYM( true, g_error_free, void, GError* )
+LL_GRAB_SYM( true, g_free, void, gpointer )
+LL_GRAB_SYM( true, g_error_free, void, GError* )
 
-LL_GST_SYM( true, g_main_context_pending, gboolean, GMainContext* )
-LL_GST_SYM( true, g_main_loop_get_context, GMainContext*, GMainLoop* )
-LL_GST_SYM( true, g_main_context_iteration, gboolean, GMainContext*, gboolean )
-LL_GST_SYM( true, g_main_loop_new, GMainLoop*, GMainContext*, gboolean )
-LL_GST_SYM( true, g_main_loop_quit, void, GMainLoop* )
-LL_GST_SYM( true, gst_mini_object_unref, void, GstMiniObject* )
-LL_GST_SYM( true, g_object_set, void, gpointer, gchar const*, ... )
-LL_GST_SYM( true, g_source_remove, gboolean, guint )
-LL_GST_SYM( true, g_value_get_string, gchar const*, GValue const* )
+LL_GRAB_SYM( true, g_main_context_pending, gboolean, GMainContext* )
+LL_GRAB_SYM( true, g_main_loop_get_context, GMainContext*, GMainLoop* )
+LL_GRAB_SYM( true, g_main_context_iteration, gboolean, GMainContext*, gboolean )
+LL_GRAB_SYM( true, g_main_loop_new, GMainLoop*, GMainContext*, gboolean )
+LL_GRAB_SYM( true, g_main_loop_quit, void, GMainLoop* )
+LL_GRAB_SYM( true, gst_mini_object_unref, void, GstMiniObject* )
+LL_GRAB_SYM( true, g_object_set, void, gpointer, gchar const*, ... )
+LL_GRAB_SYM( true, g_source_remove, gboolean, guint )
+LL_GRAB_SYM( true, g_value_get_string, gchar const*, GValue const* )
 
-
-LL_GST_SYM( true, gst_debug_set_active, void, gboolean )
-LL_GST_SYM( true, gst_debug_add_log_function, void, GstLogFunction, gpointer, GDestroyNotify )
-LL_GST_SYM( true, gst_debug_set_default_threshold, void, GstDebugLevel )
-LL_GST_SYM( true, gst_debug_message_get , gchar const*, GstDebugMessage * )
\ No newline at end of file
+LL_GRAB_SYM( true, gst_debug_set_active, void, gboolean )
+LL_GRAB_SYM( true, gst_debug_add_log_function, void, GstLogFunction, gpointer, GDestroyNotify )
+LL_GRAB_SYM( true, gst_debug_set_default_threshold, void, GstDebugLevel )
+LL_GRAB_SYM( true, gst_debug_message_get , gchar const*, GstDebugMessage * )
\ No newline at end of file
diff --git a/indra/media_plugins/gstreamer10/media_plugin_gstreamer10.cpp b/indra/media_plugins/gstreamer10/media_plugin_gstreamer10.cpp
index 07bfb67283..dbc544d96b 100644
--- a/indra/media_plugins/gstreamer10/media_plugin_gstreamer10.cpp
+++ b/indra/media_plugins/gstreamer10/media_plugin_gstreamer10.cpp
@@ -43,9 +43,9 @@ extern "C" {
 #include <gst/app/gstappsink.h>
 
 }
+SymbolGrabber gSymbolGrabber;
 
-#include "llmediaimplgstreamer.h"
-#include "llmediaimplgstreamer_syms.h"
+#include "llmediaimplgstreamer_syms_raw.inc"
 
 static inline void llgst_caps_unref( GstCaps * caps )
 {
@@ -139,9 +139,9 @@ MediaPluginGStreamer10::MediaPluginGStreamer10( LLPluginInstance::sendMessageFun
     , mBusWatchID ( 0 )
     , mSeekWanted(false)
     , mSeekDestination(0.0)
-    , mPump ( NULL )
-    , mPlaybin ( NULL )
-    , mAppSink ( NULL )
+    , mPump ( nullptr )
+    , mPlaybin ( nullptr )
+    , mAppSink ( nullptr )
     , mCommand ( COMMAND_NONE )
 {
 }
@@ -193,8 +193,8 @@ gboolean MediaPluginGStreamer10::processGSTEvents(GstBus *bus, GstMessage *messa
         }
         case GST_MESSAGE_ERROR:
         {
-            GError *err = NULL;
-            gchar *debug = NULL;
+            GError *err = nullptr;
+            gchar *debug = nullptr;
 
             llgst_message_parse_error (message, &err, &debug);
             if (err)
@@ -211,8 +211,8 @@ gboolean MediaPluginGStreamer10::processGSTEvents(GstBus *bus, GstMessage *messa
         {
             if (llgst_message_parse_info)
             {
-                GError *err = NULL;
-                gchar *debug = NULL;
+                GError *err = nullptr;
+                gchar *debug = nullptr;
             
                 llgst_message_parse_info (message, &err, &debug);
                 if (err)
@@ -223,8 +223,8 @@ gboolean MediaPluginGStreamer10::processGSTEvents(GstBus *bus, GstMessage *messa
         }
         case GST_MESSAGE_WARNING:
         {
-            GError *err = NULL;
-            gchar *debug = NULL;
+            GError *err = nullptr;
+            gchar *debug = nullptr;
             
             llgst_message_parse_warning (message, &err, &debug);
             if (err)
@@ -293,13 +293,13 @@ bool MediaPluginGStreamer10::navigateTo ( const std::string urlIn )
 
     mSeekWanted = false;
 
-    if (NULL == mPump ||  NULL == mPlaybin)
+    if (nullptr == mPump ||  nullptr == mPlaybin)
     {
         setStatus(STATUS_ERROR);
         return false; // error
     }
 
-    llg_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), NULL);
+    llg_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), nullptr);
 
     // navigateTo implicitly plays, too.
     play(1.0);
@@ -328,7 +328,7 @@ bool MediaPluginGStreamer10::update(int milliseconds)
     //  DEBUGMSG("updating media...");
     
     // sanity check
-    if (NULL == mPump || NULL == mPlaybin)
+    if (nullptr == mPump || nullptr == mPlaybin)
     {
         return false;
     }
@@ -475,7 +475,7 @@ bool MediaPluginGStreamer10::setVolume( float volume )
     mVolume = volume;
     if (mDoneInit && mPlaybin)
     {
-        llg_object_set(mPlaybin, "volume", mVolume, NULL);
+        llg_object_set(mPlaybin, "volume", mVolume, nullptr);
         return true;
     }
 
@@ -549,7 +549,7 @@ bool MediaPluginGStreamer10::load()
     mVolume = 0.1234567f; // minor hack to force an initial volume update
 
     // Create a pumpable main-loop for this media
-    mPump = llg_main_loop_new (NULL, FALSE);
+    mPump = llg_main_loop_new (nullptr, FALSE);
     if (!mPump)
     {
         setStatus(STATUS_ERROR);
@@ -582,7 +582,7 @@ bool MediaPluginGStreamer10::load()
                                             "format", G_TYPE_STRING, "RGB",
                                             "width", G_TYPE_INT, INTERNAL_TEXTURE_SIZE,
                                             "height", G_TYPE_INT, INTERNAL_TEXTURE_SIZE,
-                                            NULL );
+                                            nullptr );
 
     llgst_app_sink_set_caps( mAppSink, pCaps );
     llgst_caps_unref( pCaps );
@@ -593,7 +593,7 @@ bool MediaPluginGStreamer10::load()
         return false;
     }
     
-    llg_object_set(mPlaybin, "video-sink", mAppSink, NULL);
+    llg_object_set(mPlaybin, "video-sink", mAppSink, nullptr);
 
     return true;
 }
@@ -611,16 +611,16 @@ bool MediaPluginGStreamer10::unload ()
     {
         llgst_element_set_state (mPlaybin, GST_STATE_NULL);
         llgst_object_unref (GST_OBJECT (mPlaybin));
-        mPlaybin = NULL;
+        mPlaybin = nullptr;
     }
 
     if (mPump)
     {
         llg_main_loop_quit(mPump);
-        mPump = NULL;
+        mPump = nullptr;
     }
 
-    mAppSink = NULL;
+    mAppSink = nullptr;
 
     setStatus(STATUS_NONE);
 
@@ -628,20 +628,15 @@ bool MediaPluginGStreamer10::unload ()
 }
 
 void LogFunction(GstDebugCategory *category, GstDebugLevel level, const gchar *file, const gchar *function, gint line, GObject *object, GstDebugMessage *message, gpointer user_data )
-#ifndef LL_LINUX // Docu says we need G_GNUC_NO_INSTRUMENT, but GCC says 'error'
-    G_GNUC_NO_INSTRUMENT
-#endif
 {
-#ifdef LL_LINUX
     std::cerr << file << ":" << line << "(" << function << "): " << llgst_debug_message_get( message ) << std::endl;
-#endif
 }
 
 //static
 bool MediaPluginGStreamer10::startup()
 {
     // first - check if GStreamer is explicitly disabled
-    if (NULL != getenv("LL_DISABLE_GSTREAMER"))
+    if (nullptr != getenv("LL_DISABLE_GSTREAMER"))
         return false;
 
     // only do global GStreamer initialization once.
@@ -651,28 +646,18 @@ bool MediaPluginGStreamer10::startup()
 
         // Get symbols!
         std::vector< std::string > vctDSONames;
-#if LL_DARWIN
-#elif LL_WINDOWS
-        vctDSONames.push_back( "libgstreamer-1.0-0.dll"  );
-        vctDSONames.push_back( "libgstapp-1.0-0.dll"  );
-        vctDSONames.push_back( "libglib-2.0-0.dll" );
-        vctDSONames.push_back( "libgobject-2.0-0.dll" );
-#else // linux or other ELFy unixoid
         vctDSONames.push_back( "libgstreamer-1.0.so.0"  );
         vctDSONames.push_back( "libgstapp-1.0.so.0"  );
         vctDSONames.push_back( "libglib-2.0.so.0" );
         vctDSONames.push_back( "libgobject-2.0.so" );
-#endif
-        if( !grab_gst_syms( vctDSONames ) )
-        {
+        if( !gSymbolGrabber.grabSymbols( vctDSONames ) )
             return false;
-        }
 
         if (llgst_segtrap_set_enabled)
         {
             llgst_segtrap_set_enabled(FALSE);
         }
-#if LL_LINUX
+
         // Gstreamer tries a fork during init, waitpid-ing on it,
         // which conflicts with any installed SIGCHLD handler...
         struct sigaction tmpact, oldact;
@@ -689,36 +674,29 @@ bool MediaPluginGStreamer10::startup()
             tmpact.sa_flags = SA_SIGINFO;
             sigaction(SIGCHLD, &tmpact, &oldact);
         }
-#endif // LL_LINUX
         // Protect against GStreamer resetting the locale, yuck.
         static std::string saved_locale;
-        saved_locale = setlocale(LC_ALL, NULL);
+        saved_locale = setlocale(LC_ALL, nullptr);
         
-//      _putenv_s( "GST_PLUGIN_PATH", "E:\\gstreamer\\1.0\\x86\\lib\\gstreamer-1.0" );
-
         llgst_debug_set_default_threshold( GST_LEVEL_WARNING );
-        llgst_debug_add_log_function( LogFunction, NULL, NULL );
+        llgst_debug_add_log_function( LogFunction, nullptr, nullptr );
         llgst_debug_set_active( false );
 
         // finally, try to initialize GStreamer!
-        GError *err = NULL;
-        gboolean init_gst_success = llgst_init_check(NULL, NULL, &err);
+        GError *err = nullptr;
+        gboolean init_gst_success = llgst_init_check(nullptr, nullptr, &err);
 
         // restore old locale
         setlocale(LC_ALL, saved_locale.c_str() );
 
-#if LL_LINUX
         // restore old SIGCHLD handler
         if (!llgst_registry_fork_set_enabled)
-            sigaction(SIGCHLD, &oldact, NULL);
-#endif // LL_LINUX
+            sigaction(SIGCHLD, &oldact, nullptr);
 
         if (!init_gst_success) // fail
         {
             if (err)
-            {
                 llg_error_free(err);
-            }
             return false;
         }
         
@@ -734,8 +712,7 @@ bool MediaPluginGStreamer10::closedown()
     if (!mDoneInit)
         return false; // error
 
-    ungrab_gst_syms();
-
+    gSymbolGrabber.ungrabSymbols();
     mDoneInit = false;
 
     return true;
@@ -746,7 +723,6 @@ MediaPluginGStreamer10::~MediaPluginGStreamer10()
     closedown();
 }
 
-
 std::string MediaPluginGStreamer10::getVersion()
 {
     std::string plugin_version = "GStreamer10 media plugin, GStreamer version ";
@@ -823,7 +799,7 @@ void MediaPluginGStreamer10::receiveMessage(const char *message_string)
                     if(mPixels == iter->second.mAddress)
                     {
                         // This is the currently active pixel buffer.  Make sure we stop drawing to it.
-                        mPixels = NULL;
+                        mPixels = nullptr;
                         mTextureSegmentName.clear();
                     }
                     mSharedSegments.erase(iter);
diff --git a/indra/media_plugins/libvlc/CMakeLists.txt b/indra/media_plugins/libvlc/CMakeLists.txt
index a3c1c4ef99..eaf9dde981 100644
--- a/indra/media_plugins/libvlc/CMakeLists.txt
+++ b/indra/media_plugins/libvlc/CMakeLists.txt
@@ -13,13 +13,6 @@ include(LibVLCPlugin)
 
 ### media_plugin_libvlc
 
-if(NOT ADDRESS_SIZE EQUAL 32)
-  if(WINDOWS)
-    ##add_definitions(/FIXED:NO)
-  else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
-    add_definitions(-fPIC)
-  endif(WINDOWS)
-endif(NOT ADDRESS_SIZE EQUAL 32)
 
 set(media_plugin_libvlc_SOURCE_FILES
     media_plugin_libvlc.cpp
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index f359bebb17..e6ac84d5ab 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -2384,4 +2384,3 @@ if (LL_TESTS)
 endif (LL_TESTS)
 
 check_message_template(${VIEWER_BINARY_NAME})
-
diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh
index eb3ead433b..7d26c81283 100755
--- a/indra/newview/linux_tools/wrapper.sh
+++ b/indra/newview/linux_tools/wrapper.sh
@@ -58,17 +58,6 @@ fi
 ## - Avoids an often-buggy X feature that doesn't really benefit us anyway.
 export SDL_VIDEO_X11_DGAMOUSE=0
 
-## - Works around a problem with misconfigured 64-bit systems not finding GL
-I386_MULTIARCH="$(dpkg-architecture -ai386 -qDEB_HOST_MULTIARCH 2>/dev/null)"
-MULTIARCH_ERR=$?
-if [ $MULTIARCH_ERR -eq 0 ]; then
-    echo 'Multi-arch support detected.'
-    MULTIARCH_GL_DRIVERS="/usr/lib/${I386_MULTIARCH}/dri"
-    export LIBGL_DRIVERS_PATH="${LIBGL_DRIVERS_PATH}:${MULTIARCH_GL_DRIVERS}:/usr/lib64/dri:/usr/lib32/dri:/usr/lib/dri"
-else
-    export LIBGL_DRIVERS_PATH="${LIBGL_DRIVERS_PATH}:/usr/lib64/dri:/usr/lib32/dri:/usr/lib/dri"
-fi
-
 ## - The 'scim' GTK IM module widely crashes the viewer.  Avoid it.
 if [ "$GTK_IM_MODULE" = "scim" ]; then
     export GTK_IM_MODULE=xim
@@ -98,25 +87,6 @@ cd "${RUN_PATH}"
 ## Before we mess with LD_LIBRARY_PATH, save the old one to restore for
 ##  subprocesses that care.
 export SAVED_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}"
-
-# if [ -n "$LL_TCMALLOC" ]; then
-#    tcmalloc_libs='/usr/lib/libtcmalloc.so.0 /usr/lib/libstacktrace.so.0 /lib/libpthread.so.0'
-#    all=1
-#    for f in $tcmalloc_libs; do
-#        if [ ! -f $f ]; then
-#	    all=0
-#	fi
-#    done
-#    if [ $all != 1 ]; then
-#        echo 'Cannot use tcmalloc libraries: components missing' 1>&2
-#    else
-#	export LD_PRELOAD=$(echo $tcmalloc_libs | tr ' ' :)
-#	if [ -z "$HEAPCHECK" -a -z "$HEAPPROFILE" ]; then
-#	    export HEAPCHECK=${HEAPCHECK:-normal}
-#	fi
-#    fi
-#fi
-
 export LD_LIBRARY_PATH="$PWD/lib:${LD_LIBRARY_PATH}"
 
 # Copy "$@" to ARGS array specifically to delete the --skip-gridargs switch.
@@ -140,18 +110,6 @@ LL_RUN_ERR=$?
 if [ $LL_RUN_ERR -ne 0 ]; then
 	# generic error running the binary
 	echo '*** Bad shutdown ($LL_RUN_ERR). ***'
-	if [ "$(uname -m)" = "x86_64" ]; then
-		echo
-		cat << EOFMARKER
-You are running the Second Life Viewer on a x86_64 platform.  The
-most common problems when launching the Viewer (particularly
-'bin/do-not-directly-run-secondlife-bin: not found' and 'error while
-loading shared libraries') may be solved by installing your Linux
-distribution's 32-bit compatibility packages.
-For example, on Ubuntu and other Debian-based Linuxes you might run:
-$ sudo apt-get install ia32-libs ia32-libs-gtk ia32-libs-kde ia32-libs-sdl
-EOFMARKER
-	fi
 fi
 
 echo
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index a1fecdb981..4099f8bc7d 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1130,7 +1130,7 @@ bool LLAppViewer::init()
 
 	gGLActive = FALSE;
 
-#if LL_RELEASE_FOR_DOWNLOAD
+#if LL_RELEASE_FOR_DOWNLOAD && !LL_LINUX
     // Skip updater if this is a non-interactive instance
     if (!gSavedSettings.getBOOL("CmdLineSkipUpdater") && !gNonInteractive)
     {
@@ -5662,4 +5662,3 @@ void LLAppViewer::metricsSend(bool enable_reporting)
 	// resolution in time.
 	gViewerAssetStats->restart();
 }
-
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 59701cc5b3..3791d1e754 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1739,9 +1739,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
 		}
 		else if(LLFile::stat(plugin_name, &s))
 		{
-#if !LL_LINUX
 			LL_WARNS_ONCE("Media") << "Couldn't find plugin at " << plugin_name << LL_ENDL;
-#endif
 		}
 		else
 		{
@@ -1795,9 +1793,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
 			}
 		}
 	}
-#if !LL_LINUX
 	LL_WARNS_ONCE("Plugin") << "plugin initialization failed for mime type: " << media_type << LL_ENDL;
-#endif
 
 	if(gAgent.isInitialized())
 	{
diff --git a/indra/newview/skins/default/xui/en/mime_types_linux.xml b/indra/newview/skins/default/xui/en/mime_types_linux.xml
index 7188b1e699..22a0024874 100644
--- a/indra/newview/skins/default/xui/en/mime_types_linux.xml
+++ b/indra/newview/skins/default/xui/en/mime_types_linux.xml
@@ -7,7 +7,7 @@
 		none
 	</defaultwidget>
 	<defaultimpl>
-		media_plugin_webkit
+		media_plugin_cef
 	</defaultimpl>
 	<widgetset name="web">
 		<label name="web_label">
@@ -130,7 +130,7 @@
 			movie
 		</widgettype>
 		<impl>
-			media_plugin_libvlc
+			media_plugin_gstreamer
 		</impl>
 	</scheme>
 	<mimetype name="blank">
@@ -141,7 +141,7 @@
 			none
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype name="none/none">
@@ -152,7 +152,7 @@
 			none
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype name="audio/*">
@@ -163,7 +163,7 @@
 			audio
 		</widgettype>
 		<impl>
-			media_plugin_libvlc
+			media_plugin_gstreamer
 		</impl>
 	</mimetype>
 	<mimetype name="video/*">
@@ -174,7 +174,7 @@
 			movie
 		</widgettype>
 		<impl>
-			media_plugin_libvlc
+			media_plugin_gstreamer
 		</impl>
 	</mimetype>
 	<mimetype name="image/*">
@@ -185,7 +185,7 @@
 			image
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype menu="1" name="video/vnd.secondlife.qt.legacy">
@@ -196,7 +196,7 @@
 			movie
 		</widgettype>
 		<impl>
-			media_plugin_libvlc
+			media_plugin_gstreamer
 		</impl>
 	</mimetype>
 	<mimetype name="application/javascript">
@@ -207,7 +207,7 @@
 			web
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype name="application/ogg">
@@ -218,7 +218,7 @@
 			audio
 		</widgettype>
 		<impl>
-			media_plugin_libvlc
+			media_plugin_gstreamer
 		</impl>
 	</mimetype>
 	<mimetype name="application/pdf">
@@ -229,7 +229,7 @@
 			image
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype name="application/postscript">
@@ -240,7 +240,7 @@
 			image
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype name="application/rtf">
@@ -251,7 +251,7 @@
 			image
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype name="application/smil">
@@ -262,7 +262,7 @@
 			movie
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype name="application/xhtml+xml">
@@ -273,7 +273,7 @@
 			web
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype name="application/x-director">
@@ -284,7 +284,7 @@
 			image
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype name="audio/mid">
@@ -295,7 +295,7 @@
 			audio
 		</widgettype>
 		<impl>
-			media_plugin_libvlc
+			media_plugin_gstreamer
 		</impl>
 	</mimetype>
 	<mimetype name="audio/mpeg">
@@ -306,7 +306,7 @@
 			audio
 		</widgettype>
 		<impl>
-			media_plugin_libvlc
+			media_plugin_gstreamer
 		</impl>
 	</mimetype>
 	<mimetype name="audio/x-aiff">
@@ -317,7 +317,7 @@
 			audio
 		</widgettype>
 		<impl>
-			media_plugin_libvlc
+			media_plugin_gstreamer
 		</impl>
 	</mimetype>
 	<mimetype name="audio/x-wav">
@@ -328,7 +328,7 @@
 			audio
 		</widgettype>
 		<impl>
-			media_plugin_libvlc
+			media_plugin_gstreamer
 		</impl>
 	</mimetype>
 	<mimetype menu="1" name="image/bmp">
@@ -339,7 +339,7 @@
 			image
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype menu="1" name="image/gif">
@@ -350,7 +350,7 @@
 			image
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype menu="1" name="image/jpeg">
@@ -361,7 +361,7 @@
 			image
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype menu="1" name="image/png">
@@ -372,7 +372,7 @@
 			image
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype name="image/svg+xml">
@@ -383,7 +383,7 @@
 			image
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype menu="1" name="image/tiff">
@@ -394,7 +394,7 @@
 			image
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype menu="1" name="text/html">
@@ -405,7 +405,7 @@
 			web
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype menu="1" name="text/plain">
@@ -416,7 +416,7 @@
 			text
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype name="text/xml">
@@ -427,7 +427,7 @@
 			text
 		</widgettype>
 		<impl>
-			media_plugin_webkit
+			media_plugin_cef
 		</impl>
 	</mimetype>
 	<mimetype menu="1" name="video/mpeg">
@@ -438,7 +438,7 @@
 			movie
 		</widgettype>
 		<impl>
-			media_plugin_libvlc
+			media_plugin_gstreamer
 		</impl>
 	</mimetype>
 	<mimetype name="video/mp4">
@@ -449,7 +449,7 @@
 			movie
 		</widgettype>
 		<impl>
-			media_plugin_libvlc
+			media_plugin_gstreamer
 		</impl>
 	</mimetype>
 	<mimetype menu="1" name="video/quicktime">
@@ -460,7 +460,7 @@
 			movie
 		</widgettype>
 		<impl>
-			media_plugin_libvlc
+			media_plugin_gstreamer
 		</impl>
 	</mimetype>
 	<mimetype name="video/x-ms-asf">
@@ -471,7 +471,7 @@
 			movie
 		</widgettype>
 		<impl>
-			media_plugin_libvlc
+			media_plugin_gstreamer
 		</impl>
 	</mimetype>
 	<mimetype name="video/x-ms-wmv">
@@ -482,7 +482,7 @@
 			movie
 		</widgettype>
 		<impl>
-			media_plugin_libvlc
+			media_plugin_gstreamer
 		</impl>
 	</mimetype>
 	<mimetype menu="1" name="video/x-msvideo">
@@ -493,7 +493,7 @@
 			movie
 		</widgettype>
 		<impl>
-			media_plugin_libvlc
+			media_plugin_gstreamer
 		</impl>
 	</mimetype>
 </mimetypes>
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index c97d421504..6fae39db30 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -1243,20 +1243,20 @@ class LinuxManifest(ViewerManifest):
                 self.path("secondlife_256.BMP","ll_icon.BMP")
 
         # plugins
-        #with self.prefix(src=os.path.join(self.args['build'], os.pardir, 'media_plugins'), dst="bin/llplugin"):
-        #    self.path("gstreamer10/libmedia_plugin_gstreamer10.so", "libmedia_plugin_gstreamer.so")
+        with self.prefix(src=os.path.join(self.args['build'], os.pardir, 'media_plugins'), dst="bin/llplugin"):
+            self.path("gstreamer10/libmedia_plugin_gstreamer10.so", "libmedia_plugin_gstreamer.so")
 
 
-        """
-        Once we got CEF enable this
         with self.prefix(src=os.path.join(self.args['build'], os.pardir, 'media_plugins'), dst="bin/llplugin"):
             self.path("cef/libmedia_plugin_cef.so", "libmedia_plugin_cef.so" )
         with self.prefix(src=os.path.join(pkgdir, 'lib', 'release'), dst="lib"):
             self.path( "libcef.so" )
-        with self.prefix(src=os.path.join(pkgdir, 'lib', 'release', 'swiftshader'), dst=os.path.join("bin", "swiftshader") ):
-            self.path( "*.so" )
-        with self.prefix(src=os.path.join(pkgdir, 'lib', 'release', 'swiftshader'), dst=os.path.join("lib", "swiftshader") ):
-            self.path( "*.so" )
+
+            self.path( "libEGL*" )
+            self.path( "libvulkan*" )
+            self.path( "libvk_swiftshader*" )
+            self.path( "libGLESv2*" )
+            self.path( "vk_swiftshader_icd.json")
 
         with self.prefix(src=os.path.join(pkgdir, 'bin', 'release'), dst="bin"):
             self.path( "chrome-sandbox" )
@@ -1267,18 +1267,13 @@ class LinuxManifest(ViewerManifest):
             self.path( "snapshot_blob.bin" )
             self.path( "v8_context_snapshot.bin" )
 
-        with self.prefix(src=os.path.join(pkgdir, 'resources'), dst="bin"):
-            self.path( "chrome_100_percent.pak" )
-            self.path( "chrome_200_percent.pak" )
-            self.path( "resources.pak" )
-            self.path( "icudtl.dat" )
         with self.prefix(src=os.path.join(pkgdir, 'resources'), dst="lib"):
             self.path( "chrome_100_percent.pak" )
             self.path( "chrome_200_percent.pak" )
             self.path( "resources.pak" )
             self.path( "icudtl.dat" )
 
-        with self.prefix(src=os.path.join(pkgdir, 'resources', 'locales'), dst=os.path.join('bin', 'locales')):
+        with self.prefix(src=os.path.join(pkgdir, 'resources', 'locales'), dst=os.path.join('lib', 'locales')):
             self.path("am.pak")
             self.path("ar.pak")
             self.path("bg.pak")
@@ -1332,7 +1327,6 @@ class LinuxManifest(ViewerManifest):
             self.path("vi.pak")
             self.path("zh-CN.pak")
             self.path("zh-TW.pak")
-        """
 
         self.path("featuretable_linux.txt")
         self.path("cube.dae")
-- 
cgit v1.2.3


From 72730609f371ae0417a2d117fdc9d805ce8858fb Mon Sep 17 00:00:00 2001
From: Brad Linden <46733234+brad-linden@users.noreply.github.com>
Date: Wed, 10 Apr 2024 09:48:03 -0700
Subject: Fix linux some shader errors when running under WSL, related to
 secondlife/viewer#1149 (#1170)

---
 .../app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl   | 4 ++--
 indra/newview/app_settings/shaders/class3/deferred/materialF.glsl   | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl
index 1a85d70256..a33c4cc58b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl
@@ -27,11 +27,11 @@
 
 float random (vec2 uv) 
 {
-    return 0;
+    return 0.;
 }
 
 float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n, inout vec4 collectedColor, sampler2D source, float glossiness)
 {
     collectedColor = vec4(0);
-    return 0;
+    return 0.;
 }
diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
index ec1e49eeb4..83c3845d18 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
@@ -53,7 +53,7 @@ out vec4 frag_color;
 float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
 #endif
 
-void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
+void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv,
         vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear);
 void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm);
 void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity);
@@ -276,10 +276,10 @@ float getShadow(vec3 pos, vec3 norm)
     #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
         return sampleDirectionalShadow(pos, norm, vary_texcoord0.xy);
     #else
-        return 1;
+        return 1.;
     #endif
 #else
-    return 1;
+    return 1.;
 #endif
 }
 
-- 
cgit v1.2.3


From 148f80f0779f42c1aa7d2f07c04a63507446662c Mon Sep 17 00:00:00 2001
From: Bennett Goble <signal@lindenlab.com>
Date: Wed, 10 Apr 2024 19:54:10 -0700
Subject: Linux: build with clang, link with mold

---
 indra/cmake/00-Common.cmake | 54 ++++++++++++++++++++++++++++-----------------
 indra/cmake/Linker.cmake    | 11 +++++++++
 2 files changed, 45 insertions(+), 20 deletions(-)
 create mode 100644 indra/cmake/Linker.cmake

(limited to 'indra')

diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index d46ebc4960..21242a32be 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -15,6 +15,7 @@
 include_guard()
 
 include(Variables)
+include(Linker)
 
 # We go to some trouble to set LL_BUILD to the set of relevant compiler flags.
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} $ENV{LL_BUILD}")
@@ -127,23 +128,37 @@ if (LINUX)
           APPID=secondlife
           LL_IGNORE_SIGCHLD
   )
+
   add_compile_options(
-          -fexceptions
-          -fno-math-errno
-          -fno-strict-aliasing
-          -fsigned-char
-          -msse2
-          -mfpmath=sse
-          -pthread
-          -Wno-parentheses
-          -Wno-deprecated
-          -Wno-c++20-compat
-          -Wno-pessimizing-move
-          -Wno-stringop-overflow
-          -Wno-stringop-truncation
-          -Wno-dangling-pointer
-          -fvisibility=hidden
+      -fexceptions
+      -fno-math-errno
+      -fno-strict-aliasing
+      -fsigned-char
+      -msse2
+      -mfpmath=sse
+      -pthread
+      -fvisibility=hidden
+  )
+
+  set(GCC_CLANG_COMPATIBLE_WARNINGS
+      -Wno-parentheses
+      -Wno-deprecated
+      -Wno-c++20-compat
+      -Wno-pessimizing-move
+  )
+
+  set(CLANG_WARNINGS
+      ${GCC_CLANG_COMPATIBLE_WARNINGS}
+      # Put clang specific warning configuration here
   )
+
+  set(GCC_WARNINGS
+      ${GCC_CLANG_COMPATIBLE_WARNINGS}
+      -Wno-stringop-overflow
+      -Wno-stringop-truncation
+      -Wno-dangling-pointer
+  )
+
   add_link_options(
           -Wl,--no-keep-memory
           -Wl,--build-id
@@ -156,12 +171,15 @@ if (LINUX)
   # this stops us requiring a really recent glibc at runtime
   add_compile_options(-fno-stack-protector)
 
-  # ND: clang is a bit more picky than GCC, the latter seems to auto include -lstdc++ and -lm. The former not so and thus fails to link
   if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+    # ND: clang is a bit more picky than GCC, the latter seems to auto include -lstdc++ and -lm. The former not so and thus fails to link
     add_link_options(
             -lstdc++
             -lm
     )
+    add_compile_options(${CLANG_WARNINGS})
+  else()
+    add_compile_options(${GCC_WARNINGS})
   endif()
 endif (LINUX)
 
@@ -191,10 +209,6 @@ if (DARWIN)
 
   list(APPEND GCC_WARNINGS -Wno-reorder -Wno-non-virtual-dtor )
 
-  if(LINUX)
-    list(APPEND GCC_WARNINGS -Wno-maybe-uninitialized -Wno-dangling-pointer )
-  endif()
-
   add_compile_options(${GCC_WARNINGS})
   add_compile_options(-m${ADDRESS_SIZE})
 endif ()
diff --git a/indra/cmake/Linker.cmake b/indra/cmake/Linker.cmake
new file mode 100644
index 0000000000..292aa25c57
--- /dev/null
+++ b/indra/cmake/Linker.cmake
@@ -0,0 +1,11 @@
+include_guard(GLOBAL)
+
+if (${LINK_WITH_MOLD})
+  find_program(MOLD_BIN mold REQUIRED)
+  if(MOLD_BIN)
+    message(STATUS "Mold linker found: ${MOLD_BIN}. Enabling mold as active linker.")
+    add_link_options("-fuse-ld=${MOLD_BIN}")
+  else()
+    message(STATUS "Mold linker not found. Using default linker.")
+  endif()
+endif()
-- 
cgit v1.2.3


From 52f3f70ce887c0f8877de7a8439bf44a246e7f9a Mon Sep 17 00:00:00 2001
From: Nicky <nicky.dasmijn@posteo.nl>
Date: Wed, 10 Apr 2024 20:44:24 +0200
Subject: Make sure items get removed from maps before the item itself gets
 destroyed, Otherwise the viewer ends with a dangling pointer in the map

---
 indra/newview/llinventorymodel.cpp | 3 +--
 indra/newview/llinventorypanel.cpp | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 05aa2e423f..ab8d085ae5 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -2050,8 +2050,8 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo
 		{
 			LL_WARNS(LOG_INV) << "Deleting cat " << id << " while it still has child cats" << LL_ENDL;
 		}
+        mParentChildCategoryTree.erase(id);
 		delete cat_list;
-		mParentChildCategoryTree.erase(id);
 	}
 	addChangedMask(LLInventoryObserver::REMOVE, id);
 
@@ -5040,4 +5040,3 @@ void LLInventoryModel::FetchItemHttpHandler::processFailure(const char * const r
 					  << LLCoreHttpUtil::responseToString(response) << "]" << LL_ENDL;
 	gInventory.notifyObservers();
 }
-
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index ab04a8589a..ae2236da3f 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -578,8 +578,8 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve
 		if (model_item && view_item && viewmodel_item)
 		{
 			const LLUUID& idp = viewmodel_item->getUUID();
+            removeItemID(idp);
 			view_item->destroyView();
-			removeItemID(idp);
 		}
 
         LLInventoryObject const* objectp = mInventory->getObject(item_id);
-- 
cgit v1.2.3


From a0f282643f26789ef7e1b624398581cceafc257c Mon Sep 17 00:00:00 2001
From: Andrey Lihatskiy <alihatskiy@productengine.com>
Date: Thu, 11 Apr 2024 19:10:46 +0300
Subject: Restore the fix for #945 (lost during merge #1178)

---
 indra/newview/lloutfitslist.cpp | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 20ef1588ae..7bb9fa2eed 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -913,16 +913,8 @@ void LLOutfitListBase::onIdleRefreshList()
         LLViewerInventoryCategory *cat = gInventory.getCategory(*items_iter);
         if (cat)
         {
-            LLInventoryObject* obj = gInventory.getObject(*items_iter);
-            if (!obj || (obj->getType() != LLAssetType::AT_CATEGORY))
-            {
-                break;
-            }
-            cat = (LLViewerInventoryCategory*)obj;
+            updateChangedCategoryName(cat, cat->getName());
         }
-        std::string name = cat->getName();
-
-        updateChangedCategoryName(cat, name);
     }
 
     sortOutfits();
-- 
cgit v1.2.3


From 33c7b9701de1589e8e3875656a6bab4f8710e7a8 Mon Sep 17 00:00:00 2001
From: Nicky Dasmijn <nicky.dasmijn@posteo.nl>
Date: Fri, 12 Apr 2024 14:15:01 +0200
Subject: Chore/cmake pretty up (#1205)

* - Add an option to with ASAN
- Fix GCC -Werror option.

* - find_program should not set REQUIRED if per logic a fallback to ld.bfd is fine
- cmake idiomatic is to test Variables without dereferencing  them

* Add -Wno-unknown-warning-option for clang or it will complain about some GCC only options

```
/home/runner/work/viewer/viewer/indra/llcommon/llsdutil.cpp:39:32: error: unknown warning group '-Wstringop-truncation', ignored [-Werror,-Wunknown-warning-option]
#pragma GCC diagnostic ignored "-Wstringop-truncation" // It's actually okay what happens here
```
---
 indra/cmake/00-Common.cmake | 14 ++++++++++++--
 indra/cmake/Linker.cmake    |  4 ++--
 2 files changed, 14 insertions(+), 4 deletions(-)

(limited to 'indra')

diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 21242a32be..d90a34bb6b 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -124,11 +124,20 @@ if (LINUX)
 
   add_compile_definitions(
           _REENTRANT
-          _FORTIFY_SOURCE=2
           APPID=secondlife
           LL_IGNORE_SIGCHLD
   )
 
+  if( ENABLE_ASAN )
+      add_compile_options(-U_FORTIFY_SOURCE
+        -fsanitize=address
+        --param asan-stack=0
+      )
+      add_link_options(-fsanitize=address)
+  else()
+   add_compile_definitions( _FORTIFY_SOURCE=2 )
+  endif()
+
   add_compile_options(
       -fexceptions
       -fno-math-errno
@@ -150,6 +159,7 @@ if (LINUX)
   set(CLANG_WARNINGS
       ${GCC_CLANG_COMPATIBLE_WARNINGS}
       # Put clang specific warning configuration here
+      -Wno-unknown-warning-option
   )
 
   set(GCC_WARNINGS
@@ -165,7 +175,7 @@ if (LINUX)
           -Wl,--no-undefined
   )
   if (NOT GCC_DISABLE_FATAL_WARNINGS)
-    list(APPEND GCC_WARNINGS -Werror)
+    add_compile_options( -Werror )
   endif (NOT GCC_DISABLE_FATAL_WARNINGS)
 
   # this stops us requiring a really recent glibc at runtime
diff --git a/indra/cmake/Linker.cmake b/indra/cmake/Linker.cmake
index 292aa25c57..8016842192 100644
--- a/indra/cmake/Linker.cmake
+++ b/indra/cmake/Linker.cmake
@@ -1,7 +1,7 @@
 include_guard(GLOBAL)
 
-if (${LINK_WITH_MOLD})
-  find_program(MOLD_BIN mold REQUIRED)
+if( LINK_WITH_MOLD )
+  find_program(MOLD_BIN mold)
   if(MOLD_BIN)
     message(STATUS "Mold linker found: ${MOLD_BIN}. Enabling mold as active linker.")
     add_link_options("-fuse-ld=${MOLD_BIN}")
-- 
cgit v1.2.3


From 7f021738ef2d74f78093dbe4fa37cbfa6645e05a Mon Sep 17 00:00:00 2001
From: Nicky <nicky.dasmijn@posteo.nl>
Date: Wed, 10 Apr 2024 21:02:40 +0200
Subject: Fix ASAN errors from LLVector4a::memcpyNonAliased16

Found by running with -fsanitze=thread
Suggestion to avoid accessing invalid memory:

In both cases memory will be allocated by can be accessed beyond bounds.

In LLPolyMesh it can be off by at least one (+x%2). Though I am not even sure if even in best case it always will be a multiple of 16.

In LLViewerJointMesh::updateFaceData the code tries to account for padding by, but the allocation in LLPolyMeshSharedData::allocateVertexData is done without any padding. Thus the sizes must not match.

Replacing the calls with memcpy as a quick fix to see if the error goes away fixed address sanitzer complaining.

It is up to debate if memcpy is a good replacement. LLVector4a::memcpyNonAliased16 was invented for performance. But on the other hand one could argue that nowadays every stdlib maintainer will very heavily optmize functions like memcpy themselves and could take advantage of CPU features the old LL implementation does not take into account.

AVX comes to mind. In any case did I not measure any of this.
---
 indra/llappearance/llpolymesh.cpp   |  2 +-
 indra/newview/llviewerjointmesh.cpp | 18 ++++++++++++------
 2 files changed, 13 insertions(+), 7 deletions(-)

(limited to 'indra')

diff --git a/indra/llappearance/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp
index dab14851c8..79b879b487 100644
--- a/indra/llappearance/llpolymesh.cpp
+++ b/indra/llappearance/llpolymesh.cpp
@@ -981,7 +981,7 @@ void LLPolyMesh::initializeForMorph()
 	LLVector4a::memcpyNonAliased16((F32*) mScaledNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
 	LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
 	LLVector4a::memcpyNonAliased16((F32*) mScaledBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
-	LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2));
+	memcpy((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices)); // allocated in LLPolyMeshSharedData::allocateVertexData
 
 	for (U32 i = 0; i < mSharedData->mNumVertices; ++i)
 	{
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index 5d46c695b7..b5ccb3591f 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -405,13 +405,19 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w
 		
 				F32* tc = (F32*) tex_coordsp.get();
 				F32* vw = (F32*) vertex_weightsp.get();
-				F32* cw = (F32*) clothing_weightsp.get();	
+				F32* cw = (F32*) clothing_weightsp.get();
 
-				S32 tc_size = (num_verts*2*sizeof(F32)+0xF) & ~0xF;
-				LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), tc_size);
-				S32 vw_size = (num_verts*sizeof(F32)+0xF) & ~0xF;	
-				LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), vw_size);	
-				LLVector4a::memcpyNonAliased16(cw, (F32*) mMesh->getClothingWeights(), num_verts*4*sizeof(F32));	
+				//S32 tc_size = (num_verts*2*sizeof(F32)+0xF) & ~0xF;
+				//LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), tc_size);
+				//S32 vw_size = (num_verts*sizeof(F32)+0xF) & ~0xF;
+				//LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), vw_size);
+
+                // Both allocated in LLPolyMeshSharedData::allocateVertexData(unsigned int)
+
+                memcpy(tc, mMesh->getTexCoords(), num_verts*2*sizeof(F32) );
+                memcpy(vw, mMesh->getWeights(), num_verts*sizeof(F32) );
+
+                LLVector4a::memcpyNonAliased16(cw, (F32*) mMesh->getClothingWeights(), num_verts*4*sizeof(F32));
 			}
 
 			const U32 idx_count = mMesh->getNumFaces()*3;
-- 
cgit v1.2.3


From 9356b3f9ae553c27018eb70a5a0780d21f38786c Mon Sep 17 00:00:00 2001
From: Nicky <nicky.dasmijn@posteo.nl>
Date: Sat, 13 Apr 2024 21:54:17 +0200
Subject: Inject XZ_DEFAULTS=-T0 into the environment. This will speed up
 archive generation.

---
 indra/newview/viewer_manifest.py | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'indra')

diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 46d5c0a3ce..103dff3621 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -65,6 +65,8 @@ class ViewerManifest(LLManifest):
         self.path(src="../../scripts/messages/message_template.msg", dst="app_settings/message_template.msg")
         self.path(src="../../etc/message.xml", dst="app_settings/message.xml")
 
+        os.environ["XZ_DEFAULTS"] = "-T0"
+
         if self.is_packaging_viewer():
             with self.prefix(src_dst="app_settings"):
                 self.exclude("logcontrol.xml")
-- 
cgit v1.2.3


From 2d4de107f8fc3714f75f73fc9293c87eaf0e5acb Mon Sep 17 00:00:00 2001
From: Nicky Dasmijn <nicky.dasmijn@posteo.nl>
Date: Sun, 14 Apr 2024 15:14:23 +0200
Subject: Feature/linux gtk removal (#1225)

* GTK remnants removal

Remove old GTK code and wire up some missing fltk logic in llfilepicker
This will leave linux_crash_logger as an empy stub which could be used as a skeleton in case crash logging gets implemented.
Otherwise linux_crash_logger and what is left of it in some cmake files can be deleted.

* Update SDL2 to latest version.

This revealed openal has also a dependebcy on sndio. Consequently the dependency was moved to OPENMAL.cmake and canot be dropped.

* Handle missing filetypes:
FFSAVE_GLTF,FFLOAD_GLTF, FFLOAD_MATERIAL, FFLOAD_MATERIAL_TEXTURE
---
 indra/cmake/LLWindow.cmake                      |   2 +-
 indra/cmake/OPENAL.cmake                        |   1 +
 indra/linux_crash_logger/llcrashloggerlinux.cpp |  58 +-
 indra/llwindow/llwindowsdl.h                    |   5 -
 indra/newview/llappviewer.cpp                   |  24 +-
 indra/newview/lldirpicker.cpp                   |  43 +-
 indra/newview/llfilepicker.cpp                  | 711 ++++++++----------------
 indra/newview/llfilepicker.h                    |  51 +-
 8 files changed, 267 insertions(+), 628 deletions(-)

(limited to 'indra')

diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake
index 6c7b70461f..23f4115aeb 100644
--- a/indra/cmake/LLWindow.cmake
+++ b/indra/cmake/LLWindow.cmake
@@ -16,5 +16,5 @@ if (LINUX)
   #target_link_libraries( ll::SDL INTERFACE SDL2::SDL2 SDL2::SDL2main X11)
 
   use_prebuilt_binary(SDL2)
-  target_link_libraries( ll::SDL INTERFACE SDL2 sndio X11)
+  target_link_libraries( ll::SDL INTERFACE SDL2 X11)
 endif (LINUX)
diff --git a/indra/cmake/OPENAL.cmake b/indra/cmake/OPENAL.cmake
index 0b6a7c2853..6a28846029 100644
--- a/indra/cmake/OPENAL.cmake
+++ b/indra/cmake/OPENAL.cmake
@@ -31,6 +31,7 @@ if (USE_OPENAL)
     target_link_libraries( ll::openal INTERFACE
             openal
             alut
+            sndio
             )
   else()
     message(FATAL_ERROR "OpenAL is not available for this platform")
diff --git a/indra/linux_crash_logger/llcrashloggerlinux.cpp b/indra/linux_crash_logger/llcrashloggerlinux.cpp
index 4092d43fc5..22182d32a4 100644
--- a/indra/linux_crash_logger/llcrashloggerlinux.cpp
+++ b/indra/linux_crash_logger/llcrashloggerlinux.cpp
@@ -1,25 +1,25 @@
-/** 
+/**
  * @file llcrashloggerlinux.cpp
  * @brief Linux crash logger implementation
  *
  * $LicenseInfo:firstyear=2003&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -38,9 +38,6 @@
 #include "lldir.h"
 #include "llsdserialize.h"
 
-#if LL_GTK
-# include "gtk/gtk.h"
-#endif // LL_GTK
 
 #define MAX_LOADSTRING 100
 
@@ -54,52 +51,9 @@ static const char dialog_text[] =
 static const char dialog_title[] =
 "Second Life Crash Logger";
 
-#if LL_GTK
-static void response_callback (GtkDialog *dialog,
-			       gint       arg1,
-			       gpointer   user_data)
-{
-	gint *response = (gint*)user_data;
-	*response = arg1;
-	gtk_widget_destroy(GTK_WIDGET(dialog));
-	gtk_main_quit();
-}
-#endif // LL_GTK
-
 static BOOL do_ask_dialog(void)
 {
-#if LL_GTK
-	gtk_disable_setlocale();
-	if (!gtk_init_check(NULL, NULL)) {
-		LL_INFOS() << "Could not initialize GTK for 'ask to send crash report' dialog; not sending report." << LL_ENDL;
-		return FALSE;
-	}
-	
-	GtkWidget *win = NULL;
-	GtkDialogFlags flags = GTK_DIALOG_MODAL;
-	GtkMessageType messagetype = GTK_MESSAGE_QUESTION;
-	GtkButtonsType buttons = GTK_BUTTONS_YES_NO;
-	gint response = GTK_RESPONSE_NONE;
-
-	win = gtk_message_dialog_new(NULL,
-				     flags, messagetype, buttons,
-				     "%s", dialog_text);
-	gtk_window_set_type_hint(GTK_WINDOW(win),
-				 GDK_WINDOW_TYPE_HINT_DIALOG);
-	gtk_window_set_title(GTK_WINDOW(win), dialog_title);
-	g_signal_connect (win,
-			  "response", 
-			  G_CALLBACK (response_callback),
-			  &response);
-	gtk_widget_show_all (win);
-	gtk_main();
-
-	return (GTK_RESPONSE_OK == response ||
-		GTK_RESPONSE_YES == response ||
-		GTK_RESPONSE_APPLY == response);
-#else
-	return FALSE;
-#endif // LL_GTK
+	// Ask to send crash report. Yes/No dialog.
 }
 
 LLCrashLoggerLinux::LLCrashLoggerLinux(void)
diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h
index 74b9ff026c..e922ce592c 100644
--- a/indra/llwindow/llwindowsdl.h
+++ b/indra/llwindow/llwindowsdl.h
@@ -191,11 +191,6 @@ public:
 
     void (*Unlock_Display)(void);
 
-#if LL_GTK
-    // Lazily initialize and check the runtime GTK version for goodness.
-    static bool ll_try_gtk_init(void);
-#endif // LL_GTK
-
 #if LL_X11
 
     static Window get_SDL_XWindowID(void);
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index eb1110a457..21eb41e2b7 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -108,7 +108,7 @@
 #include "llscenemonitor.h"
 #include "llavatarrenderinfoaccountant.h"
 #include "lllocalbitmaps.h"
-#include "llperfstats.h" 
+#include "llperfstats.h"
 #include "llgltfmateriallist.h"
 
 // Linden library includes
@@ -264,10 +264,6 @@ using namespace LL;
 // define a self-registering event API object
 #include "llappviewerlistener.h"
 
-#if LL_LINUX && LL_GTK
-#include "glib.h"
-#endif // (LL_LINUX) && LL_GTK
-
 #if LL_MSVC
 // disable boost::lexical_cast warning
 #pragma warning (disable:4702)
@@ -564,7 +560,7 @@ static void settings_to_globals()
 	gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
 	gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
     LLWorldMapView::setScaleSetting(gSavedSettings.getF32("MapScale"));
-	
+
 #if LL_DARWIN
     LLWindowMacOSX::sUseMultGL = gSavedSettings.getBOOL("RenderAppleUseMultGL");
 	gHiDPISupport = gSavedSettings.getBOOL("RenderHiDPI");
@@ -1344,7 +1340,7 @@ bool LLAppViewer::frame()
 		}
 	}
 	else
-	{ 
+	{
 		try
 		{
 			ret = doFrame();
@@ -1755,7 +1751,7 @@ bool LLAppViewer::cleanup()
 	LLViewerCamera::deleteSingleton();
 
 	LL_INFOS() << "Viewer disconnected" << LL_ENDL;
-	
+
 	if (gKeyboard)
 	{
 		gKeyboard->resetKeys();
@@ -2214,7 +2210,7 @@ bool LLAppViewer::initThreads()
     }
 
     // The only configurable thread count right now is ImageDecode
-    // The viewer typically starts around 8 threads not including image decode, 
+    // The viewer typically starts around 8 threads not including image decode,
     // so try to leave at least one core free
     S32 image_decode_count = llclamp(cores - 9, 1, 8);
     threadCounts["ImageDecode"] = image_decode_count;
@@ -2290,7 +2286,7 @@ void LLAppViewer::initLoggingAndGetLastDuration()
     if (mSecondInstance)
     {
         LLFile::mkdir(gDirUtilp->getDumpLogsDirPath());
- 
+
         LLUUID uid;
         uid.generate();
         LLError::logToFile(gDirUtilp->getDumpLogsDirPath(uid.asString() + ".log"));
@@ -4211,8 +4207,8 @@ bool LLAppViewer::initCache()
     const F64 disk_cache_percent = gSavedSettings.getF32("DiskCachePercentOfTotal");
     const F64 texture_cache_percent = 100.0 - disk_cache_percent;
 
-    // note that the maximum size of this cache is defined as a percentage of the 
-    // total cache size - the 'CacheSize' pref - for all caches. 
+    // note that the maximum size of this cache is defined as a percentage of the
+    // total cache size - the 'CacheSize' pref - for all caches.
     const uintmax_t disk_cache_size = uintmax_t(cache_total_size * disk_cache_percent / 100);
 	const bool enable_cache_debug_info = gSavedSettings.getBOOL("EnableDiskCacheDebugInfo");
 
@@ -4226,7 +4222,7 @@ bool LLAppViewer::initCache()
 			gSavedSettings.setS32("LocalCacheVersion", LLAppViewer::getTextureCacheVersion());
 
             //texture cache version was bumped up in Simple Cache Viewer, and at this point old vfs files are not needed
-            remove_vfs_files = true;   
+            remove_vfs_files = true;
 		}
 	}
 
@@ -4283,7 +4279,7 @@ bool LLAppViewer::initCache()
         {
             LLDiskCache::getInstance()->removeOldVFSFiles();
         }
-        
+
         if (mPurgeCache)
 		{
 		LLSplashScreen::update(LLTrans::getString("StartupClearingCache"));
diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp
index e541d2ab00..d1c251bfc1 100644
--- a/indra/newview/lldirpicker.cpp
+++ b/indra/newview/lldirpicker.cpp
@@ -1,25 +1,25 @@
-/** 
+/**
  * @file lldirpicker.cpp
  * @brief OS-specific file picker
  *
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -59,7 +59,7 @@ LLDirPicker LLDirPicker::sInstance;
 // Implementation
 //
 
-// utility function to check if access to local file system via file browser 
+// utility function to check if access to local file system via file browser
 // is enabled and if not, tidy up and indicate we're not allowed to do this.
 bool LLDirPicker::check_local_file_access_enabled()
 {
@@ -111,7 +111,7 @@ BOOL LLDirPicker::getDir(std::string* filename, bool blocking)
 
 	BOOL success = FALSE;
 
-	
+
 	if (blocking)
 	{
 		// Modal, so pause agent
@@ -182,7 +182,7 @@ void LLDirPicker::reset()
 BOOL LLDirPicker::getDir(std::string* filename, bool blocking)
 {
     LLFilePicker::ELoadFilter filter=LLFilePicker::FFLOAD_DIRECTORY;
-    
+
     return mFilePicker->getOpenFile(filter, true);
 }
 
@@ -231,26 +231,7 @@ BOOL LLDirPicker::getDir(std::string* filename, bool blocking)
 		return FALSE;
 	}
 
-#ifndef LL_FLTK
-#if !LL_MESA_HEADLESS
-
-	if (mFilePicker)
-	{
-		GtkWindow* picker = mFilePicker->buildFilePicker(false, true,
-								 "dirpicker");
-
-		if (picker)
-		{		   
-		   gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("choose_the_directory").c_str());
-		   gtk_widget_show_all(GTK_WIDGET(picker));
-		   gtk_main();
-		   return (!mFilePicker->getFirstFile().empty());
-		}
-	}
-#endif // !LL_MESA_HEADLESS
-
-	return FALSE;
-#else
+#ifdef LL_FLTK
     gViewerWindow->getWindow()->beforeDialog();
 	Fl_Native_File_Chooser flDlg;
 	flDlg.title(LLTrans::getString("choose_the_directory").c_str());
@@ -286,7 +267,7 @@ std::string LLDirPicker::getDirName()
 
 #else // not implemented
 
-LLDirPicker::LLDirPicker() 
+LLDirPicker::LLDirPicker()
 {
 	reset();
 }
@@ -325,7 +306,7 @@ void LLDirPickerThread::getFile()
 #endif
 }
 
-//virtual 
+//virtual
 void LLDirPickerThread::run()
 {
 #if LL_WINDOWS
@@ -339,7 +320,7 @@ void LLDirPickerThread::run()
 	if (picker.getDir(&mProposedName, blocking))
 	{
 		mResponses.push_back(picker.getDirName());
-	}	
+	}
 
 	{
 		LLMutexLock lock(sMutex);
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 7ca212e062..3704a5253c 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -1,25 +1,25 @@
-/** 
+/**
  * @file llfilepicker.cpp
  * @brief OS-specific file picker
  *
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -40,6 +40,11 @@
 #include "llwindowsdl.h" // for some X/GTK utils to help with filepickers
 #endif // LL_SDL
 
+#ifdef LL_FLTK
+  #include "FL/Fl.H"
+  #include "FL/Fl_Native_File_Chooser.H"
+#endif
+
 #if LL_LINUX
 #include "llhttpconstants.h"    // file picker uses some of thes constants on Linux
 #endif
@@ -112,7 +117,7 @@ LLFilePicker::~LLFilePicker()
 	// nothing
 }
 
-// utility function to check if access to local file system via file browser 
+// utility function to check if access to local file system via file browser
 // is enabled and if not, tidy up and indicate we're not allowed to do this.
 bool LLFilePicker::check_local_file_access_enabled()
 {
@@ -267,7 +272,7 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
 	mOFN.nFilterIndex = 1;
 
 	setupFilter(filter);
-	
+
 	if (blocking)
 	{
 		// Modal, so pause agent
@@ -275,7 +280,7 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
 	}
 
 	reset();
-	
+
 	// NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
 	success = GetOpenFileName(&mOFN);
 	if (success)
@@ -290,7 +295,7 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
 		// Account for the fact that the app has been stalled.
 		LLFrameTimer::updateFrameTime();
 	}
-	
+
 	return success;
 }
 
@@ -476,7 +481,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
 			L"Targa Images (*.tga)\0*.tga\0" \
 			L"\0";
 		break;
-		
+
 	case FFSAVE_JPEG:
 		if (filename.empty())
 		{
@@ -569,7 +574,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
 		return FALSE;
 	}
 
- 
+
 	mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE;
 	mOFN.Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
 
@@ -696,11 +701,11 @@ bool	LLFilePicker::doNavChooseDialog(ELoadFilter filter)
 	{
 		return false;
 	}
-    
+
 	gViewerWindow->getWindow()->beforeDialog();
-    
+
     std::unique_ptr<std::vector<std::string>> allowed_types = navOpenFilterProc(filter);
-    
+
     std::unique_ptr<std::vector<std::string>> filev  = doLoadDialog(allowed_types.get(),
                                                     mPickOptions);
 
@@ -712,7 +717,7 @@ bool	LLFilePicker::doNavChooseDialog(ELoadFilter filter)
         mFiles.insert(mFiles.end(), filev->begin(), filev->end());
         return true;
     }
-	
+
 	return false;
 }
 
@@ -725,14 +730,14 @@ bool    LLFilePicker::doNavChooseDialogModeless(ELoadFilter filter,
     {
         return false;
     }
-    
+
     std::unique_ptr<std::vector<std::string>> allowed_types=navOpenFilterProc(filter);
-    
+
     doLoadDialogModeless(allowed_types.get(),
                                                     mPickOptions,
                                                     callback,
                                                     userdata);
-    
+
     return true;
 }
 
@@ -786,13 +791,13 @@ void set_nav_save_data(LLFilePicker::ESaveFilter filter, std::string &extension,
             creator = "\?\?\?\?";
             extension = "glb";
             break;
-            
+
         case LLFilePicker::FFSAVE_XML:
             type = "\?\?\?\?";
             creator = "\?\?\?\?";
             extension = "xml";
             break;
-            
+
         case LLFilePicker::FFSAVE_RAW:
             type = "\?\?\?\?";
             creator = "\?\?\?\?";
@@ -804,13 +809,13 @@ void set_nav_save_data(LLFilePicker::ESaveFilter filter, std::string &extension,
             creator = "prvw";
             extension = "j2c";
             break;
-        
+
         case LLFilePicker::FFSAVE_SCRIPT:
             type = "LSL ";
             creator = "\?\?\?\?";
             extension = "lsl";
             break;
-        
+
         case LLFilePicker::FFSAVE_ALL:
         default:
             type = "\?\?\?\?";
@@ -824,16 +829,16 @@ bool	LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filena
 {
 	// Setup the type, creator, and extension
     std::string		extension, type, creator;
-    
+
     set_nav_save_data(filter, extension, type, creator);
-	
+
     std::string namestring = filename;
     if (namestring.empty()) namestring="Untitled";
-    
+
 	gViewerWindow->getWindow()->beforeDialog();
 
 	// Run the dialog
-    std::unique_ptr<std::string> filev = doSaveDialog(&namestring, 
+    std::unique_ptr<std::string> filev = doSaveDialog(&namestring,
                  &type,
                  &creator,
                  &extension,
@@ -846,7 +851,7 @@ bool	LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filena
         mFiles.push_back(*filev);
 		return true;
     }
-	
+
 	return false;
 }
 
@@ -857,9 +862,9 @@ bool    LLFilePicker::doNavSaveDialogModeless(ESaveFilter filter,
 {
     // Setup the type, creator, and extension
     std::string        extension, type, creator;
-    
+
     set_nav_save_data(filter, extension, type, creator);
-    
+
     std::string namestring = filename;
     if (namestring.empty()) namestring="Untitled";
 
@@ -888,11 +893,11 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
 	}
 
 	reset();
-	
+
     mPickOptions &= ~F_MULTIPLE;
     mPickOptions |= F_FILE;
- 
-    if (filter == FFLOAD_DIRECTORY) //This should only be called from lldirpicker. 
+
+    if (filter == FFLOAD_DIRECTORY) //This should only be called from lldirpicker.
     {
 
         mPickOptions |= ( F_NAV_SUPPORT | F_DIRECTORY );
@@ -903,7 +908,7 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
 	{
         mPickOptions |= F_NAV_SUPPORT;
 	}
-	
+
 	if (blocking) // always true for linux/mac
 	{
 		// Modal, so pause agent
@@ -912,7 +917,7 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
 
 
 	success = doNavChooseDialog(filter);
-		
+
 	if (success)
 	{
 		if (!getFileCount())
@@ -944,10 +949,10 @@ BOOL LLFilePicker::getOpenFileModeless(ELoadFilter filter,
     }
 
     reset();
-    
+
     mPickOptions &= ~F_MULTIPLE;
     mPickOptions |= F_FILE;
- 
+
     if (filter == FFLOAD_DIRECTORY) //This should only be called from lldirpicker.
     {
 
@@ -973,11 +978,11 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter, bool blocking)
 	{
 		return FALSE;
 	}
-    
+
     BOOL success = FALSE;
 
 	reset();
-    
+
     mPickOptions |= F_FILE;
 
     mPickOptions |= F_MULTIPLE;
@@ -1023,7 +1028,7 @@ BOOL LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter,
     }
 
     reset();
-    
+
     mPickOptions |= F_FILE;
 
     mPickOptions |= F_MULTIPLE;
@@ -1045,7 +1050,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
 	}
 
 	reset();
-	
+
     mPickOptions &= ~F_MULTIPLE;
 
 	if (blocking)
@@ -1079,7 +1084,7 @@ BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter,
 {
     if( mLocked )
         return false;
-    
+
     // if local file browsing is turned off, return without opening dialog
     if ( check_local_file_access_enabled() == false )
     {
@@ -1087,7 +1092,7 @@ BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter,
     }
 
     reset();
-    
+
     mPickOptions &= ~F_MULTIPLE;
 
     return doNavSaveDialogModeless(filter, filename, callback, userdata);
@@ -1096,488 +1101,228 @@ BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter,
 
 #elif LL_LINUX
 
-# if LL_GTK
-
-// static
-void LLFilePicker::add_to_selectedfiles(gpointer data, gpointer user_data)
-{
-	// We need to run g_filename_to_utf8 in the user's locale
-	std::string saved_locale(setlocale(LC_ALL, NULL));
-	setlocale(LC_ALL, "");
-
-	LLFilePicker* picker = (LLFilePicker*) user_data;
-	GError *error = NULL;
-	gchar* filename_utf8 = g_filename_to_utf8((gchar*)data,
-						  -1, NULL, NULL, &error);
-	if (error)
-	{
-		// *FIXME.
-		// This condition should really be notified to the user, e.g.
-		// through a message box.  Just logging it is inappropriate.
-		
-		// g_filename_display_name is ideal, but >= glib 2.6, so:
-		// a hand-rolled hacky makeASCII which disallows control chars
-		std::string display_name;
-		for (const gchar *str = (const gchar *)data; *str; str++)
-		{
-			display_name += (char)((*str >= 0x20 && *str <= 0x7E) ? *str : '?');
-		}
-		LL_WARNS() << "g_filename_to_utf8 failed on \"" << display_name << "\": " << error->message << LL_ENDL;
-	}
-
-	if (filename_utf8)
-	{
-		picker->mFiles.push_back(std::string(filename_utf8));
-		LL_DEBUGS() << "ADDED FILE " << filename_utf8 << LL_ENDL;
-		g_free(filename_utf8);
-	}
+#if LL_FLTK
 
-	setlocale(LC_ALL, saved_locale.c_str());
-}
-
-// static
-void LLFilePicker::chooser_responder(GtkWidget *widget, gint response, gpointer user_data)
-{
-	LLFilePicker* picker = (LLFilePicker*)user_data;
-
-	LL_DEBUGS() << "GTK DIALOG RESPONSE " << response << LL_ENDL;
-
-	if (response == GTK_RESPONSE_ACCEPT)
-	{
-		GSList *file_list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget));
-		g_slist_foreach(file_list, (GFunc)add_to_selectedfiles, user_data);
-		g_slist_foreach(file_list, (GFunc)g_free, NULL);
-		g_slist_free (file_list);
-	}
-
-	// let's save the extension of the last added file(considering current filter)
-	GtkFileFilter *gfilter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(widget));
-	if(gfilter)
-	{
-		std::string filter = gtk_file_filter_get_name(gfilter);
-
-		if(filter == LLTrans::getString("png_image_files"))
-		{
-			picker->mCurrentExtension = ".png";
-		}
-		else if(filter == LLTrans::getString("targa_image_files"))
-		{
-			picker->mCurrentExtension = ".tga";
-		}
-	}
-
-	// set the default path for this usage context.
-	const char* cur_folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget));
-	if (cur_folder != NULL)
-	{
-		picker->mContextToPathMap[picker->mCurContextName] = cur_folder;
-	}
-
-	gtk_widget_destroy(widget);
-	gtk_main_quit();
-}
-
-
-GtkWindow* LLFilePicker::buildFilePicker(bool is_save, bool is_folder, std::string context)
-{
-#ifndef LL_MESA_HEADLESS
-	if (LLWindowSDL::ll_try_gtk_init())
-	{
-		GtkWidget *win = NULL;
-		GtkFileChooserAction pickertype =
-			is_save?
-			(is_folder?
-			 GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER :
-			 GTK_FILE_CHOOSER_ACTION_SAVE) :
-			(is_folder?
-			 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER :
-			 GTK_FILE_CHOOSER_ACTION_OPEN);
-
-		win = gtk_file_chooser_dialog_new(NULL, NULL,
-						  pickertype,
-						  GTK_STOCK_CANCEL,
-						   GTK_RESPONSE_CANCEL,
-						  is_folder ?
-						  GTK_STOCK_APPLY :
-						  (is_save ? 
-						   GTK_STOCK_SAVE :
-						   GTK_STOCK_OPEN),
-						   GTK_RESPONSE_ACCEPT,
-						  (gchar *)NULL);
-		mCurContextName = context;
-
-		// get the default path for this usage context if it's been
-		// seen before.
-		std::map<std::string,std::string>::iterator
-			this_path = mContextToPathMap.find(context);
-		if (this_path != mContextToPathMap.end())
-		{
-			gtk_file_chooser_set_current_folder
-				(GTK_FILE_CHOOSER(win),
-				 this_path->second.c_str());
-		}
-
-#  if LL_X11
-		// Make GTK tell the window manager to associate this
-		// dialog with our non-GTK raw X11 window, which should try
-		// to keep it on top etc.
-		Window XWindowID = LLWindowSDL::get_SDL_XWindowID();
-		if (None != XWindowID)
-		{
-			gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin
-			GdkWindow *gdkwin = gdk_window_foreign_new(XWindowID);
-			gdk_window_set_transient_for(GTK_WIDGET(win)->window,
-						     gdkwin);
-		}
-		else
-		{
-			LL_WARNS() << "Hmm, couldn't get xwid to use for transient." << LL_ENDL;
-		}
-#  endif //LL_X11
-
-		g_signal_connect (GTK_FILE_CHOOSER(win),
-				  "response",
-				  G_CALLBACK(LLFilePicker::chooser_responder),
-				  this);
-
-		gtk_window_set_modal(GTK_WINDOW(win), TRUE);
-
-		/* GTK 2.6: if (is_folder)
-			gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(win),
-			TRUE); */
-
-		return GTK_WINDOW(win);
-	}
-	else
-	{
-		return NULL;
-	}
-#else
-	return NULL;
-#endif //LL_MESA_HEADLESS
-}
-
-static void add_common_filters_to_gtkchooser(GtkFileFilter *gfilter,
-					     GtkWindow *picker,
-					     std::string filtername)
-{	
-	gtk_file_filter_set_name(gfilter, filtername.c_str());
-	gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker),
-				    gfilter);
-	GtkFileFilter *allfilter = gtk_file_filter_new();
-	gtk_file_filter_add_pattern(allfilter, "*");
-	gtk_file_filter_set_name(allfilter, LLTrans::getString("all_files").c_str());
-	gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), allfilter);
-	gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(picker), gfilter);
-}
-
-static std::string add_simple_pattern_filter_to_gtkchooser(GtkWindow *picker,
-							   std::string pattern,
-							   std::string filtername)
-{
-	GtkFileFilter *gfilter = gtk_file_filter_new();
-	gtk_file_filter_add_pattern(gfilter, pattern.c_str());
-	add_common_filters_to_gtkchooser(gfilter, picker, filtername);
-	return filtername;
-}
-
-static std::string add_simple_mime_filter_to_gtkchooser(GtkWindow *picker,
-							std::string mime,
-							std::string filtername)
+BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter,
+                                       const std::string& filename,
+                                       void (*callback)(bool, std::string&, void*),
+                                       void *userdata)
 {
-	GtkFileFilter *gfilter = gtk_file_filter_new();
-	gtk_file_filter_add_mime_type(gfilter, mime.c_str());
-	add_common_filters_to_gtkchooser(gfilter, picker, filtername);
-	return filtername;
+    LL_ERRS() << "NOT IMPLEMENTED" << LL_ENDL;
+    return FALSE;
 }
 
-static std::string add_wav_filter_to_gtkchooser(GtkWindow *picker)
+BOOL LLFilePicker::getOpenFileModeless(ELoadFilter filter,
+                                       void (*callback)(bool, std::vector<std::string> &, void*),
+                                       void *userdata)
 {
-	return add_simple_mime_filter_to_gtkchooser(picker,  "audio/x-wav",
-						    LLTrans::getString("sound_files") + " (*.wav)");
+    LL_ERRS() << "NOT IMPLEMENTED" << LL_ENDL;
+    return FALSE;
 }
 
-static std::string add_anim_filter_to_gtkchooser(GtkWindow *picker)
+BOOL LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter,
+                                                void (*callback)(bool, std::vector<std::string> &, void*),
+                                                void *userdata )
 {
-	GtkFileFilter *gfilter = gtk_file_filter_new();
-	gtk_file_filter_add_pattern(gfilter, "*.bvh");
-	gtk_file_filter_add_pattern(gfilter, "*.anim");
-	std::string filtername = LLTrans::getString("animation_files") + " (*.bvh; *.anim)";
-	add_common_filters_to_gtkchooser(gfilter, picker, filtername);
-	return filtername;
+    LL_ERRS() << "NOT IMPLEMENTED" << LL_ENDL;
+    return FALSE;
 }
 
-static std::string add_xml_filter_to_gtkchooser(GtkWindow *picker)
-{
-	return add_simple_pattern_filter_to_gtkchooser(picker,  "*.xml",
-												   LLTrans::getString("xml_files") + " (*.xml)");
-}
 
-static std::string add_collada_filter_to_gtkchooser(GtkWindow *picker)
-{
-	return add_simple_pattern_filter_to_gtkchooser(picker,  "*.dae",
-						       LLTrans::getString("scene_files") + " (*.dae)");
-}
 
-static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker)
-{
-	GtkFileFilter *gfilter = gtk_file_filter_new();
-	gtk_file_filter_add_pattern(gfilter, "*.tga");
-	gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_JPEG.c_str());
-	gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_PNG.c_str());
-	gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_BMP.c_str());
-	std::string filtername = LLTrans::getString("image_files") + " (*.tga; *.bmp; *.jpg; *.png)";
-	add_common_filters_to_gtkchooser(gfilter, picker, filtername);
-	return filtername;
-}
- 
-static std::string add_script_filter_to_gtkchooser(GtkWindow *picker)
+BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename, bool blocking )
 {
-	return add_simple_mime_filter_to_gtkchooser(picker,  HTTP_CONTENT_TEXT_PLAIN,
-							LLTrans::getString("script_files") + " (*.lsl)");
+	return openFileDialog( filter, blocking, eSaveFile );
 }
 
-static std::string add_dictionary_filter_to_gtkchooser(GtkWindow *picker)
+BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking )
 {
-	return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN,
-							LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)");
+	return openFileDialog( filter, blocking, eOpenFile );
 }
 
-static std::string add_save_texture_filter_to_gtkchooser(GtkWindow *picker)
+BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking)
 {
-	GtkFileFilter *gfilter_tga = gtk_file_filter_new();
-	GtkFileFilter *gfilter_png = gtk_file_filter_new();
-
-	gtk_file_filter_add_pattern(gfilter_tga, "*.tga");
-	gtk_file_filter_add_mime_type(gfilter_png, "image/png");
-	std::string caption = LLTrans::getString("save_texture_image_files") + " (*.tga; *.png)";
-	gtk_file_filter_set_name(gfilter_tga, LLTrans::getString("targa_image_files").c_str());
-	gtk_file_filter_set_name(gfilter_png, LLTrans::getString("png_image_files").c_str());
-
-	gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker),
-					gfilter_png);
-	gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker),
-					gfilter_tga);
-	return caption;
+	return openFileDialog( filter, blocking, eOpenMultiple );
 }
 
-BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename, bool blocking )
+bool LLFilePicker::openFileDialog( int32_t filter, bool blocking, EType aType )
 {
-	BOOL rtn = FALSE;
-
-	// if local file browsing is turned off, return without opening dialog
 	if ( check_local_file_access_enabled() == false )
-	{
-		return FALSE;
-	}
-
+		return false;
 	gViewerWindow->getWindow()->beforeDialog();
-
 	reset();
-	
-	GtkWindow* picker = buildFilePicker(true, false, "savefile");
-
-	if (picker)
+	Fl_Native_File_Chooser::Type flType = Fl_Native_File_Chooser::BROWSE_FILE;
+	if( aType == eOpenMultiple )
+		flType = Fl_Native_File_Chooser::BROWSE_MULTI_FILE;
+	else if( aType == eSaveFile )
+		flType = Fl_Native_File_Chooser::BROWSE_SAVE_FILE;
+	Fl_Native_File_Chooser flDlg;
+	std::string file_dialog_title;
+	std::string file_dialog_filter;
+	if (aType == EType::eSaveFile)
 	{
-		std::string suggest_name = "untitled";
-		std::string suggest_ext = "";
-		std::string caption = LLTrans::getString("save_file_verb") + " ";
-		switch (filter)
+		std::string file_type("all_files");
+		switch ((ESaveFilter) filter)
 		{
-		case FFSAVE_WAV:
-			caption += add_wav_filter_to_gtkchooser(picker);
-			suggest_ext = ".wav";
-			break;
-		case FFSAVE_TGA:
-			caption += add_simple_pattern_filter_to_gtkchooser
-				(picker, "*.tga", LLTrans::getString("targa_image_files") + " (*.tga)");
-			suggest_ext = ".tga";
-			break;
-		case FFSAVE_BMP:
-			caption += add_simple_mime_filter_to_gtkchooser
-				(picker, HTTP_CONTENT_IMAGE_BMP, LLTrans::getString("bitmap_image_files") + " (*.bmp)");
-			suggest_ext = ".bmp";
-			break;
-		case FFSAVE_PNG:
-			caption += add_simple_mime_filter_to_gtkchooser
-				(picker, "image/png", LLTrans::getString("png_image_files") + " (*.png)");
-			suggest_ext = ".png";
-			break;
-		case FFSAVE_TGAPNG:
-			caption += add_save_texture_filter_to_gtkchooser(picker);
-			suggest_ext = ".png";
-			break;
-		case FFSAVE_AVI:
-			caption += add_simple_mime_filter_to_gtkchooser
-				(picker, "video/x-msvideo",
-				 LLTrans::getString("avi_movie_file") + " (*.avi)");
-			suggest_ext = ".avi";
-			break;
-		case FFSAVE_ANIM:
-			caption += add_simple_pattern_filter_to_gtkchooser
-				(picker, "*.xaf", LLTrans::getString("xaf_animation_file") + " (*.xaf)");
-			suggest_ext = ".xaf";
-			break;
-		case FFSAVE_XML:
-			caption += add_simple_pattern_filter_to_gtkchooser
-				(picker, "*.xml", LLTrans::getString("xml_file") + " (*.xml)");
-			suggest_ext = ".xml";
-			break;
-		case FFSAVE_RAW:
-			caption += add_simple_pattern_filter_to_gtkchooser
-				(picker, "*.raw", LLTrans::getString("raw_file") + " (*.raw)");
-			suggest_ext = ".raw";
-			break;
-		case FFSAVE_J2C:
-			// *TODO: Should this be 'image/j2c' ?
-			caption += add_simple_mime_filter_to_gtkchooser
-				(picker, "images/jp2",
-				 LLTrans::getString("compressed_image_files") + " (*.j2c)");
-			suggest_ext = ".j2c";
-			break;
-		case FFSAVE_SCRIPT:
-			caption += add_script_filter_to_gtkchooser(picker);
-			suggest_ext = ".lsl";
-			break;
-		default:;
-			break;
+			case FFSAVE_ALL:
+				break;
+			case FFSAVE_TGA:
+				file_type = "targa_image_files";
+				file_dialog_filter = "*.tga";
+				break;
+			case FFSAVE_BMP:
+				file_type = "bitmap_image_files";
+				file_dialog_filter = "*.bmp";
+				break;
+			case FFSAVE_AVI:
+				file_type = "avi_movie_file";
+				file_dialog_filter = "*.avi";
+				break;
+			case FFSAVE_ANIM:
+				file_type = "xaf_animation_file";
+				file_dialog_filter = "*.xaf";
+				break;
+			case FFSAVE_XML:
+				file_type = "xml_file";
+				file_dialog_filter = "*.xml";
+				break;
+			case FFSAVE_COLLADA:
+				file_type = "collada_files";
+				file_dialog_filter = "*.dae";
+				break;
+			case FFSAVE_RAW:
+				file_type = "raw_file";
+				file_dialog_filter = "*.raw";
+				break;
+			case FFSAVE_J2C:
+				file_type = "compressed_image_files";
+				file_dialog_filter = "*.j2c";
+				break;
+			case FFSAVE_PNG:
+				file_type = "png_image_files";
+				file_dialog_filter = "*.png";
+				break;
+			case FFSAVE_JPEG:
+				file_type = "jpeg_image_files";
+				file_dialog_filter = "*.{jpg,jpeg}";
+				break;
+			case FFSAVE_SCRIPT:
+				file_type = "script_files";
+				file_dialog_filter = "*.lsl";
+				break;
+			case FFSAVE_TGAPNG:
+				file_type = "save_texture_image_files";
+				file_dialog_filter = "*.{tga,png}";
+				break;
+			case FFSAVE_WAV:
+				file_type = "sound_files";
+				file_dialog_filter = "*.wav";
+				break;
+			case FFSAVE_GLTF:
+				file_type = "gltf_asset_file";
+				file_dialog_filter = "*.{gltf,glb}";
+				break;
 		}
-		
-		gtk_window_set_title(GTK_WINDOW(picker), caption.c_str());
-
-		if (filename.empty())
+		file_dialog_title = LLTrans::getString("save_file_verb") + " " + LLTrans::getString(file_type);
+		file_dialog_filter = LLTrans::getString(file_type) + " \t" + file_dialog_filter;
+	}
+	else
+	{
+		std::string file_type("all_files");
+		switch ((ELoadFilter) filter)
 		{
-			suggest_name += suggest_ext;
+			case FFLOAD_ALL:
+				break;
+			case FFLOAD_WAV:
+				file_type = "sound_files";
+				file_dialog_filter = "*.wav";
+				break;
+			case FFLOAD_IMAGE:
+				file_type = "image_files";
+				file_dialog_filter = "*.{tga,bmp,jpg,jpeg,png}";
+				break;
+			case FFLOAD_ANIM:
+				file_type = "animation_files";
+				file_dialog_filter = "*.{bvh,anim}";
+				break;
+			case FFLOAD_XML:
+				file_type = "xml_file";
+				file_dialog_filter = "*.xml";
+				break;
+			case FFLOAD_SLOBJECT:
+				file_type = "xml_file";
+				file_dialog_filter = "*.slobject";
+				break;
+			case FFLOAD_RAW:
+				file_type = "raw_file";
+				file_dialog_filter = "*.raw";
+				break;
+			case FFLOAD_MODEL:
+			case FFLOAD_COLLADA:
+				file_type = "collada_files";
+				file_dialog_filter = "*.dae";
+				break;
+			case FFLOAD_SCRIPT:
+				file_type = "script_files";
+				file_dialog_filter = "*.lsl";
+				break;
+			case FFLOAD_DICTIONARY:
+				file_type = "dictionary_files";
+				file_dialog_filter = "*.{dic,xcu}";
+				break;
+			case FFLOAD_DIRECTORY:
+				file_type = "choose_the_directory";
+				break;
+			case FFLOAD_EXE:
+				file_type = "executable_files";
+				break;
+			case FFLOAD_GLTF:
+			case FFLOAD_MATERIAL:
+				file_type = "gltf_asset_file";
+				file_dialog_filter = "*.{gltg,glb}";
+				break;
+			case FFLOAD_MATERIAL_TEXTURE:
+				file_dialog_filter = "*.{gltf,glb,tga,bmp,jpg,jpeg,png}";
+				file_type = "image_files";
 
-			gtk_file_chooser_set_current_name
-				(GTK_FILE_CHOOSER(picker),
-				 suggest_name.c_str());
 		}
-		else
+		if (aType == EType::eOpenMultiple)
 		{
-			gtk_file_chooser_set_current_name
-				(GTK_FILE_CHOOSER(picker), filename.c_str());
+			file_dialog_title = LLTrans::getString("load_files");
 		}
-
-		gtk_widget_show_all(GTK_WIDGET(picker));
-
-		gtk_main();
-
-		rtn = (getFileCount() == 1);
-
-		if(rtn && filter == FFSAVE_TGAPNG)
+		else
 		{
-			std::string selected_file = mFiles.back();
-			mFiles.pop_back();
-			mFiles.push_back(selected_file + mCurrentExtension);
+			file_dialog_title = LLTrans::getString("load_file_verb") + " " + LLTrans::getString(file_type);
+			file_dialog_filter = LLTrans::getString(file_type) + " \t" + file_dialog_filter;
 		}
 	}
-
-	gViewerWindow->getWindow()->afterDialog();
-
-	return rtn;
-}
-
-BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking )
-{
-	BOOL rtn = FALSE;
-
-	// if local file browsing is turned off, return without opening dialog
-	if ( check_local_file_access_enabled() == false )
+	flDlg.title(file_dialog_title.c_str());
+	flDlg.type(flType);
+	if (!file_dialog_filter.empty())
 	{
-		return FALSE;
+		flDlg.filter(file_dialog_filter.c_str());
 	}
-
-	gViewerWindow->getWindow()->beforeDialog();
-
-	reset();
-	
-	GtkWindow* picker = buildFilePicker(false, false, "openfile");
-
-	if (picker)
+	int res = flDlg.show();
+	gViewerWindow->getWindow()->afterDialog();
+	if( res == 0 )
 	{
-		std::string caption = LLTrans::getString("load_file_verb") + " ";
-		std::string filtername = "";
-		switch (filter)
+		int32_t count = flDlg.count();
+		if( count < 0 )
+			count = 0;
+		for( int32_t i = 0; i < count; ++i )
 		{
-		case FFLOAD_WAV:
-			filtername = add_wav_filter_to_gtkchooser(picker);
-			break;
-		case FFLOAD_ANIM:
-			filtername = add_anim_filter_to_gtkchooser(picker);
-			break;
-		case FFLOAD_XML:
-			filtername = add_xml_filter_to_gtkchooser(picker);
-			break;
-        case FFLOAD_GLTF:
-            filtername = dead_code_should_blow_up_here(picker);
-            break;
-        case FFLOAD_COLLADA:
-            filtername = add_collada_filter_to_gtkchooser(picker);
-            break;
-        case FFLOAD_IMAGE:
-			filtername = add_imageload_filter_to_gtkchooser(picker);
-			break;
-		case FFLOAD_SCRIPT:
-			filtername = add_script_filter_to_gtkchooser(picker);
-			break;
-		case FFLOAD_DICTIONARY:
-			filtername = add_dictionary_filter_to_gtkchooser(picker);
-			break;
-		default:;
-			break;
+			char const *pFile = flDlg.filename(i);
+			if( pFile && strlen(pFile) > 0 )
+				mFiles.push_back( pFile  );
 		}
-
-		caption += filtername;
-		
-		gtk_window_set_title(GTK_WINDOW(picker), caption.c_str());
-
-		gtk_widget_show_all(GTK_WIDGET(picker));
-		gtk_main();
-
-		rtn = (getFileCount() == 1);
 	}
-
-	gViewerWindow->getWindow()->afterDialog();
-
-	return rtn;
-}
-
-BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking)
-{
-	BOOL rtn = FALSE;
-
-	// if local file browsing is turned off, return without opening dialog
-	if ( check_local_file_access_enabled() == false )
-	{
-		return FALSE;
-	}
-
-	gViewerWindow->getWindow()->beforeDialog();
-
-	reset();
-	
-	GtkWindow* picker = buildFilePicker(false, false, "openfile");
-
-	if (picker)
+	else if( res == -1 )
 	{
-		gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(picker),
-						      TRUE);
-
-		gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("load_files").c_str());
-
-		gtk_widget_show_all(GTK_WIDGET(picker));
-		gtk_main();
-		rtn = !mFiles.empty();
+		LL_WARNS() << "FLTK failed: " <<  flDlg.errmsg() << LL_ENDL;
 	}
-
-	gViewerWindow->getWindow()->afterDialog();
-
-	return rtn;
+	return mFiles.empty()?FALSE:TRUE;
 }
-
-# else // LL_GTK
-
+#else
 // Hacky stubs designed to facilitate fake getSaveFile and getOpenFile with
 // static results, when we don't have a real filepicker.
 
@@ -1591,7 +1336,7 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename,
 	}
 
 	reset();
-	
+
 	LL_INFOS() << "getSaveFile suggested filename is [" << filename
 		<< "]" << LL_ENDL;
 	if (!filename.empty())
@@ -1621,7 +1366,7 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking )
 	}
 
 	reset();
-	
+
 	// HACK: Static filenames for 'open' until we implement filepicker
 	std::string filename = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + "upload";
 	switch (filter)
@@ -1665,13 +1410,13 @@ BOOL LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter,
     return FALSE;
 }
 
-#endif // LL_GTK
+#endif // LL_FLTK
 
 #else // not implemented
 
 BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename )
 {
-	reset();	
+	reset();
 	return FALSE;
 }
 
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index 5686627776..5ac473755e 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -1,25 +1,25 @@
-/** 
+/**
  * @file llfilepicker.h
  * @brief OS-specific file picker
  *
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -33,12 +33,6 @@
 #ifndef LL_LLFILEPICKER_H
 #define LL_LLFILEPICKER_H
 
-#if LL_FLTK
-  #if LL_GTK
-    #undef LL_GTK
-  #endif
-#endif
-
 #include "stdtypes.h"
 
 #if LL_DARWIN
@@ -60,20 +54,8 @@
 #include <commdlg.h>
 #endif
 
-extern "C" {
-// mostly for Linux, possible on others
-#if LL_GTK
-# include "gtk/gtk.h"
-#error "Direct use of GTK is deprecated"
-#endif // LL_GTK
-}
-
 class LLFilePicker
 {
-#ifdef LL_GTK
-	friend class LLDirPicker;
-	friend void chooser_responder(GtkWidget *, gint, gpointer);
-#endif // LL_GTK
 public:
 	// calling this before main() is undefined
 	static LLFilePicker& instance( void ) { return sInstance; }
@@ -150,7 +132,7 @@ public:
 	S32 getFileCount() const { return (S32)mFiles.size(); }
 
 	// see lldir.h : getBaseFileName and getDirName to extract base or directory names
-	
+
 	// clear any lists of buffers or whatever, and make sure the file
 	// picker isn't locked.
 	void reset();
@@ -163,10 +145,10 @@ private:
 		FILENAME_BUFFER_SIZE = 65000
 	};
 
-	// utility function to check if access to local file system via file browser 
+	// utility function to check if access to local file system via file browser
 	// is enabled and if not, tidy up and indicate we're not allowed to do this.
 	bool check_local_file_access_enabled();
-	
+
 #if LL_WINDOWS
 	OPENFILENAMEW mOFN;				// for open and save dialogs
 	WCHAR mFilesW[FILENAME_BUFFER_SIZE];
@@ -177,7 +159,7 @@ private:
 #if LL_DARWIN
     S32 mPickOptions;
 	std::vector<std::string> mFileVector;
-	
+
 	bool doNavChooseDialog(ELoadFilter filter);
 	bool doNavChooseDialogModeless(ELoadFilter filter,
                                    void (*callback)(bool, std::vector<std::string>&, void*),
@@ -190,15 +172,6 @@ private:
                                  void *userdata);
 #endif
 
-#if LL_GTK
-	static void add_to_selectedfiles(gpointer data, gpointer user_data);
-	static void chooser_responder(GtkWidget *widget, gint response, gpointer user_data);
-	// we remember the last path that was accessed for a particular usage
-	std::map <std::string, std::string> mContextToPathMap;
-	std::string mCurContextName;
-	// we also remember the extension of the last added file.
-	std::string mCurrentExtension;
-#endif
 #if LL_FLTK
     enum EType
     {
@@ -212,12 +185,6 @@ private:
 	bool mLocked;
 
 	static LLFilePicker sInstance;
-	
-protected:
-#if LL_GTK
-        GtkWindow* buildFilePicker(bool is_save, bool is_folder,
-				   std::string context = "generic");
-#endif
 
 public:
 	// don't call these directly please.
-- 
cgit v1.2.3


From 295cff0fb5370f75749adf41a6c2d26c3431414c Mon Sep 17 00:00:00 2001
From: Ansariel <ansariel.hiller@phoenixviewer.com>
Date: Mon, 15 Apr 2024 11:05:56 +0200
Subject: Fix broken shaders due to 72730609f371ae0417a2d117fdc9d805ce8858fb

---
 indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl          | 2 +-
 .../newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl  | 2 +-
 .../newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl  | 2 +-
 .../newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl  | 2 +-
 indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl    | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
index acd32a81b3..0f9bd131fd 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
@@ -78,7 +78,7 @@ float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
 
 float getAmbientClamp();
 
-void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
+void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv,
         vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear);
 
 vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, float ambiance)
diff --git a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl
index 52e71edcac..35848ff4cd 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl
@@ -55,7 +55,7 @@ vec4 sampleReflectionProbesDebug(vec3 pos)
     return vec4(0, 0, 0, 0);
 }
 
-void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
+void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv,
         vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear)
 {
     ambenv = vec3(reflection_probe_ambiance * 0.25);
diff --git a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl
index 8430cca325..ab43262c0e 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl
@@ -48,7 +48,7 @@ vec3 linear_to_srgb(vec3 c);
 vec3 srgb_to_linear(vec3 c);
 
 // reflection probe interface
-void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
+void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv,
         vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear);
 
 void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity);
diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
index 906e66ecc8..d19ec89cbc 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
@@ -785,7 +785,7 @@ vec4 sampleReflectionProbesDebug(vec3 pos)
     return col;
 }
 
-void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
+void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv,
         vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit)
 {
     float reflection_lods = max_probe_lod;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index 5e8fe9301a..f4a1df9c2c 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -70,7 +70,7 @@ vec3  scaleSoftClipFragLinear(vec3 l);
 // reflection probe interface
 void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
     vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit_linear);
-void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
+void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv,
         vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear);
 void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm);
 void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity);
-- 
cgit v1.2.3


From 8f0c41c2e5d5c66df5e975b743140112494c4a7a Mon Sep 17 00:00:00 2001
From: Nicky Dasmijn <nicky.dasmijn@posteo.nl>
Date: Mon, 15 Apr 2024 22:59:16 +0200
Subject: Chore/pragma gcc cleansweep (#1226)

* Remove all GCC warning suppression pragmas.

* For Linux just just raise(SIGSEGV) as the crash driver. This has a much higher chance of the compiler understanding out intent and figuring out we end the program here.

* Remove -Wno-stringop-overflow and -Wno-stringop-truncation from GCC_WARNINGS. After calling raise(SIGSEGV) as the crash driver I saw no issue with those warnings anymore

After removing thoses GCC pragmas there is also no need for clang -Wno-unknown-warning-option anymore.

* Remove CMakePresets from this PR.

* Remove Lindens from comments :)
---
 indra/cmake/00-Common.cmake     |   3 -
 indra/llcommon/llerror.h        | 103 +++++++------
 indra/llcommon/llsdutil.cpp     |  23 ++-
 indra/llmessage/llnamevalue.cpp |   5 -
 indra/newview/llface.cpp        | 312 ++++++++++++++++++++--------------------
 indra/newview/llviewerstats.cpp |  93 ++++++------
 6 files changed, 265 insertions(+), 274 deletions(-)

(limited to 'indra')

diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index d90a34bb6b..2b6129590c 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -159,13 +159,10 @@ if (LINUX)
   set(CLANG_WARNINGS
       ${GCC_CLANG_COMPATIBLE_WARNINGS}
       # Put clang specific warning configuration here
-      -Wno-unknown-warning-option
   )
 
   set(GCC_WARNINGS
       ${GCC_CLANG_COMPATIBLE_WARNINGS}
-      -Wno-stringop-overflow
-      -Wno-stringop-truncation
       -Wno-dangling-pointer
   )
 
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 6f6b349cf5..a70b5cef3a 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -1,4 +1,4 @@
-/** 
+/**
  * @file llerror.h
  * @date   December 2006
  * @brief error message system
@@ -6,21 +6,21 @@
  * $LicenseInfo:firstyear=2006&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -95,6 +95,11 @@ const int LL_ERR_NOERR = 0;
 #define LL_STATIC_ASSERT(func, msg) static_assert(func, msg)
 #define LL_BAD_TEMPLATE_INSTANTIATION(type, msg) static_assert(false, msg)
 #else
+#if LL_LINUX
+// We need access to raise and SIGSEGV
+#include <signal.h>
+#endif
+
 #define LL_STATIC_ASSERT(func, msg) BOOST_STATIC_ASSERT(func)
 #define LL_BAD_TEMPLATE_INSTANTIATION(type, msg) BOOST_STATIC_ASSERT(sizeof(type) != 0 && false);
 #endif
@@ -103,12 +108,12 @@ const int LL_ERR_NOERR = 0;
 /** Error Logging Facility
 
 	Information for most users:
-	
+
 	Code can log messages with constructions like this:
-	
+
 		LL_INFOS("StringTag") << "request to fizzbip agent " << agent_id
 			<< " denied due to timeout" << LL_ENDL;
-		
+
 	Messages can be logged to one of four increasing levels of concern,
 	using one of four "streams":
 
@@ -116,45 +121,45 @@ const int LL_ERR_NOERR = 0;
 		LL_INFOS("StringTag")	- informational messages that are normal shown
 		LL_WARNS("StringTag")	- warning messages that signal a problem
 		LL_ERRS("StringTag")	- error messages that are major, unrecoverable failures
-		
+
 	The later (LL_ERRS("StringTag")) automatically crashes the process after the message
 	is logged.
-	
+
 	Note that these "streams" are actually #define magic.  Rules for use:
 		* they cannot be used as normal streams, only to start a message
 		* messages written to them MUST be terminated with LL_ENDL
 		* between the opening and closing, the << operator is indeed
 		  writing onto a std::ostream, so all conversions and stream
 		  formating are available
-	
+
 	These messages are automatically logged with function name, and (if enabled)
 	file and line of the message.  (Note: Existing messages that already include
 	the function name don't get name printed twice.)
-	
+
 	If you have a class, adding LOG_CLASS line to the declaration will cause
 	all messages emitted from member functions (normal and static) to be tagged
 	with the proper class name as well as the function name:
-	
+
 		class LLFoo
 		{
 			LOG_CLASS(LLFoo);
 		public:
 			...
 		};
-	
+
 		void LLFoo::doSomething(int i)
 		{
 			if (i > 100)
 			{
-				LL_WARNS("FooBarTag") << "called with a big value for i: " << i << LL_ENDL; 
+				LL_WARNS("FooBarTag") << "called with a big value for i: " << i << LL_ENDL;
 			}
 			...
 		}
-	
+
 	will result in messages like:
-	
+
 		WARN #FooBarTag# llcommon/llfoo(100) LLFoo::doSomething : called with a big value for i: 283
-	
+
     the syntax is:
         <timestamp> SPACE <level> SPACE <tags> SPACE <location> SPACE <function> SPACE COLON SPACE <message>
 
@@ -169,7 +174,7 @@ const int LL_ERR_NOERR = 0;
     A copy of that file named logcontrol-dev.xml can be made in the users personal settings
     directory; that will override the installed default file.  See the logcontrol.xml
     file or http://wiki.secondlife.com/wiki/Logging_System_Overview for configuration details.
-	
+
 	Lastly, logging is now very efficient in both compiled code and execution
 	when skipped.  There is no need to wrap messages, even debugging ones, in
 	#ifdef _DEBUG constructs.  LL_DEBUGS("StringTag") messages are compiled into all builds,
@@ -182,12 +187,12 @@ namespace LLError
 	{
 		LEVEL_ALL = 0,
 			// used to indicate that all messages should be logged
-			
+
 		LEVEL_DEBUG = 0,
 		LEVEL_INFO = 1,
 		LEVEL_WARN = 2,
 		LEVEL_ERROR = 3,	// used to be called FATAL
-		
+
 		LEVEL_NONE = 4
 			// not really a level
 			// used to indicate that no messages should be logged
@@ -223,13 +228,13 @@ namespace LLError
 		// Represents a specific place in the code where a message is logged
 		// This is public because it is used by the macros below.  It is not
 		// intended for public use.
-		CallSite(ELevel level, 
-				const char* file, 
+		CallSite(ELevel level,
+				const char* file,
 				int line,
-				const std::type_info& class_info, 
-				const char* function, 
-				bool print_once, 
-				const char** tags, 
+				const std::type_info& class_info,
+				const char* function,
+				bool print_once,
+				const char** tags,
 				size_t tag_count);
 
 		~CallSite();
@@ -238,16 +243,16 @@ namespace LLError
 		bool shouldLog();
 #else // LL_LIBRARY_INCLUDE
 		bool shouldLog()
-		{ 
-			return mCached 
-					? mShouldLog 
-					: Log::shouldLog(*this); 
+		{
+			return mCached
+					? mShouldLog
+					: Log::shouldLog(*this);
 		}
 			// this member function needs to be in-line for efficiency
 #endif // LL_LIBRARY_INCLUDE
-		
+
 		void invalidate();
-		
+
 		// these describe the call site and never change
 		const ELevel			mLevel;
 		const char* const		mFile;
@@ -263,22 +268,22 @@ namespace LLError
 								mTagString;
 		bool					mCached,
 								mShouldLog;
-		
+
 		friend class Log;
 	};
-	
-	
+
+
 	class End { };
 	inline std::ostream& operator<<(std::ostream& s, const End&)
 		{ return s; }
 		// used to indicate the end of a message
-		
+
 	class LL_COMMON_API NoClassInfo { };
 		// used to indicate no class info known for logging
 
     //LLCallStacks keeps track of call stacks and output the call stacks to log file
     //
-    //Note: to be simple, efficient and necessary to keep track of correct call stacks, 
+    //Note: to be simple, efficient and necessary to keep track of correct call stacks,
     //LLCallStacks is designed not to be thread-safe.
     //so try not to use it in multiple parallel threads at same time.
     //Used in a single thread at a time is fine.
@@ -287,8 +292,8 @@ namespace LLError
     private:
         typedef std::vector<std::string> StringVector;
         static StringVector sBuffer ;
-              
-    public:   
+
+    public:
         static void push(const char* function, const int line) ;
         static void insert(std::ostream& out, const char* function, const int line) ;
         static void print() ;
@@ -326,7 +331,7 @@ namespace LLError
     };
 }
 
-//this is cheaper than llcallstacks if no need to output other variables to call stacks. 
+//this is cheaper than llcallstacks if no need to output other variables to call stacks.
 #define LL_PUSH_CALLSTACKS() LLError::LLCallStacks::push(__FUNCTION__, __LINE__)
 
 #define llcallstacks                                                    \
@@ -341,7 +346,7 @@ namespace LLError
 	}
 
 #define LL_CLEAR_CALLSTACKS() LLError::LLCallStacks::clear()
-#define LL_PRINT_CALLSTACKS() LLError::LLCallStacks::print() 
+#define LL_PRINT_CALLSTACKS() LLError::LLCallStacks::print()
 
 /*
 	Class type information for logging
@@ -350,7 +355,7 @@ namespace LLError
 #define LOG_CLASS(s)	typedef s _LL_CLASS_TO_LOG
 	// Declares class to tag logged messages with.
 	// See top of file for example of how to use this
-	
+
 typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 	// Outside a class declaration, or in class without LOG_CLASS(), this
 	// typedef causes the messages to not be associated with any class.
@@ -392,7 +397,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 
 //Use this construct if you need to do computation in the middle of a
 //message:
-//	
+//
 //	LL_INFOS("AgentGesture") << "the agent " << agend_id;
 //	switch (f)
 //	{
@@ -401,17 +406,23 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 //		case FOP_SAYS:		LL_CONT << "says " << message;	break;
 //	}
 //	LL_CONT << " for " << t << " seconds" << LL_ENDL;
-//	
+//
 //Such computation is done iff the message will be logged.
 #define LL_CONT	_out
 
 #define LL_NEWLINE '\n'
 
 // Use this only in LL_ERRS or in a place that LL_ERRS may not be used
+
+#ifndef LL_LINUX
 #define LLERROR_CRASH                                   \
 {                                                       \
     crashdriver([](int* ptr){ *ptr = 0; exit(*ptr); }); \
 }
+#else
+// For Linux we just call raise and be done with it. No fighting the compiler to create a crashing code snippet.
+#define LLERROR_CRASH raise(SIGSEGV );
+#endif
 
 #define LL_ENDL                                         \
             LLError::End();                             \
@@ -510,7 +521,7 @@ LL_ENDL;
 
 LL_DEBUGS("SomeTag") performs the locking and map-searching ONCE, then caches
 the result in a static variable.
-*/ 
+*/
 
 // used by LLERROR_CRASH
 void crashdriver(void (*)(int*));
diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index 7438524272..4d5fb0d818 100644
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -1,4 +1,4 @@
-/** 
+/**
  * @file llsdutil.cpp
  * @author Phoenix
  * @date 2006-05-24
@@ -7,21 +7,21 @@
  * $LicenseInfo:firstyear=2006&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -36,7 +36,6 @@
 #	include <winsock2.h>	// for htonl
 #elif LL_LINUX
 #	include <netinet/in.h>
-#pragma GCC diagnostic ignored "-Wstringop-truncation" // It's actually okay what happens here
 #elif LL_DARWIN
 #	include <arpa/inet.h>
 #endif
@@ -325,7 +324,7 @@ BOOL compare_llsd_with_template(
 	return TRUE;
 }
 
-// filter_llsd_with_template() is a direct clone (copy-n-paste) of 
+// filter_llsd_with_template() is a direct clone (copy-n-paste) of
 // compare_llsd_with_template with the following differences:
 // (1) bool vs BOOL return types
 // (2) A map with the key value "*" is a special value and maps any key in the
@@ -387,7 +386,7 @@ bool filter_llsd_with_template(
 		else
 		{
 			// Traditional compare_llsd_with_template matching
-			
+
 			for (template_iter = template_llsd.beginArray();
 				 template_iter != template_llsd.endArray() &&
 					 test_iter != llsd_to_test.endArray();
@@ -418,7 +417,7 @@ bool filter_llsd_with_template(
 	else if (llsd_to_test.isMap())
 	{
 		resultant_llsd = LLSD::emptyMap();
-		
+
 		//now we loop over the keys of the two maps
 		//any excess is taken from the template
 		//excess is ignored in the test
@@ -465,7 +464,7 @@ bool filter_llsd_with_template(
 		{
 			LLSD sub_value;
 			LLSD::map_const_iterator test_iter;
-			
+
 			for (test_iter = llsd_to_test.beginMap();
 				 test_iter != llsd_to_test.endMap();
 				 ++test_iter)
@@ -945,9 +944,9 @@ LLSD drill(const LLSD& blob, const LLSD& path)
 
 } // namespace llsd
 
-// Construct a deep partial clone of of an LLSD object. primitive types share 
+// Construct a deep partial clone of of an LLSD object. primitive types share
 // references, however maps, arrays and binary objects are duplicated. An optional
-// filter may be include to exclude/include keys in a map. 
+// filter may be include to exclude/include keys in a map.
 LLSD llsd_clone(LLSD value, LLSD filter)
 {
     LL_PROFILE_ZONE_SCOPED
diff --git a/indra/llmessage/llnamevalue.cpp b/indra/llmessage/llnamevalue.cpp
index 15de4046ac..97b2d3aa5f 100644
--- a/indra/llmessage/llnamevalue.cpp
+++ b/indra/llmessage/llnamevalue.cpp
@@ -35,10 +35,6 @@
 #include "llstring.h"
 #include "llstringtable.h"
 
-#if LL_LINUX
-#pragma GCC diagnostic ignored "-Wstringop-truncation" // It's actually okay what happens here
-#endif
-
 // Anonymous enumeration to provide constants in this file.
 // *NOTE: These values may be used in sscanf statements below as their
 // value-1, so search for '2047' if you cange NV_BUFFER_LEN or '63' if
@@ -971,4 +967,3 @@ std::ostream&		operator<<(std::ostream& s, const LLNameValue &a)
 	}
 	return s;
 }
-
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index b6405df1ff..698ba0c01e 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -1,25 +1,25 @@
-/** 
+/**
  * @file llface.cpp
  * @brief LLFace class implementation
  *
  * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -57,12 +57,6 @@
 #include "llsculptidsize.h"
 #include "llmeshrepository.h"
 
-#if LL_LINUX
-// Work-around spurious used before init warning on Vector4a
-//
-#pragma GCC diagnostic ignored "-Wuninitialized"
-#endif
-
 #define LL_MAX_INDICES_COUNT 1000000
 
 static LLStaticHashedString sTextureIndexIn("texture_index_in");
@@ -87,7 +81,7 @@ The resulting texture coordinate <u,v> is:
 */
 void planarProjection(LLVector2 &tc, const LLVector4a& normal,
 					  const LLVector4a &center, const LLVector4a& vec)
-{	
+{
 	LLVector4a binormal;
 	F32 d = normal[0];
 
@@ -146,7 +140,7 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
 
 	//special value to indicate uninitialized position
 	mIndicesIndex	= 0xFFFFFFFF;
-	
+
 	for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
 	{
 		mIndexInTex[i] = 0;
@@ -188,7 +182,7 @@ void LLFace::destroy()
 			mTexture[i] = NULL;
 		}
 	}
-	
+
 	if (isState(LLFace::PARTICLE))
 	{
 		clearState(LLFace::PARTICLE);
@@ -215,7 +209,7 @@ void LLFace::destroy()
 			}
 		}
 	}
-	
+
 	setDrawInfo(NULL);
 
 	mDrawablep = NULL;
@@ -262,11 +256,11 @@ void LLFace::setPool(LLFacePool* new_pool, LLViewerTexture *texturep)
 		}
 		mDrawPoolp = new_pool;
 	}
-	
+
 	setTexture(texturep) ;
 }
 
-void LLFace::setTexture(U32 ch, LLViewerTexture* tex) 
+void LLFace::setTexture(U32 ch, LLViewerTexture* tex)
 {
 	llassert(ch < LLRender::NUM_TEXTURE_CHANNELS);
 
@@ -278,8 +272,8 @@ void LLFace::setTexture(U32 ch, LLViewerTexture* tex)
 	if(mTexture[ch].notNull())
 	{
 		mTexture[ch]->removeFace(ch, this) ;
-	}	
-	
+	}
+
 	if(tex)
 	{
 		tex->addFace(ch, this) ;
@@ -288,7 +282,7 @@ void LLFace::setTexture(U32 ch, LLViewerTexture* tex)
 	mTexture[ch] = tex ;
 }
 
-void LLFace::setTexture(LLViewerTexture* tex) 
+void LLFace::setTexture(LLViewerTexture* tex)
 {
 	setDiffuseMap(tex);
 }
@@ -362,7 +356,7 @@ void LLFace::switchTexture(U32 ch, LLViewerTexture* new_texture)
 	    getViewerObject()->changeTEImage(mTEOffset, new_texture) ;
 	}
 
-	setTexture(ch, new_texture) ;	
+	setTexture(ch, new_texture) ;
 	dirtyTexture();
 }
 
@@ -396,7 +390,7 @@ void LLFace::setSize(S32 num_vertices, S32 num_indices, bool align)
 		//allocate vertices in blocks of 4 for alignment
 		num_vertices = (num_vertices + 0x3) & ~0x3;
 	}
-	
+
 	if (mGeomCount != num_vertices ||
 		mIndicesCount != num_indices)
 	{
@@ -408,11 +402,11 @@ void LLFace::setSize(S32 num_vertices, S32 num_indices, bool align)
 	llassert(verify());
 }
 
-void LLFace::setGeomIndex(U16 idx) 
-{ 
+void LLFace::setGeomIndex(U16 idx)
+{
 	if (mGeomIndex != idx)
 	{
-		mGeomIndex = idx; 
+		mGeomIndex = idx;
 		mVertexBuffer = NULL;
 	}
 }
@@ -437,15 +431,15 @@ void LLFace::setTextureIndex(U8 index)
 	}
 }
 
-void LLFace::setIndicesIndex(S32 idx) 
-{ 
+void LLFace::setIndicesIndex(S32 idx)
+{
 	if (mIndicesIndex != idx)
 	{
-		mIndicesIndex = idx; 
+		mIndicesIndex = idx;
 		mVertexBuffer = NULL;
 	}
 }
-	
+
 //============================================================================
 
 U16 LLFace::getGeometryAvatar(
@@ -484,7 +478,7 @@ U16 LLFace::getGeometry(LLStrider<LLVector3> &vertices, LLStrider<LLVector3> &no
 
 		mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount);
 	}
-	
+
 	return mGeomIndex;
 }
 
@@ -511,7 +505,7 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
 
 	mDrawablep->getSpatialGroup()->rebuildGeom();
 	mDrawablep->getSpatialGroup()->rebuildMesh();
-		
+
 	if(mVertexBuffer.isNull())
 	{
 		return;
@@ -520,7 +514,7 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
 	if (mGeomCount > 0 && mIndicesCount > 0)
 	{
 		gGL.getTexUnit(0)->bind(imagep);
-	
+
 		gGL.pushMatrix();
 		if (mDrawablep->isActive())
 		{
@@ -532,7 +526,7 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
 		}
 
 		gGL.diffuseColor4fv(color.mV);
-	
+
 		if (mDrawablep->isState(LLDrawable::RIGGED))
 		{
 #if 0 // TODO --  there is no way this won't destroy our GL machine as implemented, rewrite it to not rely on software skinning
@@ -730,7 +724,7 @@ static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 of
 	F32 t = tex_coord.mV[1];
 
 	// Texture transforms are done about the center of the face.
-	s -= 0.5; 
+	s -= 0.5;
 	t -= 0.5;
 
 	// Handle rotation
@@ -743,7 +737,7 @@ static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 of
 	t *= magT;
 
 	// Then offset
-	s += offS + 0.5f; 
+	s += offS + 0.5f;
 	t += offT + 0.5f;
 
 	tex_coord.mV[0] = s;
@@ -751,17 +745,17 @@ static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 of
 }
 
 // Transform the texture coordinates for this face.
-static void xform4a(LLVector4a &tex_coord, const LLVector4a& trans, const LLVector4Logical& mask, const LLVector4a& rot0, const LLVector4a& rot1, const LLVector4a& offset, const LLVector4a& scale) 
+static void xform4a(LLVector4a &tex_coord, const LLVector4a& trans, const LLVector4Logical& mask, const LLVector4a& rot0, const LLVector4a& rot1, const LLVector4a& offset, const LLVector4a& scale)
 {
 	//tex coord is two coords, <s0, t0, s1, t1>
 	LLVector4a st;
 
 	// Texture transforms are done about the center of the face.
 	st.setAdd(tex_coord, trans);
-	
+
 	// Handle rotation
 	LLVector4a rot_st;
-		
+
 	// <s0 * cosAng, s0*-sinAng, s1*cosAng, s1*-sinAng>
 	LLVector4a s0;
 	s0.splat(st, 0);
@@ -770,9 +764,9 @@ static void xform4a(LLVector4a &tex_coord, const LLVector4a& trans, const LLVect
 	LLVector4a ss;
 	ss.setSelectWithMask(mask, s1, s0);
 
-	LLVector4a a; 
+	LLVector4a a;
 	a.setMul(rot0, ss);
-	
+
 	// <t0*sinAng, t0*cosAng, t1*sinAng, t1*cosAng>
 	LLVector4a t0;
 	t0.splat(st, 1);
@@ -783,7 +777,7 @@ static void xform4a(LLVector4a &tex_coord, const LLVector4a& trans, const LLVect
 
 	LLVector4a b;
 	b.setMul(rot1, tt);
-		
+
 	st.setAdd(a,b);
 
 	// Then scale
@@ -803,7 +797,7 @@ bool less_than_max_mag(const LLVector4a& vec)
 	val.setAbs(vec);
 
 	S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7;
-	
+
 	return lt == 0x7;
 }
 
@@ -822,20 +816,20 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
 		}
 
 		const LLVolumeFace &face = volume.getVolumeFace(f);
-		
-        LL_DEBUGS("RiggedBox") << "updating extents for face " << f 
-                               << " starting extents " << mExtents[0] << ", " << mExtents[1] 
-                               << " starting vf extents " << face.mExtents[0] << ", " << face.mExtents[1] 
+
+        LL_DEBUGS("RiggedBox") << "updating extents for face " << f
+                               << " starting extents " << mExtents[0] << ", " << mExtents[1]
+                               << " starting vf extents " << face.mExtents[0] << ", " << face.mExtents[1]
                                << " num verts " << face.mNumVertices << LL_ENDL;
 
         // MAINT-8264 - stray vertices, especially in low LODs, cause bounding box errors.
-		if (face.mNumVertices < 3) 
+		if (face.mNumVertices < 3)
         {
-            LL_DEBUGS("RiggedBox") << "skipping face " << f << ", bad num vertices " 
+            LL_DEBUGS("RiggedBox") << "skipping face " << f << ", bad num vertices "
                                    << face.mNumVertices << " " << face.mNumIndices << " " << face.mWeights << LL_ENDL;
             return FALSE;
         }
-        
+
 		//VECTORIZE THIS
 		LLMatrix4a mat_vert;
 		mat_vert.loadu(mat_vert_in);
@@ -845,7 +839,7 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
 
 		matMulBoundBox(mat_vert, face.mExtents, mExtents);
 
-        LL_DEBUGS("RiggedBox") << "updated extents for face " << f 
+        LL_DEBUGS("RiggedBox") << "updated extents for face " << f
                                << " bbox gave extents " << mExtents[0] << ", " << mExtents[1] << LL_ENDL;
 
 		if (!mDrawablep->isActive())
@@ -854,11 +848,11 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
 			offset.load3(mDrawablep->getRegion()->getOriginAgent().mV);
 			mExtents[0].add(offset);
 			mExtents[1].add(offset);
-            LL_DEBUGS("RiggedBox") << "updating extents for face " << f 
+            LL_DEBUGS("RiggedBox") << "updating extents for face " << f
                                    << " not active, added offset " << offset << LL_ENDL;
 		}
 
-        LL_DEBUGS("RiggedBox") << "updated extents for face " << f 
+        LL_DEBUGS("RiggedBox") << "updated extents for face " << f
                                << " to " << mExtents[0] << ", " << mExtents[1] << LL_ENDL;
 		LLVector4a t;
 		t.setAdd(mExtents[0],mExtents[1]);
@@ -885,7 +879,7 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
 LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, const LLVector4a& position, const LLVector4a& normal)
 {
 	LLVector2 tc = surface_coord;
-	
+
 	const LLTextureEntry *tep = getTextureEntry();
 
 	if (tep == NULL)
@@ -900,28 +894,28 @@ LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, const LLVector4a& po
 	if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
 	{
 		LLVector4a& center = *(mDrawablep->getVOVolume()->getVolume()->getVolumeFace(mTEOffset).mCenter);
-		
+
 		LLVector4a volume_position;
 		LLVector3 v_position(position.getF32ptr());
 
 		volume_position.load3(mDrawablep->getVOVolume()->agentPositionToVolume(v_position).mV);
-		
+
 		if (!mDrawablep->getVOVolume()->isVolumeGlobal())
 		{
 			LLVector4a scale;
 			scale.load3(mVObjp->getScale().mV);
 			volume_position.mul(scale);
 		}
-		
+
 		LLVector4a volume_normal;
 		LLVector3 v_normal(normal.getF32ptr());
 		volume_normal.load3(mDrawablep->getVOVolume()->agentDirectionToVolume(v_normal).mV);
 		volume_normal.normalize3fast();
-		
+
 		if (texgen == LLTextureEntry::TEX_GEN_PLANAR)
 		{
 			planarProjection(tc, volume_normal, center, volume_position);
-		}		
+		}
 	}
 
 	if (mTextureMatrix)	// if we have a texture matrix, use it
@@ -930,14 +924,14 @@ LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, const LLVector4a& po
 		tc3 = tc3 * *mTextureMatrix;
 		tc = LLVector2(tc3);
 	}
-	
+
 	else // otherwise use the texture entry parameters
 	{
 		xform(tc, cos(tep->getRotation()), sin(tep->getRotation()),
 			  tep->mOffsetS, tep->mOffsetT, tep->mScaleS, tep->mScaleT);
 	}
 
-	
+
 	return tc;
 }
 
@@ -978,7 +972,7 @@ void LLFace::getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_po
 }
 
 // Returns the necessary texture transform to align this face's TE to align_to's TE
-bool LLFace::calcAlignedPlanarTE(const LLFace* align_to,  LLVector2* res_st_offset, 
+bool LLFace::calcAlignedPlanarTE(const LLFace* align_to,  LLVector2* res_st_offset,
 								 LLVector2* res_st_scale, F32* res_st_rot, LLRender::eTexIndex map) const
 {
 	if (!align_to)
@@ -1101,13 +1095,13 @@ bool LLFace::canRenderAsMask()
         return false;
     }
 
-	
+
 	LLMaterial* mat = te->getMaterialParams();
 	if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND)
 	{
 		return false;
 	}
-	
+
 	if ((te->getColor().mV[3] == 1.0f) && // can't treat as mask if we have face alpha
 		(te->getGlow() == 0.f) && // glowing masks are hard to implement - don't mask
 		getTexture()->getIsAlphaMask()) // texture actually qualifies for masking (lazily recalculated but expensive)
@@ -1171,7 +1165,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
     const LLVolumeFace &vf = volume.getVolumeFace(face_index);
 	S32 num_vertices = (S32)vf.mNumVertices;
 	S32 num_indices = (S32) vf.mNumIndices;
-	
+
 	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE))
 	{
 		updateRebuildFlags();
@@ -1217,7 +1211,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 	LLStrider<LLVector4> wght;
 
 	BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME);
-	
+
 	BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal();
 	LLVector3 scale;
 	if (global_volume)
@@ -1228,7 +1222,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 	{
 		scale = mVObjp->getScale();
 	}
-	
+
 	bool rebuild_pos = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_POSITION);
 	bool rebuild_color = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_COLOR);
 	bool rebuild_emissive = rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE);
@@ -1244,7 +1238,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 	BOOL is_global = is_static;
 
 	LLVector3 center_sum(0.f, 0.f, 0.f);
-	
+
 	if (is_global)
 	{
 		setState(GLOBAL);
@@ -1263,13 +1257,13 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 	if (rebuild_color)
 	{ //decide if shiny goes in alpha channel of color
-		if (tep && 
+		if (tep &&
 			!isInAlphaPool())  // <--- alpha channel MUST contain transparency, not shiny
 	{
 			LLMaterial* mat = tep->getMaterialParams().get();
-						
+
 			bool shiny_in_alpha = false;
-			
+
 			//store shiny in alpha if we don't have a specular map
 			if  (!mat || mat->getSpecularID().isNull())
 			{
@@ -1285,7 +1279,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 					0.5f,
 					0.75f
 				};
-			
+
 				llassert(tep->getShiny() <= 3);
 				color.mV[3] = U8 (SHININESS_TO_ALPHA[tep->getShiny()] * 255);
 			}
@@ -1303,7 +1297,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		__m128i offset = _mm_set1_epi16(index_offset);
 
 		S32 end = num_indices/8;
-		
+
 		for (S32 i = 0; i < end; i++)
 		{
 			__m128i res = _mm_add_epi16(src[i], offset);
@@ -1320,7 +1314,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			}
 		}
 	}
-	
+
 
     LLMaterial* mat = tep->getMaterialParams().get();
     LLGLTFMaterial* gltf_mat = tep->getGLTFRenderMaterial();
@@ -1390,7 +1384,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
             }
         }
     }
-	
+
     const LLMeshSkinInfo* skin = nullptr;
     LLMatrix4a mat_vert;
     LLMatrix4a mat_normal;
@@ -1438,7 +1432,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		if (rebuild_tcoord)
 		{
             LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tcoord");
-									
+
 			//bump setup
 			LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f );
 			LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f);
@@ -1449,11 +1443,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			{
 				bump_quat = LLQuaternion(mDrawablep->getRenderMatrix());
 			}
-		
+
 			if (bump_code)
 			{
 				mVObjp->getVolume()->genTangents(face_index);
-				F32 offset_multiple; 
+				F32 offset_multiple;
 				switch( bump_code )
 				{
 					case BE_NO_BUMP:
@@ -1488,7 +1482,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 					tep->getScale( &s_scale, &t_scale );
 				}
 				// Use the nudged south when coming from above sun angle, such
-				// that emboss mapping always shows up on the upward faces of cubes when 
+				// that emboss mapping always shows up on the upward faces of cubes when
 				// it's noon (since a lot of builders build with the sun forced to noon).
 				LLVector3   sun_ray  = gSky.mVOSkyp->mBumpSunDir;
 				LLVector3   moon_ray = gSky.mVOSkyp->getMoon().getDirection();
@@ -1505,10 +1499,10 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			}
 
 			U8 tex_mode = 0;
-	
+
 			bool tex_anim = false;
 
-				LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp;	
+				LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp;
 				tex_mode = vobj->mTexAnimMode;
 
 			if (vobj->mTextureAnimp)
@@ -1549,7 +1543,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 				do_bump  = mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)
 					     || mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2);
 			}
-			
+
             // For GLTF materials: Transforms will be applied later
 			bool do_tex_mat = tex_mode && mTextureMatrix && !gltf_mat;
 
@@ -1597,7 +1591,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 							U32 count = num_vertices/2 + num_vertices%2;
 
 							for (S32 i = 0; i < count; i++)
-							{	
+							{
 								LLVector4a res = *src++;
 								xform4a(res, trans, mask, rot0, rot1, offset, scale);
 								res.store4a(dst);
@@ -1608,14 +1602,14 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 					else
 					{ //do tex mat, no texgen, no bump
 						for (S32 i = 0; i < num_vertices; i++)
-						{	
+						{
 							LLVector2 tc(vf.mTexCoords[i]);
-							
+
 							LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
 							tmp = tmp * *mTextureMatrix;
 							tc.mV[0] = tmp.mV[0];
 							tc.mV[1] = tmp.mV[1];
-							*tex_coords0++ = tc;	
+							*tex_coords0++ = tc;
 						}
 					}
 				}
@@ -1625,50 +1619,50 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 					if (do_tex_mat)
 					{
 						for (S32 i = 0; i < num_vertices; i++)
-						{	
+						{
 							LLVector2 tc(vf.mTexCoords[i]);
 							LLVector4a& norm = vf.mNormals[i];
 							LLVector4a& center = *(vf.mCenter);
-							LLVector4a vec = vf.mPositions[i];	
+							LLVector4a vec = vf.mPositions[i];
 							vec.mul(scalea);
 							planarProjection(tc, norm, center, vec);
-						
+
 							LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
 							tmp = tmp * *mTextureMatrix;
 							tc.mV[0] = tmp.mV[0];
 							tc.mV[1] = tmp.mV[1];
-				
-							*tex_coords0++ = tc;	
+
+							*tex_coords0++ = tc;
 						}
 					}
 					else if (xforms != XFORM_NONE)
 					{
 						for (S32 i = 0; i < num_vertices; i++)
-						{	
+						{
 							LLVector2 tc(vf.mTexCoords[i]);
 							LLVector4a& norm = vf.mNormals[i];
 							LLVector4a& center = *(vf.mCenter);
-							LLVector4a vec = vf.mPositions[i];	
+							LLVector4a vec = vf.mPositions[i];
 							vec.mul(scalea);
 							planarProjection(tc, norm, center, vec);
-						
+
 							xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
 
-							*tex_coords0++ = tc;	
+							*tex_coords0++ = tc;
 						}
 					}
 					else
 					{
 						for (S32 i = 0; i < num_vertices; i++)
-						{	
+						{
 							LLVector2 tc(vf.mTexCoords[i]);
 							LLVector4a& norm = vf.mNormals[i];
 							LLVector4a& center = *(vf.mCenter);
-							LLVector4a vec = vf.mPositions[i];	
+							LLVector4a vec = vf.mPositions[i];
 							vec.mul(scalea);
 							planarProjection(tc, norm, center, vec);
 
-							*tex_coords0++ = tc;	
+							*tex_coords0++ = tc;
 						}
 					}
 				}
@@ -1678,7 +1672,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
                 LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - texgen default");
 
 				std::vector<LLVector2> bump_tc;
-		
+
 				if (mat && !mat->getNormalID().isNull())
 				{ //writing out normal and specular texture coordinates, not bump offsets
 					do_bump = false;
@@ -1691,9 +1685,9 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
                     S32 xform_channel = XFORM_NONE;
 					switch (ch)
 					{
-						case 0: 
+						case 0:
                             xform_channel = XFORM_BLINNPHONG_COLOR;
-							mVertexBuffer->getTexCoord0Strider(dst, mGeomIndex, mGeomCount); 
+							mVertexBuffer->getTexCoord0Strider(dst, mGeomIndex, mGeomCount);
 							break;
 						case 1:
                             xform_channel = XFORM_BLINNPHONG_NORMAL;
@@ -1738,26 +1732,26 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 							break;
 					}
                     const bool do_xform = (xforms & xform_channel) != XFORM_NONE;
-					
+
 
                     for (S32 i = 0; i < num_vertices; i++)
-                    {   
+                    {
                         LLVector2 tc(vf.mTexCoords[i]);
-                
+
                         LLVector4a& norm = vf.mNormals[i];
-                    
+
                         LLVector4a& center = *(vf.mCenter);
-               
+
                         if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
                         {
                             LLVector4a vec = vf.mPositions[i];
-                    
+
                             vec.mul(scalea);
 
                             if (texgen == LLTextureEntry::TEX_GEN_PLANAR)
                             {
                                 planarProjection(tc, norm, center, vec);
-                            }       
+                            }
                         }
 
                         if (tex_mode && mTextureMatrix)
@@ -1783,7 +1777,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 				if ((!mat && !gltf_mat) && do_bump)
 				{
 					mVertexBuffer->getTexCoord1Strider(tex_coords1, mGeomIndex, mGeomCount);
-		
+
                     mVObjp->getVolume()->genTangents(face_index);
 
 					for (S32 i = 0; i < num_vertices; i++)
@@ -1800,7 +1794,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 						tangent_to_object.rotate(binormal_dir, t);
 						LLVector4a binormal;
 						mat_normal.rotate(t, binormal);
-						
+
 						//VECTORIZE THIS
 						if (mDrawablep->isActive())
 						{
@@ -1814,7 +1808,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 						LLVector2 tc = bump_tc[i];
 						tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() );
-					
+
 						*tex_coords1++ = tc;
 					}
 				}
@@ -1824,23 +1818,23 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		if (rebuild_pos)
 		{
 			LLVector4a* src = vf.mPositions;
-			
+
 			//_mm_prefetch((char*)src, _MM_HINT_T0);
 
 			LLVector4a* end = src+num_vertices;
 			//LLVector4a* end_64 = end-4;
 
 			llassert(num_vertices > 0);
-		
+
 			mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount);
-			
-			
+
+
 			F32* dst = (F32*) vert.get();
 			F32* end_f32 = dst+mGeomCount*4;
 
 			//_mm_prefetch((char*)dst, _MM_HINT_NTA);
 			//_mm_prefetch((char*)src, _MM_HINT_NTA);
-				
+
 			//_mm_prefetch((char*)dst, _MM_HINT_NTA);
 
 
@@ -1853,26 +1847,26 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			F32 val = 0.f;
 			S32* vp = (S32*) &val;
 			*vp = index;
-			
+
 			llassert(index <= LLGLSLShader::sIndexedTextureChannels-1);
 
 			LLVector4Logical mask;
 			mask.clear();
 			mask.setElement<3>();
-		
+
 			texIdx.set(0,0,0,val);
 
 			LLVector4a tmp;
 
-			
+
 			while (src < end)
-			{	
+			{
 				mat_vert.affineTransform(*src++, res0);
 				tmp.setSelectWithMask(mask, texIdx, res0);
 				tmp.store4a((F32*) dst);
 				dst += 4;
 			}
-			
+
 			while (dst < end_f32)
 			{
 				res0.store4a((F32*) dst);
@@ -1888,24 +1882,24 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			F32* normals = (F32*) norm.get();
 			LLVector4a* src = vf.mNormals;
 			LLVector4a* end = src+num_vertices;
-			
+
 			while (src < end)
-			{	
+			{
 				LLVector4a normal;
 				mat_normal.rotate(*src++, normal);
 				normal.store4a(normals);
 				normals += 4;
 			}
 		}
-		
+
 		if (rebuild_tangent)
 		{
             LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tangent");
 			mVertexBuffer->getTangentStrider(tangent, mGeomIndex, mGeomCount);
 			F32* tangents = (F32*) tangent.get();
-			
+
             mVObjp->getVolume()->genTangents(face_index);
-			
+
 			LLVector4Logical mask;
 			mask.clear();
 			mask.setElement<3>();
@@ -1919,12 +1913,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 				mat_normal.rotate(*src, tangent_out);
 				tangent_out.setSelectWithMask(mask, *src, tangent_out);
 				tangent_out.store4a(tangents);
-				
+
 				src++;
 				tangents += 4;
 			}
 		}
-	
+
 		if (rebuild_weights && vf.mWeights)
 		{
             LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - weight");
@@ -1942,7 +1936,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 			U32 vec[4];
 			vec[0] = vec[1] = vec[2] = vec[3] = color.asRGBA();
-		
+
 			src.loadua((F32*) vec);
 
 			F32* dst = (F32*) colors.get();
@@ -1953,7 +1947,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			}
 
 			for (S32 i = 0; i < num_vecs; i++)
-			{	
+			{
 				src.store4a(dst);
 				dst += 4;
 			}
@@ -1969,14 +1963,14 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 			LLVector4a src;
 
-		
+
 			LLColor4U glow4u = LLColor4U(0,0,0,glow);
 
 			U32 glow32 = glow4u.asRGBA();
 
 			U32 vec[4];
 			vec[0] = vec[1] = vec[2] = vec[3] = glow32;
-		
+
 			src.loadua((F32*) vec);
 
 			F32* dst = (F32*) emissive.get();
@@ -1987,7 +1981,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			}
 
 			for (S32 i = 0; i < num_vecs; i++)
-			{	
+			{
 				src.store4a(dst);
 				dst += 4;
 			}
@@ -2000,7 +1994,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		mTexExtents[1].setVec(1,1);
 		xform(mTexExtents[0], cos_ang, sin_ang, os, ot, ms, mt);
 		xform(mTexExtents[1], cos_ang, sin_ang, os, ot, ms, mt);
-		
+
 		F32 es = vf.mTexCoordExtents[1].mV[0] - vf.mTexCoordExtents[0].mV[0] ;
 		F32 et = vf.mTexCoordExtents[1].mV[1] - vf.mTexCoordExtents[0].mV[1] ;
 		mTexExtents[0][0] *= es ;
@@ -2023,13 +2017,13 @@ void LLFace::renderIndexed()
 }
 
 //check if the face has a media
-BOOL LLFace::hasMedia() const 
+BOOL LLFace::hasMedia() const
 {
 	if(mHasMedia)
 	{
 		return TRUE ;
 	}
-	if(mTexture[LLRender::DIFFUSE_MAP].notNull()) 
+	if(mTexture[LLRender::DIFFUSE_MAP].notNull())
 	{
 		return mTexture[LLRender::DIFFUSE_MAP]->hasParcelMedia() ;  //if has a parcel media
 	}
@@ -2050,7 +2044,7 @@ F32 LLFace::getTextureVirtualSize()
 {
     LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
 	F32 radius;
-	F32 cos_angle_to_view_dir;	
+	F32 cos_angle_to_view_dir;
 	BOOL in_frustum = calcPixelArea(cos_angle_to_view_dir, radius);
 
 	if (mPixelArea < F_ALMOST_ZERO || !in_frustum)
@@ -2085,9 +2079,9 @@ F32 LLFace::getTextureVirtualSize()
 	if(face_area > LLViewerTexture::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping.
 	{
 		if(mImportanceToCamera > LEAST_IMPORTANCE_FOR_LARGE_IMAGE && mTexture[LLRender::DIFFUSE_MAP].notNull() && mTexture[LLRender::DIFFUSE_MAP]->isLargeImage())
-		{		
+		{
 			face_area *= adjustPartialOverlapPixelArea(cos_angle_to_view_dir, radius );
-		}	
+		}
 	}
 
 	setVirtualSize(face_area) ;
@@ -2135,7 +2129,7 @@ BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
 	LLVector4a t;
 	t.load3(camera->getOrigin().mV);
 	lookAt.setSub(center, t);
-	
+
 	F32 dist = lookAt.getLength3().getF32();
 	dist = llmax(dist-size.getLength3().getF32(), 0.001f);
 	//ramp down distance for nearby objects
@@ -2146,7 +2140,7 @@ BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
 		dist *= 16.f;
 	}
 
-	lookAt.normalize3fast() ;	
+	lookAt.normalize3fast() ;
 
 	//get area of circle around node
 	F32 app_angle = atanf((F32) sqrt(size_squared) / dist);
@@ -2156,10 +2150,10 @@ BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
 	x_axis.load3(camera->getXAxis().mV);
 	cos_angle_to_view_dir = lookAt.dot3(x_axis).getF32();
 
-	//if has media, check if the face is out of the view frustum.	
+	//if has media, check if the face is out of the view frustum.
 	if(hasMedia())
 	{
-		if(!camera->AABBInFrustum(center, size)) 
+		if(!camera->AABBInFrustum(center, size))
 		{
 			mImportanceToCamera = 0.f ;
 			return false ;
@@ -2169,7 +2163,7 @@ BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
 			cos_angle_to_view_dir = 1.0f ;
 		}
 		else
-		{		
+		{
 			LLVector4a d;
 			d.setSub(lookAt, x_axis);
 
@@ -2186,7 +2180,7 @@ BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
 		mImportanceToCamera = 1.0f ;
 	}
 	else
-	{		
+	{
 		mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ;
 	}
 
@@ -2207,10 +2201,10 @@ F32 LLFace::adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius
 		//F32 radius_square = radius * radius ;
 		//F32 d_square = d * d ;
 		//F32 screen_radius_square = screen_radius * screen_radius ;
-		//face_area = 
+		//face_area =
 		//	radius_square * acosf((d_square + radius_square - screen_radius_square)/(2 * d * radius)) +
 		//	screen_radius_square * acosf((d_square + screen_radius_square - radius_square)/(2 * d * screen_radius)) -
-		//	0.5f * sqrtf((-d + radius + screen_radius) * (d + radius - screen_radius) * (d - radius + screen_radius) * (d + radius + screen_radius)) ;			
+		//	0.5f * sqrtf((-d + radius + screen_radius) * (d + radius - screen_radius) * (d - radius + screen_radius) * (d + radius + screen_radius)) ;
 		//----------------------------------------------
 
 		//the above calculation is too expensive
@@ -2228,13 +2222,13 @@ const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL][2] = //
 const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[FACE_IMPORTANCE_LEVEL][2] =    //{cos(angle), importance_weight}
 	{{0.985f /*cos(10 degrees)*/, 1.0f}, {0.94f /*cos(20 degrees)*/, 0.8f}, {0.866f /*cos(30 degrees)*/, 0.64f}, {0.0f, 0.36f}} ;
 
-//static 
+//static
 F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist)
 {
 	F32 importance = 0.f ;
-	
-	if(cos_angle_to_view_dir > LLViewerCamera::getInstance()->getCosHalfFov() && 
-		dist < FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL - 1][0]) 
+
+	if(cos_angle_to_view_dir > LLViewerCamera::getInstance()->getCosHalfFov() &&
+		dist < FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL - 1][0])
 	{
 		LLViewerCamera* camera = LLViewerCamera::getInstance();
 		F32 camera_moving_speed = camera->getAverageSpeed() ;
@@ -2245,12 +2239,12 @@ F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist)
 			//if camera moves or rotates too fast, ignore the importance factor
 			return 0.f ;
 		}
-		
+
 		S32 i = 0 ;
 		for(i = 0; i < FACE_IMPORTANCE_LEVEL && dist > FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][0]; ++i);
 		i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ;
 		F32 dist_factor = FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][1] ;
-		
+
 		for(i = 0; i < FACE_IMPORTANCE_LEVEL && cos_angle_to_view_dir < FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][0] ; ++i) ;
 		i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ;
 		importance = dist_factor * FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][1] ;
@@ -2259,7 +2253,7 @@ F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist)
 	return importance ;
 }
 
-//static 
+//static
 F32 LLFace::adjustPixelArea(F32 importance, F32 pixel_area)
 {
 	if(pixel_area > LLViewerTexture::sMaxSmallImageSize)
@@ -2274,7 +2268,7 @@ F32 LLFace::adjustPixelArea(F32 importance, F32 pixel_area)
 			if(importance < LEAST_IMPORTANCE_FOR_LARGE_IMAGE)//if the face is not important, do not load hi-res.
 			{
 				pixel_area = LLViewerTexture::sMinLargeImageSize ;
-			}				
+			}
 		}
 	}
 
@@ -2289,7 +2283,7 @@ BOOL LLFace::verify(const U32* indices_array) const
 	{ //no vertex buffer, face is implicitly valid
 		return TRUE;
 	}
-	
+
 	// First, check whether the face data fits within the pool's range.
 	if ((mGeomIndex + mGeomCount) > mVertexBuffer->getNumVerts())
 	{
@@ -2298,18 +2292,18 @@ BOOL LLFace::verify(const U32* indices_array) const
 	}
 
 	S32 indices_count = (S32)getIndicesCount();
-	
+
 	if (!indices_count)
 	{
 		return TRUE;
 	}
-	
+
 	if (indices_count > LL_MAX_INDICES_COUNT)
 	{
 		ok = FALSE;
 		LL_INFOS() << "Face has bogus indices count" << LL_ENDL;
 	}
-	
+
 	if (mIndicesIndex + mIndicesCount > mVertexBuffer->getNumIndices())
 	{
 		ok = FALSE;
@@ -2368,7 +2362,7 @@ S32 LLFace::getColors(LLStrider<LLColor4U> &colors)
 	{
 		return -1;
 	}
-	
+
 	// llassert(mGeomIndex >= 0);
 	mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount);
 	return mGeomIndex;
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index c1f4f858c1..9d4022fda1 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -1,25 +1,25 @@
-/** 
+/**
  * @file llviewerstats.cpp
  * @brief LLViewerStats class implementation
  *
  * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -36,10 +36,10 @@
 
 #include "llappviewer.h"
 
-#include "pipeline.h" 
-#include "lltexturefetch.h" 
-#include "llviewerobjectlist.h" 
-#include "llviewertexturelist.h" 
+#include "pipeline.h"
+#include "lltexturefetch.h"
+#include "llviewerobjectlist.h"
+#include "llviewertexturelist.h"
 #include "lltexlayer.h"
 #include "lltexlayerparams.h"
 #include "llsurface.h"
@@ -67,11 +67,6 @@
 #include "lluiusage.h"
 #include "lltranslate.h"
 
-#if LL_LINUX
-#pragma GCC diagnostic ignored "-Wunused-value" // Happens due to LL_DEBUGS("LogViewerStatsPacket"); Does that even do anything?
-#endif
-
-
 // "Minimal Vulkan" to get max API Version
 
 // Calls
@@ -147,13 +142,13 @@ LLTrace::CountStatHandle<>	FPS("FPS", "Frames rendered"),
 							TEX_REBAKES("texrebakes", "Number of times avatar textures have been forced to rebake"),
 							NUM_NEW_OBJECTS("numnewobjectsstat", "Number of objects in scene that were not previously in cache");
 
-LLTrace::CountStatHandle<LLUnit<F64, LLUnits::Kilotriangles> > 
+LLTrace::CountStatHandle<LLUnit<F64, LLUnits::Kilotriangles> >
 							TRIANGLES_DRAWN("trianglesdrawnstat");
 
 LLTrace::EventStatHandle<LLUnit<F64, LLUnits::Kilotriangles> >
 							TRIANGLES_DRAWN_PER_FRAME("trianglesdrawnperframestat");
 
-LLTrace::CountStatHandle<F64Kilobytes >	
+LLTrace::CountStatHandle<F64Kilobytes >
 							ACTIVE_MESSAGE_DATA_RECEIVED("activemessagedatareceived", "Message system data received on all active regions"),
 							LAYERS_NETWORK_DATA_RECEIVED("layersdatareceived", "Network data received for layer data (terrain)"),
 							OBJECT_NETWORK_DATA_RECEIVED("objectdatareceived", "Network data received for objects"),
@@ -162,7 +157,7 @@ LLTrace::CountStatHandle<F64Kilobytes >
 							MESSAGE_SYSTEM_DATA_IN("messagedatain", "Incoming message system network data"),
 							MESSAGE_SYSTEM_DATA_OUT("messagedataout", "Outgoing message system network data");
 
-LLTrace::CountStatHandle<F64Seconds >	
+LLTrace::CountStatHandle<F64Seconds >
 							SIM_20_FPS_TIME("sim20fpstime", "Seconds with sim FPS below 20"),
 							SIM_PHYSICS_20_FPS_TIME("simphysics20fpstime", "Seconds with physics FPS below 20"),
 							LOSS_5_PERCENT_TIME("loss5percenttime", "Seconds with packet loss > 5%");
@@ -186,7 +181,7 @@ SimMeasurement<>			SIM_TIME_DILATION("simtimedilation", "Simulator time scale",
 							SIM_PHYSICS_PINNED_TASKS("physicspinnedtasks", "", LL_SIM_STAT_PHYSICS_PINNED_TASKS),
 							SIM_PHYSICS_LOD_TASKS("physicslodtasks", "", LL_SIM_STAT_PHYSICS_LOD_TASKS);
 
-SimMeasurement<LLUnit<F64, LLUnits::Percent> >	
+SimMeasurement<LLUnit<F64, LLUnits::Percent> >
 							SIM_PERCENTAGE_SCRIPTS_RUN("simpctscriptsrun", "", LL_SIM_STAT_PCTSCRIPTSRUN),
 							SIM_SKIPPED_CHARACTERS_PERCENTAGE("simsimpctsteppedcharacters", "", LL_SIM_STAT_PCTSTEPPEDCHARACTERS);
 
@@ -203,17 +198,17 @@ LLTrace::SampleStatHandle<>	FPS_SAMPLE("fpssample"),
 							WINDOW_WIDTH("windowwidth", "Window width"),
 							WINDOW_HEIGHT("windowheight", "Window height");
 
-LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > 
+LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> >
 							PACKETS_LOST_PERCENT("packetslostpercentstat");
 
-static LLTrace::SampleStatHandle<bool> 
+static LLTrace::SampleStatHandle<bool>
 							CHAT_BUBBLES("chatbubbles", "Chat Bubbles Enabled");
 
 LLTrace::SampleStatHandle<F64Megabytes > FORMATTED_MEM("formattedmemstat");
 LLTrace::SampleStatHandle<F64Kilobytes >	DELTA_BANDWIDTH("deltabandwidth", "Increase/Decrease in bandwidth based on packet loss"),
 															MAX_BANDWIDTH("maxbandwidth", "Max bandwidth setting");
 
-	
+
 SimMeasurement<F64Milliseconds >	SIM_FRAME_TIME("simframemsec", "", LL_SIM_STAT_FRAMEMS),
 													SIM_NET_TIME("simnetmsec", "", LL_SIM_STAT_NETMS),
 													SIM_OTHER_TIME("simsimothermsec", "", LL_SIM_STAT_SIMOTHERMS),
@@ -228,7 +223,7 @@ SimMeasurement<F64Milliseconds >	SIM_FRAME_TIME("simframemsec", "", LL_SIM_STAT_
 													SIM_SPARE_TIME("simsparemsec", "", LL_SIM_STAT_SIMSPARETIME),
 													SIM_SLEEP_TIME("simsleepmsec", "", LL_SIM_STAT_SIMSLEEPTIME),
 													SIM_PUMP_IO_TIME("simpumpiomsec", "", LL_SIM_STAT_IOPUMPTIME);
-	
+
 SimMeasurement<F64Kilobytes >	SIM_UNACKED_BYTES("simtotalunackedbytes", "", LL_SIM_STAT_TOTAL_UNACKED_BYTES);
 SimMeasurement<F64Megabytes >	SIM_PHYSICS_MEM("physicsmemoryallocated", "", LL_SIM_STAT_SIMPHYSICSMEMORY);
 
@@ -240,7 +235,7 @@ LLTrace::SampleStatHandle<F64Milliseconds >	FRAMETIME_JITTER("frametimejitter",
 LLTrace::EventStatHandle<LLUnit<F64, LLUnits::Meters> > AGENT_POSITION_SNAP("agentpositionsnap", "agent position corrections");
 
 LLTrace::EventStatHandle<>	LOADING_WEARABLES_LONG_DELAY("loadingwearableslongdelay", "Wearables took too long to load");
-	
+
 LLTrace::EventStatHandle<F64Milliseconds >	REGION_CROSSING_TIME("regioncrossingtime", "CROSSING_AVG"),
 																FRAME_STACKTIME("framestacktime", "FRAME_SECS"),
 																UPDATE_STACKTIME("updatestacktime", "UPDATE_SECS"),
@@ -248,7 +243,7 @@ LLTrace::EventStatHandle<F64Milliseconds >	REGION_CROSSING_TIME("regioncrossingt
 																IMAGE_STACKTIME("imagestacktime", "IMAGE_SECS"),
 																REBUILD_STACKTIME("rebuildstacktime", "REBUILD_SECS"),
 																RENDER_STACKTIME("renderstacktime", "RENDER_SECS");
-	
+
 LLTrace::EventStatHandle<F64Seconds >	AVATAR_EDIT_TIME("avataredittime", "Seconds in Edit Appearance"),
 															TOOLBOX_TIME("toolboxtime", "Seconds using Toolbox"),
 															MOUSELOOK_TIME("mouselooktime", "Seconds in Mouselook"),
@@ -268,7 +263,7 @@ LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> >  SWAP_FRAME_PCT("swap_
 LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> >  IDLE_FRAME_PCT("idle_frame_pct");
 }
 
-LLViewerStats::LLViewerStats() 
+LLViewerStats::LLViewerStats()
 :	mLastTimeDiff(0.0)
 {
 	getRecording().start();
@@ -288,20 +283,20 @@ void LLViewerStats::updateFrameStats(const F64Seconds time_diff)
 	{
 		add(LLStatViewer::LOSS_5_PERCENT_TIME, time_diff);
 	}
-	
+
 	F32 sim_fps = getRecording().getLastValue(LLStatViewer::SIM_FPS);
 	if (0.f < sim_fps && sim_fps < 20.f)
 	{
 		add(LLStatViewer::SIM_20_FPS_TIME, time_diff);
 	}
-	
+
 	F32 sim_physics_fps = getRecording().getLastValue(LLStatViewer::SIM_PHYSICS_FPS);
 
 	if (0.f < sim_physics_fps && sim_physics_fps < 20.f)
 	{
 		add(LLStatViewer::SIM_PHYSICS_20_FPS_TIME, time_diff);
 	}
-		
+
 	if (time_diff >= (F64Seconds)0.5)
 	{
 		record(LLStatViewer::FPS_2_TIME, time_diff);
@@ -325,7 +320,7 @@ void LLViewerStats::updateFrameStats(const F64Seconds time_diff)
 		// old stats that were never really used
 		F64Seconds jit = (F64Seconds) std::fabs((mLastTimeDiff - time_diff));
 		sample(LLStatViewer::FRAMETIME_JITTER, jit);
-			
+
 		F32Seconds average_frametime = gRenderStartTime.getElapsedTimeF32() / (F32)gFrameCount;
 		sample(LLStatViewer::FRAMETIME_SLEW, F64Milliseconds (average_frametime - time_diff));
 
@@ -334,39 +329,39 @@ void LLViewerStats::updateFrameStats(const F64Seconds time_diff)
 		sample(LLStatViewer::DELTA_BANDWIDTH, F64Bits(delta_bandwidth));
 		sample(LLStatViewer::MAX_BANDWIDTH, F64Bits(max_bandwidth));
 	}
-	
+
 	mLastTimeDiff = time_diff;
 }
 
 void LLViewerStats::addToMessage(LLSD &body)
 {
 	LLSD &misc = body["misc"];
-	
+
 	misc["Version"] = TRUE;
 	//TODO RN: get last value, not mean
 	misc["Vertex Buffers Enabled"] = getRecording().getMean(LLStatViewer::ENABLE_VBO);
-	
+
 	body["AgentPositionSnaps"] = getRecording().getSum(LLStatViewer::AGENT_POSITION_SNAP).value(); //mAgentPositionSnaps.asLLSD();
-	LL_INFOS() << "STAT: AgentPositionSnaps: Mean = " << getRecording().getMean(LLStatViewer::AGENT_POSITION_SNAP).value() << "; StdDev = " << getRecording().getStandardDeviation(LLStatViewer::AGENT_POSITION_SNAP).value() 
+	LL_INFOS() << "STAT: AgentPositionSnaps: Mean = " << getRecording().getMean(LLStatViewer::AGENT_POSITION_SNAP).value() << "; StdDev = " << getRecording().getStandardDeviation(LLStatViewer::AGENT_POSITION_SNAP).value()
 			<< "; Count = " << getRecording().getSampleCount(LLStatViewer::AGENT_POSITION_SNAP) << LL_ENDL;
 }
 
 // *NOTE:Mani The following methods used to exist in viewer.cpp
 // Moving them here, but not merging them into LLViewerStats yet.
-U32		gTotalLandIn = 0, 
+U32		gTotalLandIn = 0,
 		gTotalLandOut = 0,
-		gTotalWaterIn = 0, 
+		gTotalWaterIn = 0,
 		gTotalWaterOut = 0;
 
-F32		gAveLandCompression = 0.f, 
+F32		gAveLandCompression = 0.f,
 		gAveWaterCompression = 0.f,
 		gBestLandCompression = 1.f,
 		gBestWaterCompression = 1.f,
-		gWorstLandCompression = 0.f, 
+		gWorstLandCompression = 0.f,
 		gWorstWaterCompression = 0.f;
 
-U32Bytes				gTotalWorldData, 
-								gTotalObjectData, 
+U32Bytes				gTotalWorldData,
+								gTotalObjectData,
 								gTotalTextureData;
 U32								gSimPingCount = 0;
 U32Bits				gObjectData;
@@ -447,7 +442,7 @@ void update_statistics()
         world->updateNetStats();
         world->requestCacheMisses();
     }
-	
+
 	// Reset all of these values.
 	gVLManager.resetBitCounts();
 	gObjectData = (U32Bytes)0;
@@ -481,7 +476,7 @@ void update_statistics()
             // auto tot_avatar_render_time_raw = tot_avatar_time_raw - tot_av_idle_time_raw;
             // the time spent this frame on the "display()" call. Treated as "tot time rendering"
             auto tot_render_time_raw = LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_DISPLAY);
-            // sleep time is basically forced sleep when window out of focus 
+            // sleep time is basically forced sleep when window out of focus
             auto tot_sleep_time_raw = LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_SLEEP);
             // time spent on UI
             auto tot_ui_time_raw = LLPerfStats::StatsRecorder::getSceneStat(LLPerfStats::StatType_t::RENDER_UI);
@@ -577,11 +572,11 @@ void send_viewer_stats(bool include_preferences)
 		LL_WARNS() << "Could not get ViewerStats capability" << LL_ENDL;
 		return;
 	}
-	
+
 	LLViewerStats::instance().getRecording().pause();
 
 	LLSD &agent = body["agent"];
-	
+
 	time_t ltime;
 	time(&ltime);
 	F32 run_time = F32(LLFrameTimer::getElapsedSeconds());
@@ -607,7 +602,7 @@ void send_viewer_stats(bool include_preferences)
 	agent["version"] = LLVersionInfo::instance().getChannelAndVersion();
 	std::string language = LLUI::getLanguage();
 	agent["language"] = language;
-	
+
 	agent["sim_fps"] = ((F32) gFrameCount - gSimFrames) /
 		(F32) (gRenderStartTime.getElapsedTimeF32() - gSimLastTime);
 
@@ -622,7 +617,7 @@ void send_viewer_stats(bool include_preferences)
 	agent["translation"] = LLTranslate::instance().asLLSD();
 
 	LLSD &system = body["system"];
-	
+
 	system["ram"] = (S32) gSysMemory.getPhysicalMemoryKB().value();
 	system["os"] = LLOSInfo::instance().getOSStringSimple();
 	system["cpu"] = gSysCPU.getCPUString();
@@ -673,7 +668,7 @@ void send_viewer_stats(bool include_preferences)
 	{
 		shader_level = 2;
 	}
-	
+
 
 
 	system["shader_level"] = shader_level;
@@ -692,9 +687,9 @@ void send_viewer_stats(bool include_preferences)
 	in["compressed_packets"] = (S32) gMessageSystem->mCompressedPacketsIn;
 	in["savings"] = (gMessageSystem->mUncompressedBytesIn -
 					 gMessageSystem->mCompressedBytesIn) / 1024.0;
-	
+
 	LLSD &out = body["stats"]["net"]["out"];
-	
+
 	out["kbytes"] = gMessageSystem->mTotalBytesOut / 1024.0;
 	out["packets"] = (S32) gMessageSystem->mPacketsOut;
 	out["compressed_packets"] = (S32) gMessageSystem->mCompressedPacketsOut;
@@ -717,7 +712,7 @@ void send_viewer_stats(bool include_preferences)
 	gInventory.mValidationInfo->asLLSD(validation_info);
 
 	body["ui"] = LLUIUsage::instance().asLLSD();
-		
+
 	body["stats"]["voice"] = LLVoiceVivoxStats::getInstance()->read();
 
 	// Misc stats, two strings and two ints
-- 
cgit v1.2.3


From e4dd93ed3c0c503f121865917115eef543df5368 Mon Sep 17 00:00:00 2001
From: Alexander Gavriliuk <alexandrgproductengine@lindenlab.com>
Date: Sun, 14 Apr 2024 03:00:41 +0200
Subject: secondlife/viewer#912 BugSplat Crash 1412267: nvoglv64+0xadcd00

---
 indra/llprimitive/lldaeloader.cpp   |  44 ++++------
 indra/llprimitive/llmodel.cpp       |  18 ++--
 indra/llprimitive/llmodel.h         |   6 +-
 indra/llprimitive/llmodelloader.cpp |  33 +++----
 indra/llprimitive/llmodelloader.h   |  45 +++++-----
 indra/newview/llmodelpreview.cpp    | 166 +++++++++++++++++++-----------------
 6 files changed, 152 insertions(+), 160 deletions(-)

(limited to 'indra')

diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 2e4b013b77..97d48f6873 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -65,7 +65,7 @@
 #include <boost/regex.hpp>
 #include <boost/algorithm/string/replace.hpp>
 
-std::string colladaVersion[VERSIONTYPE_COUNT+1] = 
+std::string colladaVersion[VERSIONTYPE_COUNT+1] =
 {
 	"1.4.0",
 	"1.4.1",
@@ -1119,22 +1119,20 @@ bool LLDAELoader::OpenFile(const std::string& filename)
 	{ //add skinned meshes as instances
 		domSkin* skin = NULL;
 		db->getElement((daeElement**) &skin, idx, NULL, COLLADA_TYPE_SKIN);
-		
+
 		if (skin)
 		{
-			domGeometry* geom = daeSafeCast<domGeometry>(skin->getSource().getElement());
-			
-			if (geom)
+			if (domGeometry* geom = daeSafeCast<domGeometry>(skin->getSource().getElement()))
 			{
-				domMesh* mesh = geom->getMesh();
-				if (mesh)
+				if (domMesh* mesh = geom->getMesh())
 				{
-					std::vector< LLPointer< LLModel > >::iterator i = mModelsMap[mesh].begin();
-					while (i != mModelsMap[mesh].end())
+					dae_model_map::const_iterator it = mModelsMap.find(mesh);
+					if (it != mModelsMap.end())
 					{
-						LLPointer<LLModel> mdl = *i;
-						LLDAELoader::processDomModel(mdl, &dae, root, mesh, skin);
-						i++;
+						for (const LLPointer<LLModel>& model : it->second)
+						{
+							LLDAELoader::processDomModel(model, &dae, root, mesh, skin);
+						}
 					}
 				}
 			}
@@ -1304,6 +1302,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
 			}
 		}
 		else
+		{
 			//Has one or more skeletons
             for (std::vector<domInstance_controller::domSkeleton*>::iterator skel_it = skeletons.begin();
                  skel_it != skeletons.end(); ++skel_it)
@@ -1388,6 +1387,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
                     }
                 }//got skeleton?
             }
+        }
 
 
 		domSkin::domJoints* joints = skin->getJoints();
@@ -1688,7 +1688,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
 			materials[model->mMaterialList[i]] = LLImportMaterial();
 		}
 		mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials));
-		stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform);
+		stretch_extents(model, transformation);
 	}
 }
 
@@ -2081,21 +2081,14 @@ void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* da
 		mTransform.condition();
 	}
 
-	domInstance_geometry* instance_geo = daeSafeCast<domInstance_geometry>(element);
-	if (instance_geo)
+	if (domInstance_geometry* instance_geo = daeSafeCast<domInstance_geometry>(element))
 	{
-		domGeometry* geo = daeSafeCast<domGeometry>(instance_geo->getUrl().getElement());
-		if (geo)
+		if (domGeometry* geo = daeSafeCast<domGeometry>(instance_geo->getUrl().getElement()))
 		{
-			domMesh* mesh = daeSafeCast<domMesh>(geo->getDescendant(daeElement::matchType(domMesh::ID())));
-			if (mesh)
+			if (domMesh* mesh = daeSafeCast<domMesh>(geo->getDescendant(daeElement::matchType(domMesh::ID()))))
 			{
-
-				std::vector< LLPointer< LLModel > >::iterator i = mModelsMap[mesh].begin();				
-				while (i != mModelsMap[mesh].end())
+				for (LLModel* model : mModelsMap.find(mesh)->second)
 				{
-					LLModel* model = *i;
-
 					LLMatrix4 transformation = mTransform;
 				
 					if (mTransform.determinant() < 0)
@@ -2166,8 +2159,7 @@ void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* da
 					}
 
 					mScene[transformation].push_back(LLModelInstance(model, label, transformation, materials));
-					stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform);
-					i++;
+					stretch_extents(model, transformation);
 				}
 			}
 		}
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index d56ffdc317..aea4cf676f 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -90,19 +90,15 @@ std::string LLModel::getStatusString(U32 status)
 }
 
 
-void LLModel::offsetMesh( const LLVector3& pivotPoint )
+void LLModel::offsetMesh(const LLVector3& pivotPoint)
 {
-	LLVector4a pivot( pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ] );
-	
-	for (std::vector<LLVolumeFace>::iterator faceIt = mVolumeFaces.begin(); faceIt != mVolumeFaces.end(); )
+	LLVector4a pivot(pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ]);
+
+	for (LLVolumeFace& face : mVolumeFaces)
 	{
-		std::vector<LLVolumeFace>:: iterator currentFaceIt = faceIt++;
-		LLVolumeFace& face = *currentFaceIt;
-		LLVector4a *pos = (LLVector4a*) face.mPositions;
-		
-		for (U32 i=0; i<face.mNumVertices; ++i )
+		for (U32 i = 0; i < face.mNumVertices; ++i)
 		{
-			pos[i].add( pivot );
+			face.mPositions[i].add(pivot);
 		}
 	}
 }
@@ -337,7 +333,7 @@ void LLModel::normalizeVolumeFaces()
 	}
 }
 
-void LLModel::getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out)
+void LLModel::getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out) const
 {
 	scale_out = mNormalizedScale;
 	translation_out = mNormalizedTranslation;
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index 4505d6b3b9..37736483c6 100644
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -199,8 +199,8 @@ public:
 	void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL);
     void remapVolumeFaces();
 	void optimizeVolumeFaces();
-	void offsetMesh( const LLVector3& pivotPoint );
-	void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out);
+	void offsetMesh(const LLVector3& pivotPoint);
+	void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out) const;
 	LLVector3 getTransformedCenter(const LLMatrix4& mat);
 	
 	//reorder face list based on mMaterialList in this and reference so 
@@ -365,7 +365,7 @@ class LLModelInstanceBase
 {
 public:
 	LLPointer<LLModel> mModel;
-	LLPointer<LLModel> mLOD[5];
+	LLPointer<LLModel> mLOD[LLModel::NUM_LODS];
 	LLUUID mMeshID;
 
 	LLMatrix4 mTransform;
diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp
index fc826727e1..e35aa0572f 100644
--- a/indra/llprimitive/llmodelloader.cpp
+++ b/indra/llprimitive/llmodelloader.cpp
@@ -37,7 +37,7 @@
 
 std::list<LLModelLoader*> LLModelLoader::sActiveLoaderList;
 
-void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform)
+static void stretch_extents(const LLModel* model, const LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, bool& first_transform)
 {
 	LLVector4a box[] =
 	{
@@ -59,7 +59,7 @@ void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4
 		center.setAdd(face.mExtents[0], face.mExtents[1]);
 		center.mul(0.5f);
 		LLVector4a size;
-		size.setSub(face.mExtents[1],face.mExtents[0]);
+		size.setSub(face.mExtents[1], face.mExtents[0]);
 		size.mul(0.5f);
 
 		for (U32 i = 0; i < 8; i++)
@@ -74,7 +74,7 @@ void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4
 
 			if (first_transform)
 			{
-				first_transform = FALSE;
+				first_transform = false;
 				min = max = v;
 			}
 			else
@@ -85,19 +85,19 @@ void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4
 	}
 }
 
-void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform)
+void LLModelLoader::stretch_extents(const LLModel* model, const LLMatrix4& mat)
 {
 	LLVector4a mina, maxa;
 	LLMatrix4a mata;
 
 	mata.loadu(mat);
-	mina.load3(min.mV);
-	maxa.load3(max.mV);
+	mina.load3(mExtents[0].mV);
+	maxa.load3(mExtents[1].mV);
 
-	stretch_extents(model, mata, mina, maxa, first_transform);
+	::stretch_extents(model, mata, mina, maxa, mFirstTransform);
 
-	min.set(mina.getF32ptr());
-	max.set(maxa.getF32ptr());
+	mExtents[0].set(mina.getF32ptr());
+	mExtents[1].set(maxa.getF32ptr());
 }
 
 //-----------------------------------------------------------------------------
@@ -121,7 +121,7 @@ LLModelLoader::LLModelLoader(
 , mFilename(filename)
 , mLod(lod)
 , mTrySLM(false)
-, mFirstTransform(TRUE)
+, mFirstTransform(true)
 , mNumOfFetchingTextures(0)
 , mLoadCallback(load_cb)
 , mJointLookupFunc(joint_lookup_func)
@@ -292,14 +292,7 @@ bool LLModelLoader::loadFromSLM(const std::string& filename)
 			{
 				if (idx >= model[lod].size())
 				{
-					if (model[lod].size())
-					{
-						instance_list[i].mLOD[lod] = model[lod][0];
-					}
-					else
-					{
-						instance_list[i].mLOD[lod] = NULL;
-					}					
+					instance_list[i].mLOD[lod] = model[lod].front();
 					continue;
 				}
 
@@ -337,12 +330,12 @@ bool LLModelLoader::loadFromSLM(const std::string& filename)
 
 
 	//convert instance_list to mScene
-	mFirstTransform = TRUE;
+	mFirstTransform = true;
 	for (U32 i = 0; i < instance_list.size(); ++i)
 	{
 		LLModelInstance& cur_instance = instance_list[i];
 		mScene[cur_instance.mTransform].push_back(cur_instance);
-		stretch_extents(cur_instance.mModel, cur_instance.mTransform, mExtents[0], mExtents[1], mFirstTransform);
+		stretch_extents(cur_instance.mModel, cur_instance.mTransform);
 	}
 	
 	setLoadState( DONE );
diff --git a/indra/llprimitive/llmodelloader.h b/indra/llprimitive/llmodelloader.h
index fbc74554a0..0c766e0b53 100644
--- a/indra/llprimitive/llmodelloader.h
+++ b/indra/llprimitive/llmodelloader.h
@@ -34,13 +34,13 @@
 
 class LLJoint;
 
-typedef std::map<std::string, LLMatrix4>			JointTransformMap;
-typedef std::map<std::string, LLMatrix4>::iterator	JointTransformMapIt;
-typedef std::map<std::string, std::string>			JointMap;
-typedef std::deque<std::string>						JointNameSet;
+typedef std::map<std::string, LLMatrix4> JointTransformMap;
+typedef std::map<std::string, LLMatrix4>::iterator JointTransformMapIt;
+typedef std::map<std::string, std::string> JointMap;
+typedef std::deque<std::string> JointNameSet;
 
 const S32 SLM_SUPPORTED_VERSION	= 3;
-const S32 NUM_LOD						= 4;
+const S32 NUM_LOD = 4;
 
 const U32 LEGACY_RIG_OK = 0;
 const U32 LEGACY_RIG_FLAG_TOO_MANY_JOINTS = 1;
@@ -50,32 +50,32 @@ class LLModelLoader : public LLThread
 {
 public:
 
-	typedef std::map<std::string, LLImportMaterial>			material_map;
-	typedef std::vector<LLPointer<LLModel > >					model_list;	
-	typedef std::vector<LLModelInstance>						model_instance_list;	
-	typedef std::map<LLMatrix4, model_instance_list >		scene;
+	typedef std::map<std::string, LLImportMaterial> material_map;
+	typedef std::vector<LLPointer<LLModel>> model_list;
+	typedef std::vector<LLModelInstance> model_instance_list;
+	typedef std::map<LLMatrix4, model_instance_list> scene;
 
 	// Callback with loaded model data and loaded LoD
-	// 
-	typedef boost::function<void (scene&,model_list&,S32,void*) >		load_callback_t;
+	//
+	typedef boost::function<void (scene&, model_list&, S32, void*)> load_callback_t;
 
 	// Function to provide joint lookup by name
 	// (within preview avi skeleton, for example)
 	//
-	typedef boost::function<LLJoint* (const std::string&,void*) >		joint_lookup_func_t;
+	typedef boost::function<LLJoint* (const std::string&, void*)> joint_lookup_func_t;
 
 	// Func to load and associate material with all it's textures,
 	// returned value is the number of textures loaded
 	// intentionally non-const so func can modify material to
 	// store platform-specific data
 	//
-	typedef boost::function<U32 (LLImportMaterial&,void*) >				texture_load_func_t;
+	typedef boost::function<U32 (LLImportMaterial&, void*)> texture_load_func_t;
 
 	// Callback to inform client of state changes
 	// during loading process (errors will be reported
 	// as state changes here as well)
 	//
-	typedef boost::function<void (U32,void*) >								state_callback_t;
+	typedef boost::function<void (U32, void*)> state_callback_t;
 
 	typedef enum
 	{
@@ -104,7 +104,7 @@ public:
 	S32 mLod;
 	
 	LLMatrix4 mTransform;
-	BOOL mFirstTransform;
+	bool mFirstTransform;
 	LLVector3 mExtents[2];
 	
 	bool mTrySLM;
@@ -136,7 +136,7 @@ public:
 		JointNameSet&						jointsFromNodes,
         JointMap&                           legalJointNamesMap,
         U32									maxJointsPerMesh);
-	virtual ~LLModelLoader() ;
+	virtual ~LLModelLoader();
 
 	virtual void setNoNormalize() { mNoNormalize = true; }
 	virtual void setNoOptimize() { mNoOptimize = true; }
@@ -156,13 +156,13 @@ public:
 	bool loadFromSLM(const std::string& filename);
 	
 	void loadModelCallback();
-	void loadTextures() ; //called in the main thread.
+	void loadTextures(); // called in the main thread.
 	void setLoadState(U32 state);
 
-	
+	void stretch_extents(const LLModel* model, const LLMatrix4& mat);
 
-	S32 mNumOfFetchingTextures ; //updated in the main thread
-	bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread.
+	S32 mNumOfFetchingTextures; // updated in the main thread
+	bool areTexturesReady() { return !mNumOfFetchingTextures; } // called in the main thread.
 
 	bool verifyCount( int expected, int result );
 
@@ -212,10 +212,7 @@ protected:
 	LLSD mWarningsArray; // preview floater will pull logs from here
 
 	static std::list<LLModelLoader*> sActiveLoaderList;
-	static bool isAlive(LLModelLoader* loader) ;
+	static bool isAlive(LLModelLoader* loader);
 };
-class LLMatrix4a;
-void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform);
-void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform);
 
 #endif  // LL_LLMODELLOADER_H
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index 8fbcf8e18d..16182ad940 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -132,25 +132,17 @@ std::string getLodSuffix(S32 lod)
 
 void FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut)
 {
-    LLModelLoader::scene::iterator base_iter = scene.begin();
-    bool found = false;
-    while (!found && (base_iter != scene.end()))
+    for (auto scene_iter = scene.begin(); scene_iter != scene.end(); scene_iter++)
     {
-        matOut = base_iter->first;
-
-        LLModelLoader::model_instance_list::iterator base_instance_iter = base_iter->second.begin();
-        while (!found && (base_instance_iter != base_iter->second.end()))
+        for (auto model_iter = scene_iter->second.begin(); model_iter != scene_iter->second.end(); model_iter++)
         {
-            LLModelInstance& base_instance = *base_instance_iter++;
-            LLModel* base_model = base_instance.mModel;
-
-            if (base_model && (base_model->mLabel == name_to_match))
+            if (model_iter->mModel && (model_iter->mModel->mLabel == name_to_match))
             {
-                baseModelOut = base_model;
+                baseModelOut = model_iter->mModel;
+                matOut = scene_iter->first;
                 return;
             }
         }
-        base_iter++;
     }
 }
 
@@ -210,9 +202,12 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
 
 LLModelPreview::~LLModelPreview()
 {
+    LLMutexLock lock(this);
+
     if (mModelLoader)
     {
         mModelLoader->shutdown();
+        mModelLoader = NULL;
     }
 
     if (mPreviewAvatar)
@@ -250,7 +245,7 @@ void LLModelPreview::updateDimentionsAndOffsets()
             accounted.insert(instance.mModel);
 
             // update instance skin info for each lods pelvisZoffset
-            for (int j = 0; j<LLModel::NUM_LODS; ++j)
+            for (int j = 0; j < LLModel::NUM_LODS; ++j)
             {
                 if (instance.mLOD[j])
                 {
@@ -291,7 +286,7 @@ void LLModelPreview::rebuildUploadData()
     BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching");
     U32 load_state = 0;
 
-    for (LLModelLoader::scene::iterator iter = mBaseScene.begin(); iter != mBaseScene.end(); ++iter)
+    for (auto iter = mBaseScene.begin(); iter != mBaseScene.end(); ++iter)
     { //for each transform in scene
         LLMatrix4 mat = iter->first;
 
@@ -310,9 +305,9 @@ void LLModelPreview::rebuildUploadData()
 
         mat *= scale_mat;
 
-        for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end();)
+        for (auto model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
         { // for each instance with said transform applied
-            LLModelInstance instance = *model_iter++;
+            LLModelInstance instance = *model_iter;
 
             LLModel* base_model = instance.mModel;
 
@@ -872,7 +867,7 @@ void LLModelPreview::clearIncompatible(S32 lod)
                 {
                     mBaseModel = mModel[lod];
                     mBaseScene = mScene[lod];
-                    mVertexBuffer[5].clear();
+                    mVertexBuffer[LLModel::NUM_LODS].clear();
                     replaced_base_model = true;
                 }
             }
@@ -1071,7 +1066,7 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod)
             mBaseModel = mModel[loaded_lod];
 
             mBaseScene = mScene[loaded_lod];
-            mVertexBuffer[5].clear();
+            mVertexBuffer[LLModel::NUM_LODS].clear();
         }
         else
         {
@@ -1175,7 +1170,7 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod)
     {
         if (!mBaseModel.empty())
         {
-            const std::string& model_name = mBaseModel[0]->getName();
+            std::string model_name = mBaseModel.front()->getName();
             LLLineEditor* description_form = mFMP->getChild<LLLineEditor>("description_form");
             if (description_form->getText().empty())
             {
@@ -1196,6 +1191,8 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod)
 
 void LLModelPreview::resetPreviewTarget()
 {
+    LLMutexLock lock(this);
+
     if (mModelLoader)
     {
         mPreviewTarget = (mModelLoader->mExtents[0] + mModelLoader->mExtents[1]) * 0.5f;
@@ -1241,7 +1238,7 @@ void LLModelPreview::generateNormals()
             (*it)->generateNormals(angle_cutoff);
         }
 
-        mVertexBuffer[5].clear();
+        mVertexBuffer[LLModel::NUM_LODS].clear();
     }
 
     bool perform_copy = mModelFacesCopy[which_lod].empty();
@@ -2083,7 +2080,7 @@ void LLModelPreview::updateStatusMessages()
     S32 total_verts[LLModel::NUM_LODS];
     S32 total_submeshes[LLModel::NUM_LODS];
 
-    for (U32 i = 0; i < LLModel::NUM_LODS - 1; i++)
+    for (U32 i = 0; i < LLModel::NUM_LODS; i++)
     {
         total_tris[i] = 0;
         total_verts[i] = 0;
@@ -2387,12 +2384,16 @@ void LLModelPreview::updateStatusMessages()
         }
     }
 
-    if (mModelNoErrors && mModelLoader)
+    if (mModelNoErrors)
     {
-        if (!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean())
+        LLMutexLock lock(this);
+        if (mModelLoader)
         {
-            // Some textures are still loading, prevent upload until they are done
-            mModelNoErrors = false;
+            if (!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean())
+            {
+                // Some textures are still loading, prevent upload until they are done
+                mModelNoErrors = false;
+            }
         }
     }
 
@@ -2721,10 +2722,10 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
 {
     LLModelLoader::model_list* model = NULL;
 
-    if (lod < 0 || lod > 4)
+    if (lod < 0 || lod >= LLModel::NUM_LODS)
     {
         model = &mBaseModel;
-        lod = 5;
+        lod = LLModel::NUM_LODS;
     }
     else
     {
@@ -2961,8 +2962,9 @@ void LLModelPreview::loadedCallback(
     S32 lod,
     void* opaque)
 {
-    LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque);
-    if (pPreview && !LLModelPreview::sIgnoreLoadedCallback)
+    LLModelPreview* pPreview = static_cast<LLModelPreview*>(opaque);
+    LLMutexLock lock(pPreview);
+    if (pPreview && pPreview->mModelLoader && !LLModelPreview::sIgnoreLoadedCallback)
     {
         // Load loader's warnings into floater's log tab
         const LLSD out = pPreview->mModelLoader->logOut();
@@ -2983,7 +2985,9 @@ void LLModelPreview::loadedCallback(
         }
 
         const LLVOAvatar* avatarp = pPreview->getPreviewAvatar();
-        if (avatarp) { // set up ground plane for possible rendering
+        if (avatarp && avatarp->mRoot && avatarp->mDrawable)
+        {
+            // set up ground plane for possible rendering
             const LLVector3 root_pos = avatarp->mRoot->getPosition();
             const LLVector4a* ext = avatarp->mDrawable->getSpatialExtents();
             const LLVector4a min = ext[0], max = ext[1];
@@ -3120,12 +3124,12 @@ BOOL LLModelPreview::render()
     LLMutexLock lock(this);
     mNeedsUpdate = FALSE;
 
-    bool edges = mViewOption["show_edges"];
-    bool joint_overrides = mViewOption["show_joint_overrides"];
-    bool joint_positions = mViewOption["show_joint_positions"];
-    bool skin_weight = mViewOption["show_skin_weight"];
-    bool textures = mViewOption["show_textures"];
-    bool physics = mViewOption["show_physics"];
+    bool show_edges = mViewOption["show_edges"];
+    bool show_joint_overrides = mViewOption["show_joint_overrides"];
+    bool show_joint_positions = mViewOption["show_joint_positions"];
+    bool show_skin_weight = mViewOption["show_skin_weight"];
+    bool show_textures = mViewOption["show_textures"];
+    bool show_physics = mViewOption["show_physics"];
 
     S32 width = getWidth();
     S32 height = getHeight();
@@ -3134,7 +3138,7 @@ BOOL LLModelPreview::render()
     LLGLDisable no_blend(GL_BLEND);
     LLGLEnable cull(GL_CULL_FACE);
     LLGLDepthTest depth(GL_FALSE); // SL-12781 disable z-buffer to render background color
-    
+
     {
         gUIProgram.bind();
 
@@ -3202,15 +3206,15 @@ BOOL LLModelPreview::render()
                     fmp->childSetValue("upload_skin", true);
                     mFirstSkinUpdate = false;
                     upload_skin = true;
-                    skin_weight = true;
+                    show_skin_weight = true;
                     mViewOption["show_skin_weight"] = true;
                 }
 
                 fmp->enableViewOption("show_skin_weight");
-                fmp->setViewOptionEnabled("show_joint_overrides", skin_weight);
-                fmp->setViewOptionEnabled("show_joint_positions", skin_weight);
+                fmp->setViewOptionEnabled("show_joint_overrides", show_skin_weight);
+                fmp->setViewOptionEnabled("show_joint_positions", show_skin_weight);
                 mFMP->childEnable("upload_skin");
-                mFMP->childSetValue("show_skin_weight", skin_weight);
+                mFMP->childSetValue("show_skin_weight", show_skin_weight);
 
             }
             else if ((flags & LEGACY_RIG_FLAG_TOO_MANY_JOINTS) > 0)
@@ -3233,11 +3237,12 @@ BOOL LLModelPreview::render()
             fmp->disableViewOption("show_joint_overrides");
             fmp->disableViewOption("show_joint_positions");
 
-            skin_weight = false;
+            show_skin_weight = false;
             mFMP->childSetValue("show_skin_weight", false);
-            fmp->setViewOptionEnabled("show_skin_weight", skin_weight);
+            fmp->setViewOptionEnabled("show_skin_weight", show_skin_weight);
         }
     }
+    //if (this) return TRUE;
 
     if (upload_skin && !has_skin_weights)
     { //can't upload skin weights if model has no skin weights
@@ -3280,7 +3285,7 @@ BOOL LLModelPreview::render()
         mFMP->childSetEnabled("upload_joints", upload_skin);
     }
 
-    F32 explode = mFMP->childGetValue("physics_explode").asReal();
+    F32 physics_explode = mFMP->childGetValue("physics_explode").asReal();
 
     LLGLDepthTest gls_depth(GL_TRUE); // SL-12781 re-enable z-buffer for 3D model preview
 
@@ -3300,7 +3305,7 @@ BOOL LLModelPreview::render()
     F32 z_near = 0.001f;
     F32 z_far = mCameraDistance*10.0f + mPreviewScale.magVec() + mCameraOffset.magVec();
 
-    if (skin_weight)
+    if (show_skin_weight)
     {
         target_pos = getPreviewAvatar()->getPositionAgent() + offset;
         z_near = 0.01f;
@@ -3310,7 +3315,7 @@ BOOL LLModelPreview::render()
         refresh();
     }
 
-    gObjectPreviewProgram.bind(skin_weight);
+    gObjectPreviewProgram.bind(show_skin_weight);
 
     gGL.loadIdentity();
     gPipeline.enableLightsPreview();
@@ -3319,7 +3324,7 @@ BOOL LLModelPreview::render()
         LLQuaternion(mCameraYaw, LLVector3::z_axis);
 
     LLQuaternion av_rot = camera_rot;
-    F32 camera_distance = skin_weight ? SKIN_WEIGHT_CAMERA_DISTANCE : mCameraDistance;
+    F32 camera_distance = show_skin_weight ? SKIN_WEIGHT_CAMERA_DISTANCE : mCameraDistance;
     LLViewerCamera::getInstance()->setOriginAndLookAt(
         target_pos + ((LLVector3(camera_distance, 0.f, 0.f) + offset) * av_rot),		// camera
         LLVector3::z_axis,																	// up
@@ -3335,9 +3340,9 @@ BOOL LLModelPreview::render()
     gGL.pushMatrix();
     gGL.color4fv(PREVIEW_EDGE_COL.mV);
 
-    if (!mBaseModel.empty() && mVertexBuffer[5].empty())
+    if (!mBaseModel.empty() && mVertexBuffer[LLModel::NUM_LODS].empty())
     {
-        genBuffers(-1, skin_weight);
+        genBuffers(-1, show_skin_weight);
         //genBuffers(3);
     }
 
@@ -3352,7 +3357,7 @@ BOOL LLModelPreview::render()
             if (!vb_vec.empty())
             {
                 const LLVertexBuffer* buff = vb_vec[0];
-                regen = buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) != skin_weight;
+                regen = buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) != show_skin_weight;
             }
             else
             {
@@ -3363,15 +3368,15 @@ BOOL LLModelPreview::render()
 
         if (regen)
         {
-            genBuffers(mPreviewLOD, skin_weight);
+            genBuffers(mPreviewLOD, show_skin_weight);
         }
 
-        if (physics && mVertexBuffer[LLModel::LOD_PHYSICS].empty())
+        if (show_physics && mVertexBuffer[LLModel::LOD_PHYSICS].empty())
         {
             genBuffers(LLModel::LOD_PHYSICS, false);
         }
 
-        if (!skin_weight)
+        if (!show_skin_weight)
         {
             for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
             {
@@ -3393,11 +3398,7 @@ BOOL LLModelPreview::render()
                 U32 num_models = mVertexBuffer[mPreviewLOD][model].size();
                 for (U32 i = 0; i < num_models; ++i)
                 {
-                    LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i];
-
-                    buffer->setBuffer();
-
-                    if (textures)
+                    if (show_textures)
                     {
                         int materialCnt = instance.mModel->mMaterialList.size();
                         if (i < materialCnt)
@@ -3421,10 +3422,16 @@ BOOL LLModelPreview::render()
                         gGL.diffuseColor4fv(PREVIEW_BASE_COL.mV);
                     }
 
+                    // Zero this variable for an obligatory buffer initialization
+                    // See https://github.com/secondlife/viewer/issues/912
+                    LLVertexBuffer::sGLRenderBuffer = 0;
+                    LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i];
+                    buffer->setBuffer();
                     buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts() - 1, buffer->getNumIndices(), 0);
+
                     gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
                     gGL.diffuseColor4fv(PREVIEW_EDGE_COL.mV);
-                    if (edges)
+                    if (show_edges)
                     {
                         glLineWidth(PREVIEW_EDGE_WIDTH);
                         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
@@ -3437,7 +3444,7 @@ BOOL LLModelPreview::render()
                 gGL.popMatrix();
             }
 
-            if (physics)
+            if (show_physics)
             {
                 glClear(GL_DEPTH_BUFFER_BIT);
 
@@ -3503,12 +3510,12 @@ BOOL LLModelPreview::render()
 
                                     for (U32 i = 0; i < physics.mMesh.size(); ++i)
                                     {
-                                        if (explode > 0.f)
+                                        if (physics_explode > 0.f)
                                         {
                                             gGL.pushMatrix();
 
                                             LLVector3 offset = model->mHullCenter[i] - model->mCenterOfHullCenters;
-                                            offset *= explode;
+                                            offset *= physics_explode;
 
                                             gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
                                         }
@@ -3523,7 +3530,7 @@ BOOL LLModelPreview::render()
                                         gGL.diffuseColor4ubv(hull_colors[i].mV);
                                         LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions);
 
-                                        if (explode > 0.f)
+                                        if (physics_explode > 0.f)
                                         {
                                             gGL.popMatrix();
                                         }
@@ -3538,14 +3545,17 @@ BOOL LLModelPreview::render()
                         if (render_mesh)
                         {
                             U32 num_models = mVertexBuffer[LLModel::LOD_PHYSICS][model].size();
-                            if (pass > 0){
+                            if (pass > 0)
+                            {
                                 for (U32 i = 0; i < num_models; ++i)
                                 {
-                                    LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
-
                                     gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
                                     gGL.diffuseColor4fv(PREVIEW_PSYH_FILL_COL.mV);
 
+                                    // Zero this variable for an obligatory buffer initialization
+                                    // See https://github.com/secondlife/viewer/issues/912
+                                    LLVertexBuffer::sGLRenderBuffer = 0;
+                                    LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
                                     buffer->setBuffer();
                                     buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts() - 1, buffer->getNumIndices(), 0);
 
@@ -3605,10 +3615,11 @@ BOOL LLModelPreview::render()
                                     U32 num_models = mVertexBuffer[LLModel::LOD_PHYSICS][model].size();
                                     for (U32 v = 0; v < num_models; ++v)
                                     {
+                                        // Zero this variable for an obligatory buffer initialization
+                                        // See https://github.com/secondlife/viewer/issues/912
+                                        LLVertexBuffer::sGLRenderBuffer = 0;
                                         LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][v];
-
                                         buffer->setBuffer();
-
                                         LLStrider<LLVector3> pos_strider;
                                         buffer->getVertexStrider(pos_strider, 0);
                                         LLVector4a* pos = (LLVector4a*)pos_strider.get();
@@ -3672,7 +3683,7 @@ BOOL LLModelPreview::render()
                         U32 joint_count = LLSkinningUtil::getMeshJointCount(skin);
                         U32 bind_count = skin->mAlternateBindMatrix.size();
 
-                        if (joint_overrides
+                        if (show_joint_overrides
                             && bind_count > 0
                             && joint_count == bind_count)
                         {
@@ -3715,16 +3726,15 @@ BOOL LLModelPreview::render()
                             }
                         }
 
-                        for (U32 i = 0, e = mVertexBuffer[mPreviewLOD][model].size(); i < e; ++i)
+                        std::size_t size = mVertexBuffer[mPreviewLOD][model].size();
+                        for (U32 i = 0; i < size; ++i)
                         {
-                            LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i];
-
                             model->mSkinInfo.updateHash();
                             LLRenderPass::uploadMatrixPalette(mPreviewAvatar, &model->mSkinInfo);
 
                             gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 
-                            if (textures)
+                            if (show_textures)
                             {
                                 int materialCnt = instance.mModel->mMaterialList.size();
                                 if (i < materialCnt)
@@ -3748,10 +3758,14 @@ BOOL LLModelPreview::render()
                                 gGL.diffuseColor4fv(PREVIEW_BASE_COL.mV);
                             }
 
+                            // Zero this variable for an obligatory buffer initialization
+                            // See https://github.com/secondlife/viewer/issues/912
+                            LLVertexBuffer::sGLRenderBuffer = 0;
+                            LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i];
                             buffer->setBuffer();
                             buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0);
 
-                            if (edges)
+                            if (show_edges)
                             {
                                 gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
                                 gGL.diffuseColor4fv(PREVIEW_EDGE_COL.mV);
@@ -3766,7 +3780,7 @@ BOOL LLModelPreview::render()
                 }
             }
 
-            if (joint_positions)
+            if (show_joint_positions)
             {
                 LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
                 if (shader)
-- 
cgit v1.2.3


From 2ab17fa3f991a71cdb83d6dba8e345e14f11514c Mon Sep 17 00:00:00 2001
From: Nicky <nicky.dasmijn@posteo.nl>
Date: Thu, 18 Apr 2024 17:59:56 +0200
Subject: Update open_libndofdev and openal to latest versions.

- With the updated openal the dependency on sndio can be dropped
- The updated libndofdev is compiled against the correct version of SDL2 and thus NDOF can be enabled again
---
 indra/cmake/OPENAL.cmake | 1 -
 1 file changed, 1 deletion(-)

(limited to 'indra')

diff --git a/indra/cmake/OPENAL.cmake b/indra/cmake/OPENAL.cmake
index 6a28846029..0b6a7c2853 100644
--- a/indra/cmake/OPENAL.cmake
+++ b/indra/cmake/OPENAL.cmake
@@ -31,7 +31,6 @@ if (USE_OPENAL)
     target_link_libraries( ll::openal INTERFACE
             openal
             alut
-            sndio
             )
   else()
     message(FATAL_ERROR "OpenAL is not available for this platform")
-- 
cgit v1.2.3


From 982d57fa00ea93ebbf4c8fdf8407310cb171e2e7 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 18 Apr 2024 21:52:58 +0300
Subject: viewer-private#217 Fix cef log name

---
 indra/newview/llviewermedia.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 3791d1e754..18cfa37fe1 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1723,7 +1723,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
 		std::string user_data_path_cache = gDirUtilp->getCacheDir(false);
 		user_data_path_cache += gDirUtilp->getDirDelimiter();
 
-		std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef.txt");
+		std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef.log");
         std::string user_data_path_cef_old = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef.old");
         if (gDirUtilp->fileExists(user_data_path_cef_log))
         {
-- 
cgit v1.2.3


From ea4ddb5f40ee8dd253be0ac4229de90f1eef61a3 Mon Sep 17 00:00:00 2001
From: Andrey Lihatskiy <alihatskiy@productengine.com>
Date: Mon, 15 Apr 2024 18:39:23 +0300
Subject: Revert "SL-20140 Setting shape hand size to 36 won't save"

This reverts commit 810a3d24c2e3671f926091c062b101bdec6a1517. (secondlife/jira-archive-internal#70482)
---
 indra/newview/character/avatar_lad.xml      | 17 ++++----
 indra/newview/llscrollingpanelparam.cpp     | 63 ++++++++++++++++++++---------
 indra/newview/llscrollingpanelparam.h       |  3 ++
 indra/newview/llscrollingpanelparambase.cpp | 29 +++++++------
 indra/newview/llscrollingpanelparambase.h   |  7 +---
 5 files changed, 72 insertions(+), 47 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml
index aef402d4db..2cdd86267e 100644
--- a/indra/newview/character/avatar_lad.xml
+++ b/indra/newview/character/avatar_lad.xml
@@ -2021,7 +2021,7 @@
      value_min="-1"
      value_max="1">
       <param_skeleton>
-
+	  
         <bone
          name="mEyeLeft"
          scale="0 0 0"
@@ -2031,8 +2031,9 @@
          name="mEyeRight"
          scale="0 0 0"
          offset="-.005 0 0" />
-
-        <bone
+		 
+	  
+<bone
          name="mFaceEyeAltLeft"
          scale="0 0 0"
          offset="-.005 0 0" />
@@ -2041,7 +2042,7 @@
          name="mFaceEyeAltRight"
          scale="0 0 0"
          offset="-.005 0 0" />
-
+	  
         <bone
          name="mFaceEyeLidLowerRight"
          scale="0 0.3 0.7"
@@ -2052,7 +2053,7 @@
          scale="0 0.3 0.7"
          offset="0 0 0" />
 
-        <bone
+		 <bone
          name="mFaceEyeLidUpperRight"
          scale="0 0.3 0.7"
          offset=" 0 0 0" />
@@ -2061,17 +2062,17 @@
          name="mFaceEyeLidUpperLeft"
          scale="0 0.3 0.7"
          offset=" 0 0 0" />
-
+		 
         <bone
          name="mFaceEyecornerInnerLeft"
          scale="0 0 0"
          offset="-0.005 -0.008 0.0" />
-
+		 
         <bone
          name="mFaceEyecornerInnerRight"
          scale="0 0 0"
          offset="-0.005 0.008 0.0" />
-
+		 
       </param_skeleton>
     </param>
 
diff --git a/indra/newview/llscrollingpanelparam.cpp b/indra/newview/llscrollingpanelparam.cpp
index efd84eaa6d..bfa453a0ae 100644
--- a/indra/newview/llscrollingpanelparam.cpp
+++ b/indra/newview/llscrollingpanelparam.cpp
@@ -259,15 +259,19 @@ void LLScrollingPanelParam::onHintHeldDown( LLVisualParamHint* hint )
 
 		// Make sure we're not taking the slider out of bounds
 		// (this is where some simple UI limits are stored)
-		F32 new_percent = weightToSlider(new_weight);
-		if (mSlider->getMinValue() < new_percent
-			&& new_percent < mSlider->getMaxValue())
+		F32 new_percent = weightToPercent(new_weight);
+		LLSliderCtrl* slider = getChild<LLSliderCtrl>("param slider");
+		if (slider)
 		{
-			mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight);
-			mWearable->writeToAvatar(gAgentAvatarp);
-			gAgentAvatarp->updateVisualParams();
+			if (slider->getMinValue() < new_percent
+				&& new_percent < slider->getMaxValue())
+			{
+				mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight);
+				mWearable->writeToAvatar(gAgentAvatarp);
+				gAgentAvatarp->updateVisualParams();
 
-			mSlider->setValue( weightToSlider( new_weight ) );
+				slider->setValue( weightToPercent( new_weight ) );
+			}
 		}
 	}
 }
@@ -288,13 +292,17 @@ void LLScrollingPanelParam::onHintMinMouseUp( void* userdata )
 		F32 range = self->mHintMax->getVisualParamWeight() - self->mHintMin->getVisualParamWeight();
 		// step a fraction in the negative directiona
 		F32 new_weight = current_weight - (range / 10.f);
-		F32 new_percent = self->weightToSlider(new_weight);
-		if (self->mSlider->getMinValue() < new_percent
-			&& new_percent < self->mSlider->getMaxValue())
+		F32 new_percent = self->weightToPercent(new_weight);
+		LLSliderCtrl* slider = self->getChild<LLSliderCtrl>("param slider");
+		if (slider)
 		{
-			self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight);
-			self->mWearable->writeToAvatar(gAgentAvatarp);
-			self->mSlider->setValue( self->weightToSlider( new_weight ) );
+			if (slider->getMinValue() < new_percent
+				&& new_percent < slider->getMaxValue())
+			{
+				self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight);
+				self->mWearable->writeToAvatar(gAgentAvatarp);
+				slider->setValue( self->weightToPercent( new_weight ) );
+			}
 		}
 	}
 
@@ -318,16 +326,33 @@ void LLScrollingPanelParam::onHintMaxMouseUp( void* userdata )
 			F32 range = self->mHintMax->getVisualParamWeight() - self->mHintMin->getVisualParamWeight();
 			// step a fraction in the negative direction
 			F32 new_weight = current_weight + (range / 10.f);
-			F32 new_percent = self->weightToSlider(new_weight);
-			if (self->mSlider->getMinValue() < new_percent
-				&& new_percent < self->mSlider->getMaxValue())
+			F32 new_percent = self->weightToPercent(new_weight);
+			LLSliderCtrl* slider = self->getChild<LLSliderCtrl>("param slider");
+			if (slider)
 			{
-				self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight);
-				self->mWearable->writeToAvatar(gAgentAvatarp);
-				self->mSlider->setValue( self->weightToSlider( new_weight ) );
+				if (slider->getMinValue() < new_percent
+					&& new_percent < slider->getMaxValue())
+				{
+					self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight);
+					self->mWearable->writeToAvatar(gAgentAvatarp);
+					slider->setValue( self->weightToPercent( new_weight ) );
+				}
 			}
 		}
 	}
 
 	LLVisualParamHint::requestHintUpdates( self->mHintMin, self->mHintMax );
 }
+
+
+F32 LLScrollingPanelParam::weightToPercent( F32 weight )
+{
+	LLViewerVisualParam* param = mParam;
+	return (weight - param->getMinWeight()) /  (param->getMaxWeight() - param->getMinWeight()) * 100.f;
+}
+
+F32 LLScrollingPanelParam::percentToWeight( F32 percent )
+{
+	LLViewerVisualParam* param = mParam;
+	return percent / 100.f * (param->getMaxWeight() - param->getMinWeight()) + param->getMinWeight();
+}
diff --git a/indra/newview/llscrollingpanelparam.h b/indra/newview/llscrollingpanelparam.h
index dc344486fc..c7a47d5c7a 100644
--- a/indra/newview/llscrollingpanelparam.h
+++ b/indra/newview/llscrollingpanelparam.h
@@ -61,6 +61,9 @@ public:
 	void				onHintMouseDown( LLVisualParamHint* hint );
 	void				onHintHeldDown( LLVisualParamHint* hint );
 
+	F32					weightToPercent( F32 weight );
+	F32					percentToWeight( F32 percent );
+
 public:
 	// Constants for LLPanelVisualParam
 	const static F32 PARAM_STEP_TIME_THRESHOLD;
diff --git a/indra/newview/llscrollingpanelparambase.cpp b/indra/newview/llscrollingpanelparambase.cpp
index 2a6c25235d..fe7a362723 100644
--- a/indra/newview/llscrollingpanelparambase.cpp
+++ b/indra/newview/llscrollingpanelparambase.cpp
@@ -43,7 +43,6 @@ LLScrollingPanelParamBase::LLScrollingPanelParamBase( const LLPanel::Params& pan
 						      LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp, BOOL use_hints)
 	: LLScrollingPanel( panel_params ),
 	  mParam(param),
-	  mSlider(nullptr),
 	  mAllowModify(allow_modify),
 	  mWearable(wearable)
 {
@@ -51,15 +50,13 @@ LLScrollingPanelParamBase::LLScrollingPanelParamBase( const LLPanel::Params& pan
 		buildFromFile( "panel_scrolling_param.xml");
 	else
 		buildFromFile( "panel_scrolling_param_base.xml");
-
-	mSlider = getChild<LLSliderCtrl>("param slider");
-	mSlider->setMaxValue(100.f * (mParam->getMaxWeight() - mParam->getMinWeight()));
-	mSlider->setValue(weightToSlider(param->getWeight()));
+	
+	getChild<LLUICtrl>("param slider")->setValue(weightToPercent(param->getWeight()));
 
 	std::string display_name = LLTrans::getString(param->getDisplayName());
-	mSlider->setLabelArg("[DESC]", display_name);
-	mSlider->setEnabled(mAllowModify);
-	mSlider->setCommitCallback(boost::bind(LLScrollingPanelParamBase::onSliderMoved, mSlider, this));
+	getChild<LLUICtrl>("param slider")->setLabelArg("[DESC]", display_name);
+	getChildView("param slider")->setEnabled(mAllowModify);
+	childSetCommitCallback("param slider", LLScrollingPanelParamBase::onSliderMoved, this);
 
 	setVisible(FALSE);
 	setBorderVisible( FALSE );
@@ -80,9 +77,9 @@ void LLScrollingPanelParamBase::updatePanel(BOOL allow_modify)
 	}
 
 	F32 current_weight = mWearable->getVisualParamWeight( param->getID() );
-	mSlider->setValue(weightToSlider( current_weight ) );
+	getChild<LLUICtrl>("param slider")->setValue(weightToPercent( current_weight ) );
 	mAllowModify = allow_modify;
-	mSlider->setEnabled(mAllowModify);
+	getChildView("param slider")->setEnabled(mAllowModify);
 }
 
 // static
@@ -93,7 +90,7 @@ void LLScrollingPanelParamBase::onSliderMoved(LLUICtrl* ctrl, void* userdata)
 	LLViewerVisualParam* param = self->mParam;
 	
 	F32 current_weight = self->mWearable->getVisualParamWeight( param->getID() );
-	F32 new_weight = self->sliderToWeight( (F32)slider->getValue().asReal() );
+	F32 new_weight = self->percentToWeight( (F32)slider->getValue().asReal() );
 	if (current_weight != new_weight )
 	{
 		self->mWearable->setVisualParamWeight( param->getID(), new_weight);
@@ -102,12 +99,14 @@ void LLScrollingPanelParamBase::onSliderMoved(LLUICtrl* ctrl, void* userdata)
 	}
 }
 
-F32 LLScrollingPanelParamBase::weightToSlider(F32 weight)
+F32 LLScrollingPanelParamBase::weightToPercent( F32 weight )
 {
-	return (weight - mParam->getMinWeight()) * 100.f;
+	LLViewerVisualParam* param = mParam;
+	return (weight - param->getMinWeight()) /  (param->getMaxWeight() - param->getMinWeight()) * 100.f;
 }
 
-F32 LLScrollingPanelParamBase::sliderToWeight(F32 slider)
+F32 LLScrollingPanelParamBase::percentToWeight( F32 percent )
 {
-	return slider / 100.f + mParam->getMinWeight();
+	LLViewerVisualParam* param = mParam;
+	return percent / 100.f * (param->getMaxWeight() - param->getMinWeight()) + param->getMinWeight();
 }
diff --git a/indra/newview/llscrollingpanelparambase.h b/indra/newview/llscrollingpanelparambase.h
index e7f88a21bd..9538826251 100644
--- a/indra/newview/llscrollingpanelparambase.h
+++ b/indra/newview/llscrollingpanelparambase.h
@@ -36,7 +36,6 @@ class LLViewerVisualParam;
 class LLWearable;
 class LLVisualParamHint;
 class LLViewerVisualParam;
-class LLSliderCtrl;
 class LLJoint;
 
 class LLScrollingPanelParamBase : public LLScrollingPanel
@@ -50,13 +49,11 @@ public:
 
 	static void			onSliderMoved(LLUICtrl* ctrl, void* userdata);
 
-	F32					weightToSlider(F32 weight);
-	F32					sliderToWeight(F32 slider);
+	F32					weightToPercent( F32 weight );
+	F32					percentToWeight( F32 percent );
 
 public:
 	LLViewerVisualParam* mParam;
-	LLSliderCtrl* mSlider;
-
 protected:
 	BOOL mAllowModify;
 	LLWearable *mWearable;
-- 
cgit v1.2.3


From cc7b416fb8e776c406db6a4f95e505398f5f7fd5 Mon Sep 17 00:00:00 2001
From: nerodevo <100370411+nerodevo@users.noreply.github.com>
Date: Mon, 22 Apr 2024 15:21:38 -0500
Subject: Remove invalid text color parameter from panel_login_first.xml
 Follow-up to previous commit 4a07fd3. This will resolve the warning showing
 up when loading the viewer for the first time.

---
 indra/newview/skins/default/xui/en/panel_login_first.xml | 1 -
 1 file changed, 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/skins/default/xui/en/panel_login_first.xml b/indra/newview/skins/default/xui/en/panel_login_first.xml
index d002e24782..09eb24c019 100644
--- a/indra/newview/skins/default/xui/en/panel_login_first.xml
+++ b/indra/newview/skins/default/xui/en/panel_login_first.xml
@@ -179,7 +179,6 @@
             control_name="RememberPassword"
             follows="left|top"
             font="SansSerifLarge"
-            text_color="EmphasisColor"
             height="24"
             left="262"
             bottom_delta="0"
-- 
cgit v1.2.3


From f69ac40e24e78fe265c81ff3785c185229764151 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 26 Apr 2024 23:54:40 +0300
Subject: viewer-private#217 Cef log was deleted too often

delete once per session, not once per instance
---
 indra/newview/llappviewer.cpp   | 8 ++++++++
 indra/newview/llviewermedia.cpp | 9 +--------
 2 files changed, 9 insertions(+), 8 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 547a1c49cd..67ef234129 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2352,6 +2352,14 @@ void LLAppViewer::initLoggingAndGetLastDuration()
         {
             LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL;
         }
+
+        std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef.log");
+        if (gDirUtilp->fileExists(user_data_path_cef_log))
+        {
+            std::string user_data_path_cef_old = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef.old");
+            LLFile::remove(user_data_path_cef_old, ENOENT);
+            LLFile::rename(user_data_path_cef_log, user_data_path_cef_old);
+        }
     }
 }
 
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 18cfa37fe1..d35c63200a 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1723,14 +1723,6 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
 		std::string user_data_path_cache = gDirUtilp->getCacheDir(false);
 		user_data_path_cache += gDirUtilp->getDirDelimiter();
 
-		std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef.log");
-        std::string user_data_path_cef_old = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef.old");
-        if (gDirUtilp->fileExists(user_data_path_cef_log))
-        {
-            LLFile::remove(user_data_path_cef_old, ENOENT);
-            LLFile::rename(user_data_path_cef_log, user_data_path_cef_old);
-        }
-
 		// See if the plugin executable exists
 		llstat s;
 		if(LLFile::stat(launcher_name, &s))
@@ -1745,6 +1737,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
 		{
 			media_source = new LLPluginClassMedia(owner);
 			media_source->setSize(default_width, default_height);
+            std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef.log");
 			media_source->setUserDataPath(user_data_path_cache, gDirUtilp->getUserName(), user_data_path_cef_log);
 			media_source->setLanguageCode(LLUI::getLanguage());
 			media_source->setZoomFactor(zoom_factor);
-- 
cgit v1.2.3


From f59af191051bd182806d5cfc77a3e538f02fe129 Mon Sep 17 00:00:00 2001
From: AiraYumi <aira.youme@airanyumi.net>
Date: Wed, 8 May 2024 20:41:17 +0900
Subject: enable ime on xwayland

---
 indra/llwindow/llwindowsdl.cpp | 5 +++++
 1 file changed, 5 insertions(+)

(limited to 'indra')

diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index b8b502508b..798732e84d 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -654,6 +654,11 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
         SDL_SetHint( std::get<0>(hint), std::get<1>(hint));
     }
 
+#if LL_LINUX
+    // Enable IME on XWayland
+    setenv("XMODIFIERS", std::string("@im=fcitx;ibus").c_str(), 1);
+#endif
+
     std::initializer_list<std::tuple<uint32_t, char const*, bool>> initList=
             { {SDL_INIT_VIDEO,"SDL_INIT_VIDEO", true},
               {SDL_INIT_AUDIO,"SDL_INIT_AUDIO", false},
-- 
cgit v1.2.3


From 24e8a0bb5d47f14727ce4d018232d935232469d2 Mon Sep 17 00:00:00 2001
From: AiraYumi <aira.youme@airanyumi.net>
Date: Thu, 9 May 2024 23:23:39 +0900
Subject: enable ime on xwayland (environment setting move)

---
 indra/llwindow/llwindowsdl.cpp       | 5 -----
 indra/newview/linux_tools/wrapper.sh | 4 ++++
 2 files changed, 4 insertions(+), 5 deletions(-)

(limited to 'indra')

diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index 798732e84d..b8b502508b 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -654,11 +654,6 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
         SDL_SetHint( std::get<0>(hint), std::get<1>(hint));
     }
 
-#if LL_LINUX
-    // Enable IME on XWayland
-    setenv("XMODIFIERS", std::string("@im=fcitx;ibus").c_str(), 1);
-#endif
-
     std::initializer_list<std::tuple<uint32_t, char const*, bool>> initList=
             { {SDL_INIT_VIDEO,"SDL_INIT_VIDEO", true},
               {SDL_INIT_AUDIO,"SDL_INIT_AUDIO", false},
diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh
index 7d26c81283..a027aaf6d1 100755
--- a/indra/newview/linux_tools/wrapper.sh
+++ b/indra/newview/linux_tools/wrapper.sh
@@ -62,6 +62,10 @@ export SDL_VIDEO_X11_DGAMOUSE=0
 if [ "$GTK_IM_MODULE" = "scim" ]; then
     export GTK_IM_MODULE=xim
 fi
+if [ "$XMODIFIERS" = "" ]; then
+    ## IME is valid only for fcitx, not when using ibus
+    export XMODIFIERS="@im=fcitx"
+fi
 
 ## - Automatically work around the ATI mouse cursor crash bug:
 ## (this workaround is disabled as most fglrx users do not see the bug)
-- 
cgit v1.2.3


From d5378e9cab2024237b4d900057ba59f7f22f4594 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 9 May 2024 01:54:03 +0300
Subject: viewer-private#236 Don't block removal of marketplace folders

Marketplace is not visible outside of own floater and that floater will
do an extra warning when deleting listings that have additional data.
---
 indra/newview/llinventoryfunctions.cpp | 6 ------
 1 file changed, 6 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index c8aa235506..016b0880eb 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -843,12 +843,6 @@ bool get_is_category_and_children_removable(LLInventoryModel* model, const LLUUI
         return false;
     }
 
-    const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
-    if (mp_id.notNull() && gInventory.isObjectDescendentOf(folder_id, mp_id))
-    {
-        return false;
-    }
-
     LLInventoryModel::cat_array_t cat_array;
     LLInventoryModel::item_array_t item_array;
     model->collectDescendents(
-- 
cgit v1.2.3


From 82d713782529074b03720833038cb0df2b8bcffd Mon Sep 17 00:00:00 2001
From: Andrey Lihatskiy <alihatskiy@productengine.com>
Date: Tue, 14 May 2024 08:50:04 +0300
Subject: #1457 Fix the tests on mac

---
 indra/llimage/tests/llimageworker_test.cpp | 3 ++-
 indra/test/test.cpp                        | 6 ------
 2 files changed, 2 insertions(+), 7 deletions(-)

(limited to 'indra')

diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp
index 49fc1afd82..2568adf89e 100644
--- a/indra/llimage/tests/llimageworker_test.cpp
+++ b/indra/llimage/tests/llimageworker_test.cpp
@@ -68,6 +68,7 @@ U8* LLImageRaw::allocateData(S32 size) { return NULL; }
 U8* LLImageRaw::reallocateData(S32 size) { return NULL; }
 const U8* LLImageBase::getData() const { return NULL; }
 U8* LLImageBase::getData() { return NULL; }
+const std::string& LLImage::getLastThreadError() { static std::string msg; return msg; }
 
 // End Stubbing
 // -------------------------------------------------------------------------------------------
@@ -98,7 +99,7 @@ namespace tut
                 done = res;
                 *done = false;
             }
-            virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32)
+            virtual void completed(bool success, const std::string& error_message, LLImageRaw* raw, LLImageRaw* aux, U32 request_id)
             {
                 *done = true;
             }
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 21232e88f5..61a4eb07c5 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -54,12 +54,6 @@
 #endif
 
 #ifndef LL_WINDOWS
-
-typedef struct {
-  void *re_pcre;
-  size_t re_nsub;
-  size_t re_erroffset;
-} regex_t;
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #endif
-- 
cgit v1.2.3


From 1ebf006b73c06d037e3d3ae4393136082195096d Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Wed, 27 Mar 2024 19:51:59 -0400
Subject: Remove dead googlemock dependency and related setup code

---
 indra/cmake/CMakeLists.txt               |  1 -
 indra/cmake/GoogleMock.cmake             | 32 ----------------
 indra/cmake/LLAddBuildTest.cmake         |  7 ----
 indra/llmessage/tests/llmockhttpclient.h | 66 --------------------------------
 indra/test/CMakeLists.txt                |  2 -
 indra/test/test.cpp                      | 11 ------
 6 files changed, 119 deletions(-)
 delete mode 100644 indra/cmake/GoogleMock.cmake
 delete mode 100644 indra/llmessage/tests/llmockhttpclient.h

(limited to 'indra')

diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index e1507bf6a0..df968144ed 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -26,7 +26,6 @@ set(cmake_SOURCE_FILES
         FreeType.cmake
         GLEXT.cmake
         GLH.cmake
-        GoogleMock.cmake
         Havok.cmake
         Hunspell.cmake
         JsonCpp.cmake
diff --git a/indra/cmake/GoogleMock.cmake b/indra/cmake/GoogleMock.cmake
deleted file mode 100644
index c3d195c37b..0000000000
--- a/indra/cmake/GoogleMock.cmake
+++ /dev/null
@@ -1,32 +0,0 @@
-# -*- cmake -*-
-include(Prebuilt)
-include(Linking)
-
-include_guard()
-
-add_library( ll::googlemock INTERFACE IMPORTED )
-if(USE_CONAN)
-  target_link_libraries( ll::googlemock INTERFACE  CONAN_PKG::gtest )
-
-  #Not very nice, but for the moment we need this for tut.hpp
-  target_include_directories( ll::googlemock SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include )
-  return()
-endif()
-
-use_prebuilt_binary(googlemock)
-
-target_include_directories( ll::googlemock SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include )
-
-if (LINUX)
-    # VWR-24366: gmock is underlinked, it needs gtest.
-    target_link_libraries( ll::googlemock INTERFACE gmock gtest)
-elseif(WINDOWS)
-    target_link_libraries( ll::googlemock INTERFACE gmock)
-    target_include_directories( ll::googlemock SYSTEM INTERFACE
-            ${LIBS_PREBUILT_DIR}/include
-            ${LIBS_PREBUILT_DIR}/include/gmock)
-elseif(DARWIN)
-    target_link_libraries( ll::googlemock INTERFACE gmock gtest)
-endif(LINUX)
-
-
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 6e948c2186..5d96a4398f 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -8,7 +8,6 @@ endif()
 
 include(00-Common)
 include(LLTestCommand)
-include(GoogleMock)
 include(bugsplat)
 include(Tut)
 
@@ -26,10 +25,6 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
   #
   # More info and examples at: https://wiki.secondlife.com/wiki/How_to_add_unit_tests_to_indra_code
 
-  # This here looks weird, but is needed. It will inject GoogleMock into projects that forgot to include `this` (LLAddBuildTest.cmake)
-  # But through some other means have access to this macro
-  include(GoogleMock)
-
   if(LL_TEST_VERBOSE)
     message("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}")
   endif()
@@ -48,7 +43,6 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
 
   set(alltest_LIBRARIES
           llcommon
-          ll::googlemock
           )
   if(NOT "${project}" STREQUAL "llmath")
     # add llmath as a dep unless the tested module *is* llmath!
@@ -211,7 +205,6 @@ FUNCTION(LL_ADD_INTEGRATION_TEST
 
   set(libraries
           ${library_dependencies}
-          ll::googlemock
           )
 
   # Add test executable build target
diff --git a/indra/llmessage/tests/llmockhttpclient.h b/indra/llmessage/tests/llmockhttpclient.h
deleted file mode 100644
index 1611ab7bd8..0000000000
--- a/indra/llmessage/tests/llmockhttpclient.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * @file
- * @brief
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-/* Macro Definitions */
-#ifndef LL_LLMOCKHTTPCLIENT_H
-#define LL_LLMOCKHTTPCLIENT_H
-
-#include "linden_common.h"
-#include "llhttpclientinterface.h"
-
-#include <gmock/gmock.h>
-
-class LLMockHTTPClient : public LLHTTPClientInterface
-{
-public:
-  MOCK_METHOD2(get, void(const std::string& url, LLCurl::ResponderPtr responder));
-  MOCK_METHOD3(get, void(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers));
-  MOCK_METHOD3(put, void(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder));
-};
-
-// A helper to match responder types
-template<typename T>
-struct ResponderType
-{
-    bool operator()(LLCurl::ResponderPtr ptr) const
-    {
-        T* p = dynamic_cast<T*>(ptr.get());
-        return p != NULL;
-    }
-};
-
-inline bool operator==(const LLSD& l, const LLSD& r)
-{
-    std::ostringstream ls, rs;
-    ls << l;
-    rs << r;
-    return ls.str() == rs.str();
-
-}
-
-
-#endif //LL_LLMOCKHTTPCLIENT_H
-
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index 4a0a8716c4..3dcddf9dc2 100644
--- a/indra/test/CMakeLists.txt
+++ b/indra/test/CMakeLists.txt
@@ -9,7 +9,6 @@ include(Linking)
 include(Tut)
 include(LLAddBuildTest)
 include(bugsplat)
-include(GoogleMock)
 
 set(test_SOURCE_FILES
     io.cpp
@@ -65,7 +64,6 @@ target_link_libraries(lltest
         llxml
         llcommon
         llcorehttp
-        ll::googlemock
         )
 
 if (WINDOWS)
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 61a4eb07c5..cbd1077306 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -53,11 +53,6 @@
 #   include "ctype_workaround.h"
 #endif
 
-#ifndef LL_WINDOWS
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#endif
-
 #if LL_MSVC
 #pragma warning (push)
 #pragma warning (disable : 4702) // warning C4702: unreachable code
@@ -522,12 +517,6 @@ static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL;
 
 int main(int argc, char **argv)
 {
-    // The following line must be executed to initialize Google Mock
-    // (and Google Test) before running the tests.
-#ifndef LL_WINDOWS
-    ::testing::InitGoogleMock(&argc, argv);
-#endif
-
     ll_init_apr();
     apr_getopt_t* os = NULL;
     if(APR_SUCCESS != apr_getopt_init(&os, gAPRPoolp, argc, argv))
-- 
cgit v1.2.3


From 2f25f87ee719a79efc8316079f3c881eddb4d266 Mon Sep 17 00:00:00 2001
From: Alexander Gavriliuk <alexandrgproductengine@lindenlab.com>
Date: Wed, 15 May 2024 19:10:17 +0200
Subject: secondlife/jira-archive-internal#70713 Combine recently and
 frequently used

---
 indra/newview/llfloateremojipicker.cpp             | 59 ++--------------------
 indra/newview/llfloateremojipicker.h               |  1 -
 .../skins/default/xui/en/floater_emoji_picker.xml  |  1 -
 3 files changed, 4 insertions(+), 57 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llfloateremojipicker.cpp b/indra/newview/llfloateremojipicker.cpp
index baad75ed8e..c9d14c45f8 100644
--- a/indra/newview/llfloateremojipicker.cpp
+++ b/indra/newview/llfloateremojipicker.cpp
@@ -57,8 +57,7 @@ static const S32 USED_EMOJIS_IMAGE_INDEX = 0x23F2;
 // https://www.compart.com/en/unicode/U+1F6D1
 static const S32 EMPTY_LIST_IMAGE_INDEX = 0x1F6D1;
 // The following categories should follow the required alphabetic order
-static const std::string RECENTLY_USED_CATEGORY = "1 recently used";
-static const std::string FREQUENTLY_USED_CATEGORY = "2 frequently used";
+static const std::string FREQUENTLY_USED_CATEGORY = "frequently used";
 
 // Floater state related variables
 static std::list<llwchar> sRecentlyUsed;
@@ -445,11 +444,10 @@ void LLFloaterEmojiPicker::fillGroups()
     // Create button for "All categories"
     createGroupButton(params, rect, ALL_EMOJIS_IMAGE_INDEX);
 
-    // Create group and button for "Recently used" and/or "Frequently used"
-    if (!sRecentlyUsed.empty() || !sFrequentlyUsed.empty())
+    // Create group and button for "Frequently used"
+    if (!sFrequentlyUsed.empty())
     {
         std::map<std::string, std::vector<LLEmojiSearchResult>> cats;
-        fillCategoryRecentlyUsed(cats);
         fillCategoryFrequentlyUsed(cats);
 
         if (!cats.empty())
@@ -480,40 +478,6 @@ void LLFloaterEmojiPicker::fillGroups()
     resizeGroupButtons();
 }
 
-void LLFloaterEmojiPicker::fillCategoryRecentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats)
-{
-    if (sRecentlyUsed.empty())
-        return;
-
-    std::vector<LLEmojiSearchResult> emojis;
-
-    // In case of empty mFilterPattern we'd use sRecentlyUsed directly
-    if (!mFilterPattern.empty())
-    {
-        // List all emojis in "Recently used"
-        const LLEmojiDictionary::emoji2descr_map_t& emoji2descr = LLEmojiDictionary::instance().getEmoji2Descr();
-        std::size_t begin, end;
-        for (llwchar emoji : sRecentlyUsed)
-        {
-            auto e2d = emoji2descr.find(emoji);
-            if (e2d != emoji2descr.end() && !e2d->second->ShortCodes.empty())
-            {
-                for (const std::string& shortcode : e2d->second->ShortCodes)
-                {
-                if (LLEmojiDictionary::searchInShortCode(begin, end, shortcode, mFilterPattern))
-                {
-                    emojis.emplace_back(emoji, shortcode, begin, end);
-                }
-            }
-        }
-        }
-        if (emojis.empty())
-            return;
-    }
-
-    cats.emplace(std::make_pair(RECENTLY_USED_CATEGORY, emojis));
-}
-
 void LLFloaterEmojiPicker::fillCategoryFrequentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats)
 {
     if (sFrequentlyUsed.empty())
@@ -755,7 +719,6 @@ void LLFloaterEmojiPicker::fillEmojisCategory(const std::vector<LLEmojiSearchRes
 {
     // Place the category title
     std::string title =
-        category == RECENTLY_USED_CATEGORY ? getString("title_for_recently_used") :
         category == FREQUENTLY_USED_CATEGORY ? getString("title_for_frequently_used") :
         isupper(category.front()) ? category : LLStringUtil::capitalize(category);
     LLEmojiGridDivider* div = new LLEmojiGridDivider(row_panel_params, title);
@@ -768,21 +731,7 @@ void LLFloaterEmojiPicker::fillEmojisCategory(const std::vector<LLEmojiSearchRes
     {
         const LLEmojiDictionary::emoji2descr_map_t& emoji2descr = LLEmojiDictionary::instance().getEmoji2Descr();
         LLEmojiSearchResult emoji { 0, "", 0, 0 };
-        if (category == RECENTLY_USED_CATEGORY)
-        {
-            for (llwchar code : sRecentlyUsed)
-            {
-                const LLEmojiDictionary::emoji2descr_map_t::const_iterator& e2d = emoji2descr.find(code);
-                if (e2d != emoji2descr.end() && !e2d->second->ShortCodes.empty())
-                {
-                    emoji.Character = code;
-                    emoji.String = e2d->second->ShortCodes.front();
-                    createEmojiIcon(emoji, category, row_panel_params, row_list_params, icon_params,
-                        icon_rect, max_icons, bg, row, icon_index);
-                }
-            }
-        }
-        else if (category == FREQUENTLY_USED_CATEGORY)
+        if (category == FREQUENTLY_USED_CATEGORY)
         {
             for (const auto& code : sFrequentlyUsed)
             {
diff --git a/indra/newview/llfloateremojipicker.h b/indra/newview/llfloateremojipicker.h
index 05b4826e37..bc64cb1f35 100644
--- a/indra/newview/llfloateremojipicker.h
+++ b/indra/newview/llfloateremojipicker.h
@@ -60,7 +60,6 @@ public:
 private:
     void initialize();
     void fillGroups();
-    void fillCategoryRecentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats);
     void fillCategoryFrequentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats);
     void fillGroupEmojis(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats, U32 index);
     void createGroupButton(LLButton::Params& params, const LLRect& rect, llwchar emoji);
diff --git a/indra/newview/skins/default/xui/en/floater_emoji_picker.xml b/indra/newview/skins/default/xui/en/floater_emoji_picker.xml
index e4b8f13df7..f642ca93b7 100644
--- a/indra/newview/skins/default/xui/en/floater_emoji_picker.xml
+++ b/indra/newview/skins/default/xui/en/floater_emoji_picker.xml
@@ -13,7 +13,6 @@
     chrome="true"
     height="350"
     width="304">
-  <floater.string name="title_for_recently_used" value="Recently used"/>
   <floater.string name="title_for_frequently_used" value="Frequently used"/>
   <floater.string name="text_no_emoji_for_filter" value="No emoji found for '[FILTER]'"/>
   <scroll_container
-- 
cgit v1.2.3


From 732b4cd60a53d390e413a7791c29a4a4628fa4f2 Mon Sep 17 00:00:00 2001
From: AiraYumi <aira.youme@airanyumi.net>
Date: Thu, 16 May 2024 14:16:37 +0900
Subject: Correcting the display position of the input dialog (#1480)

---
 indra/llwindow/llwindowsdl.cpp | 15 +++++++++++++++
 indra/llwindow/llwindowsdl.h   |  2 ++
 2 files changed, 17 insertions(+)

(limited to 'indra')

diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index 255d89af77..218f953c7f 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -647,6 +647,7 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
             {
                     {SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR,"0"},
                     {SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH,"1"},
+                    {SDL_HINT_IME_INTERNAL_EDITING,"1"}
             };
 
     for( auto hint: hintList )
@@ -2619,3 +2620,17 @@ U32 LLWindowSDL::getAvailableVRAMMegabytes()
 {
     return 4096;
 }
+
+void LLWindowSDL::setLanguageTextInput(const LLCoordGL& position)
+{
+    LLCoordWindow win_pos;
+    convertCoords( position, &win_pos );
+
+    SDL_Rect r;
+    r.x = win_pos.mX;
+    r.y = win_pos.mY;
+    r.w = 500;
+    r.h = 16;
+
+    SDL_SetTextInputRect(&r);
+}
diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h
index e922ce592c..d24739cbda 100644
--- a/indra/llwindow/llwindowsdl.h
+++ b/indra/llwindow/llwindowsdl.h
@@ -171,6 +171,8 @@ public:
     void *getPlatformWindow() override;
 
     void bringToFront() override;
+    
+    void setLanguageTextInput(const LLCoordGL& pos) override;
 
     void spawnWebBrowser(const std::string &escaped_url, bool async) override;
 
-- 
cgit v1.2.3


From 4fbb190453200c12169fdcc3e151df2fa73c0db4 Mon Sep 17 00:00:00 2001
From: Beq Janus <beqjanus@gmail.com>
Date: Fri, 17 May 2024 16:48:03 +0100
Subject: fix bad indentation and modernise (#1503)

---
 indra/llxml/llxmltree.cpp | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

(limited to 'indra')

diff --git a/indra/llxml/llxmltree.cpp b/indra/llxml/llxmltree.cpp
index baf2e6a951..cd41aa6f2d 100644
--- a/indra/llxml/llxmltree.cpp
+++ b/indra/llxml/llxmltree.cpp
@@ -108,14 +108,17 @@ LLXmlTreeNode::LLXmlTreeNode( const std::string& name, LLXmlTreeNode* parent, LL
 
 LLXmlTreeNode::~LLXmlTreeNode()
 {
-    attribute_map_t::iterator iter;
-    for (iter=mAttributes.begin(); iter != mAttributes.end(); iter++)
-        delete iter->second;
-        for(LLXmlTreeNode* node : mChildren)
-        {
-            delete node;
-        }
-        mChildren.clear();
+    for (auto& attr : mAttributes)
+    {
+        delete attr.second;
+    }
+    mAttributes.clear();
+
+    for (auto& child : mChildren)
+    {
+        delete child;
+    }
+    mChildren.clear();
 }
 
 void LLXmlTreeNode::dump( const std::string& prefix )
-- 
cgit v1.2.3


From 4189cb74421794ba123bf8724caa843c9d9d1c78 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 29 May 2024 18:50:29 +0300
Subject: viewer#1577 Attachments cannot be detached in performance floater

attachment list gets filled with object ids, not attachment ids
---
 indra/newview/llfloaterperformance.cpp | 12 ++++++++----
 indra/newview/llfloaterperformance.h   |  2 +-
 2 files changed, 9 insertions(+), 5 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llfloaterperformance.cpp b/indra/newview/llfloaterperformance.cpp
index 97ae97dafc..ba655ab760 100644
--- a/indra/newview/llfloaterperformance.cpp
+++ b/indra/newview/llfloaterperformance.cpp
@@ -115,12 +115,12 @@ BOOL LLFloaterPerformance::postBuild()
     mHUDList = mHUDsPanel->getChild<LLNameListCtrl>("hud_list");
     mHUDList->setNameListType(LLNameListCtrl::SPECIAL);
     mHUDList->setHoverIconName("StopReload_Off");
-    mHUDList->setIconClickedCallback(boost::bind(&LLFloaterPerformance::detachItem, this, _1));
+    mHUDList->setIconClickedCallback(boost::bind(&LLFloaterPerformance::detachObject, this, _1));
 
     mObjectList = mComplexityPanel->getChild<LLNameListCtrl>("obj_list");
     mObjectList->setNameListType(LLNameListCtrl::SPECIAL);
     mObjectList->setHoverIconName("StopReload_Off");
-    mObjectList->setIconClickedCallback(boost::bind(&LLFloaterPerformance::detachItem, this, _1));
+    mObjectList->setIconClickedCallback(boost::bind(&LLFloaterPerformance::detachObject, this, _1));
 
     mSettingsPanel->getChild<LLButton>("advanced_btn")->setCommitCallback(boost::bind(&LLFloaterPerformance::onClickAdvanced, this));
     mSettingsPanel->getChild<LLButton>("defaults_btn")->setCommitCallback(boost::bind(&LLFloaterPerformance::onClickDefaults, this));
@@ -524,9 +524,13 @@ void LLFloaterPerformance::setFPSText()
     getChild<LLTextBox>("fps_lbl")->setValue(fps_text);
 }
 
-void LLFloaterPerformance::detachItem(const LLUUID& item_id)
+void LLFloaterPerformance::detachObject(const LLUUID& obj_id)
 {
-    LLAppearanceMgr::instance().removeItemFromAvatar(item_id);
+    LLViewerObject* obj = gObjectList.findObject(obj_id);
+    if (obj)
+    {
+        LLAppearanceMgr::instance().removeItemFromAvatar(obj->getAttachmentItemID());
+    }
 }
 
 void LLFloaterPerformance::onClickAdvanced()
diff --git a/indra/newview/llfloaterperformance.h b/indra/newview/llfloaterperformance.h
index d2f45a9e2e..03fa9e8184 100644
--- a/indra/newview/llfloaterperformance.h
+++ b/indra/newview/llfloaterperformance.h
@@ -46,7 +46,7 @@ public:
     void hidePanels();
     void showAutoadjustmentsPanel();
 
-    void detachItem(const LLUUID& item_id);
+    void detachObject(const LLUUID& obj_id);
 
     void onAvatarListRightClick(LLUICtrl* ctrl, S32 x, S32 y);
 
-- 
cgit v1.2.3