aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Scripting
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2012-09-06 22:12:05 +0100
committerJustin Clark-Casey (justincc)2012-09-06 22:12:05 +0100
commit8f02fd926e14dfad7f5eb77a67a6701f449511e0 (patch)
tree08e15f6bb44ff84027c278c51bb55a22951d5ecd /OpenSim/Region/CoreModules/Scripting
parentAdded missing configs, and deleted the [Profile] part on the Hypergrind config. (diff)
downloadopensim-SC_OLD-8f02fd926e14dfad7f5eb77a67a6701f449511e0.zip
opensim-SC_OLD-8f02fd926e14dfad7f5eb77a67a6701f449511e0.tar.gz
opensim-SC_OLD-8f02fd926e14dfad7f5eb77a67a6701f449511e0.tar.bz2
opensim-SC_OLD-8f02fd926e14dfad7f5eb77a67a6701f449511e0.tar.xz
If reusing dynamic textures, do not reuse small data length textures that fall below current viewer discard level 2 thresholds.
Viewer LL 3.3.4 and before sometimes fail to properly redisplay dynamic textures that have a small data length compared to pixel size when pulled from cache. This appears to happen when the data length is smaller than the estimate discard level 2 size the viewer uses when making this GetTexture request. This commit works around this by always regenerating dynamic textures that fall below this threshold rather than reusing them if ReuseDynamicTextures = true This can be controlled by the [Textures] ReuseDynamicLowDataTextures config setting which defaults to false.
Diffstat (limited to 'OpenSim/Region/CoreModules/Scripting')
-rw-r--r--OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs59
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs41
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs42
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs24
4 files changed, 125 insertions, 41 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
index e09f1a9..1f340df 100644
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
42{ 42{
43 public class DynamicTextureModule : IRegionModule, IDynamicTextureManager 43 public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
44 { 44 {
45// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 private const int ALL_SIDES = -1; 47 private const int ALL_SIDES = -1;
48 48
@@ -54,6 +54,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
54 /// </summary> 54 /// </summary>
55 public bool ReuseTextures { get; set; } 55 public bool ReuseTextures { get; set; }
56 56
57 /// <summary>
58 /// If false, then textures which have a low data size are not reused when ReuseTextures = true.
59 /// </summary>
60 /// <remarks>
61 /// LL viewers 3.3.4 and before appear to not fully render textures pulled from the viewer cache if those
62 /// textures have a relatively high pixel surface but a small data size. Typically, this appears to happen
63 /// if the data size is smaller than the viewer's discard level 2 size estimate. So if this is setting is
64 /// false, textures smaller than the calculation in IsSizeReuseable are always regenerated rather than reused
65 /// to work around this problem.</remarks>
66 public bool ReuseLowDataTextures { get; set; }
67
57 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>(); 68 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>();
58 69
59 private Dictionary<string, IDynamicTextureRender> RenderPlugins = 70 private Dictionary<string, IDynamicTextureRender> RenderPlugins =
@@ -83,18 +94,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
83 /// <summary> 94 /// <summary>
84 /// Called by code which actually renders the dynamic texture to supply texture data. 95 /// Called by code which actually renders the dynamic texture to supply texture data.
85 /// </summary> 96 /// </summary>
86 /// <param name="id"></param> 97 /// <param name="updaterId"></param>
87 /// <param name="data"></param> 98 /// <param name="texture"></param>
88 /// <param name="isReuseable">True if the data generated can be reused for subsequent identical requests</param> 99 public void ReturnData(UUID updaterId, IDynamicTexture texture)
89 public void ReturnData(UUID id, byte[] data, bool isReuseable)
90 { 100 {
91 DynamicTextureUpdater updater = null; 101 DynamicTextureUpdater updater = null;
92 102
93 lock (Updaters) 103 lock (Updaters)
94 { 104 {
95 if (Updaters.ContainsKey(id)) 105 if (Updaters.ContainsKey(updaterId))
96 { 106 {
97 updater = Updaters[id]; 107 updater = Updaters[updaterId];
98 } 108 }
99 } 109 }
100 110
@@ -103,11 +113,16 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
103 if (RegisteredScenes.ContainsKey(updater.SimUUID)) 113 if (RegisteredScenes.ContainsKey(updater.SimUUID))
104 { 114 {
105 Scene scene = RegisteredScenes[updater.SimUUID]; 115 Scene scene = RegisteredScenes[updater.SimUUID];
106 UUID newTextureID = updater.DataReceived(data, scene); 116 UUID newTextureID = updater.DataReceived(texture.Data, scene);
107 117
108 if (ReuseTextures && isReuseable && !updater.BlendWithOldTexture) 118 if (ReuseTextures
119 && !updater.BlendWithOldTexture
120 && texture.IsReuseable
121 && (ReuseLowDataTextures || IsDataSizeReuseable(texture)))
122 {
109 m_reuseableDynamicTextures.Store( 123 m_reuseableDynamicTextures.Store(
110 GenerateReusableTextureKey(updater.BodyData, updater.Params), newTextureID); 124 GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID);
125 }
111 } 126 }
112 } 127 }
113 128
@@ -123,6 +138,27 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
123 } 138 }
124 } 139 }
125 140
141 /// <summary>
142 /// Determines whether the texture is reuseable based on its data size.
143 /// </summary>
144 /// <remarks>
145 /// This is a workaround for a viewer bug where very small data size textures relative to their pixel size
146 /// are not redisplayed properly when pulled from cache. The calculation here is based on the typical discard
147 /// level of 2, a 'rate' of 0.125 and 4 components (which makes for a factor of 0.5).
148 /// </remarks>
149 /// <returns></returns>
150 private bool IsDataSizeReuseable(IDynamicTexture texture)
151 {
152// Console.WriteLine("{0} {1}", texture.Size.Width, texture.Size.Height);
153 int discardLevel2DataThreshold = (int)Math.Ceiling((texture.Size.Width >> 2) * (texture.Size.Height >> 2) * 0.5);
154
155// m_log.DebugFormat(
156// "[DYNAMIC TEXTURE MODULE]: Discard level 2 threshold {0}, texture data length {1}",
157// discardLevel2DataThreshold, texture.Data.Length);
158
159 return discardLevel2DataThreshold < texture.Data.Length;
160 }
161
126 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, 162 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
127 string extraParams, int updateTimer) 163 string extraParams, int updateTimer)
128 { 164 {
@@ -293,7 +329,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
293 { 329 {
294 IConfig texturesConfig = config.Configs["Textures"]; 330 IConfig texturesConfig = config.Configs["Textures"];
295 if (texturesConfig != null) 331 if (texturesConfig != null)
332 {
296 ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false); 333 ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false);
334 ReuseLowDataTextures = texturesConfig.GetBoolean("ReuseDynamicLowDataTextures", false);
335 }
297 336
298 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) 337 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
299 { 338 {
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
index 2b3a0f2..45e6527 100644
--- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -32,6 +32,7 @@ using System.Net;
32using Nini.Config; 32using Nini.Config;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.Imaging; 34using OpenMetaverse.Imaging;
35using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
35using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
37using log4net; 38using log4net;
@@ -73,12 +74,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
73// return false; 74// return false;
74// } 75// }
75 76
76 public byte[] ConvertUrl(string url, string extraParams) 77 public IDynamicTexture ConvertUrl(string url, string extraParams)
77 { 78 {
78 return null; 79 return null;
79 } 80 }
80 81
81 public byte[] ConvertData(string bodyData, string extraParams) 82 public IDynamicTexture ConvertData(string bodyData, string extraParams)
82 { 83 {
83 return null; 84 return null;
84 } 85 }
@@ -171,11 +172,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
171 172
172 private void HttpRequestReturn(IAsyncResult result) 173 private void HttpRequestReturn(IAsyncResult result)
173 { 174 {
174
175 RequestState state = (RequestState) result.AsyncState; 175 RequestState state = (RequestState) result.AsyncState;
176 WebRequest request = (WebRequest) state.Request; 176 WebRequest request = (WebRequest) state.Request;
177 Stream stream = null; 177 Stream stream = null;
178 byte[] imageJ2000 = new byte[0]; 178 byte[] imageJ2000 = new byte[0];
179 Size newSize = new Size(0, 0);
179 180
180 try 181 try
181 { 182 {
@@ -188,37 +189,43 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
188 try 189 try
189 { 190 {
190 Bitmap image = new Bitmap(stream); 191 Bitmap image = new Bitmap(stream);
191 Size newsize;
192 192
193 // TODO: make this a bit less hard coded 193 // TODO: make this a bit less hard coded
194 if ((image.Height < 64) && (image.Width < 64)) 194 if ((image.Height < 64) && (image.Width < 64))
195 { 195 {
196 newsize = new Size(32, 32); 196 newSize.Width = 32;
197 newSize.Height = 32;
197 } 198 }
198 else if ((image.Height < 128) && (image.Width < 128)) 199 else if ((image.Height < 128) && (image.Width < 128))
199 { 200 {
200 newsize = new Size(64, 64); 201 newSize.Width = 64;
202 newSize.Height = 64;
201 } 203 }
202 else if ((image.Height < 256) && (image.Width < 256)) 204 else if ((image.Height < 256) && (image.Width < 256))
203 { 205 {
204 newsize = new Size(128, 128); 206 newSize.Width = 128;
207 newSize.Height = 128;
205 } 208 }
206 else if ((image.Height < 512 && image.Width < 512)) 209 else if ((image.Height < 512 && image.Width < 512))
207 { 210 {
208 newsize = new Size(256, 256); 211 newSize.Width = 256;
212 newSize.Height = 256;
209 } 213 }
210 else if ((image.Height < 1024 && image.Width < 1024)) 214 else if ((image.Height < 1024 && image.Width < 1024))
211 { 215 {
212 newsize = new Size(512, 512); 216 newSize.Width = 512;
217 newSize.Height = 512;
213 } 218 }
214 else 219 else
215 { 220 {
216 newsize = new Size(1024, 1024); 221 newSize.Width = 1024;
222 newSize.Height = 1024;
217 } 223 }
218 224
219 Bitmap resize = new Bitmap(image, newsize); 225 using (Bitmap resize = new Bitmap(image, newSize))
220 226 {
221 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); 227 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
228 }
222 } 229 }
223 catch (Exception) 230 catch (Exception)
224 { 231 {
@@ -233,7 +240,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
233 } 240 }
234 catch (WebException) 241 catch (WebException)
235 { 242 {
236
237 } 243 }
238 finally 244 finally
239 { 245 {
@@ -243,10 +249,13 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
243 } 249 }
244 } 250 }
245 251
246 m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}", 252 m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}",
247 imageJ2000.Length, state.RequestID); 253 imageJ2000.Length, state.RequestID);
248 254
249 m_textureManager.ReturnData(state.RequestID, imageJ2000, false); 255 m_textureManager.ReturnData(
256 state.RequestID,
257 new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
258 request.RequestUri, null, imageJ2000, newSize, false));
250 } 259 }
251 260
252 #region Nested type: RequestState 261 #region Nested type: RequestState
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
index b50c0bd..41baccc 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -57,6 +57,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
57 57
58 m_dtm = new DynamicTextureModule(); 58 m_dtm = new DynamicTextureModule();
59 m_dtm.ReuseTextures = reuseTextures; 59 m_dtm.ReuseTextures = reuseTextures;
60// m_dtm.ReuseLowDataTextures = reuseTextures;
60 61
61 m_vrm = new VectorRenderModule(); 62 m_vrm = new VectorRenderModule();
62 63
@@ -201,6 +202,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
201 public void TestRepeatSameDrawReusingTexture() 202 public void TestRepeatSameDrawReusingTexture()
202 { 203 {
203 TestHelpers.InMethod(); 204 TestHelpers.InMethod();
205// TestHelpers.EnableLogging();
204 206
205 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; 207 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
206 208
@@ -228,6 +230,46 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
228 Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); 230 Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
229 } 231 }
230 232
233 /// <summary>
234 /// Test a low data dynamically generated texture such that it is treated as a low data texture that causes
235 /// problems for current viewers.
236 /// </summary>
237 /// <remarks>
238 /// As we do not set DynamicTextureModule.ReuseLowDataTextures = true in this test, it should not reuse the
239 /// texture
240 /// </remarks>
241 [Test]
242 public void TestRepeatSameDrawLowDataTexture()
243 {
244 TestHelpers.InMethod();
245// TestHelpers.EnableLogging();
246
247 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
248
249 SetupScene(true);
250 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
251
252 m_dtm.AddDynamicTextureData(
253 m_scene.RegionInfo.RegionID,
254 so.UUID,
255 m_vrm.GetContentType(),
256 dtText,
257 "1024",
258 0);
259
260 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
261
262 m_dtm.AddDynamicTextureData(
263 m_scene.RegionInfo.RegionID,
264 so.UUID,
265 m_vrm.GetContentType(),
266 dtText,
267 "1024",
268 0);
269
270 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
271 }
272
231 [Test] 273 [Test]
232 public void TestRepeatSameDrawDifferentExtraParamsReusingTexture() 274 public void TestRepeatSameDrawDifferentExtraParamsReusingTexture()
233 { 275 {
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index 0e7051e..d82551e 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -35,6 +35,7 @@ using System.Net;
35using Nini.Config; 35using Nini.Config;
36using OpenMetaverse; 36using OpenMetaverse;
37using OpenMetaverse.Imaging; 37using OpenMetaverse.Imaging;
38using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
38using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
40using log4net; 41using log4net;
@@ -85,20 +86,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
85// return lines.Any((str, r) => str.StartsWith("Image")); 86// return lines.Any((str, r) => str.StartsWith("Image"));
86// } 87// }
87 88
88 public byte[] ConvertUrl(string url, string extraParams) 89 public IDynamicTexture ConvertUrl(string url, string extraParams)
89 { 90 {
90 return null; 91 return null;
91 } 92 }
92 93
93 public byte[] ConvertData(string bodyData, string extraParams) 94 public IDynamicTexture ConvertData(string bodyData, string extraParams)
94 { 95 {
95 bool reuseable; 96 return Draw(bodyData, extraParams);
96 return Draw(bodyData, extraParams, out reuseable);
97 }
98
99 private byte[] ConvertData(string bodyData, string extraParams, out bool reuseable)
100 {
101 return Draw(bodyData, extraParams, out reuseable);
102 } 97 }
103 98
104 public bool AsyncConvertUrl(UUID id, string url, string extraParams) 99 public bool AsyncConvertUrl(UUID id, string url, string extraParams)
@@ -109,10 +104,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
109 public bool AsyncConvertData(UUID id, string bodyData, string extraParams) 104 public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
110 { 105 {
111 // XXX: This isn't actually being done asynchronously! 106 // XXX: This isn't actually being done asynchronously!
112 bool reuseable; 107 m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams));
113 byte[] data = ConvertData(bodyData, extraParams, out reuseable);
114
115 m_textureManager.ReturnData(id, data, reuseable);
116 108
117 return true; 109 return true;
118 } 110 }
@@ -191,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
191 183
192 #endregion 184 #endregion
193 185
194 private byte[] Draw(string data, string extraParams, out bool reuseable) 186 private IDynamicTexture Draw(string data, string extraParams)
195 { 187 {
196 // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha 188 // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha
197 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 189 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
@@ -334,6 +326,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
334 326
335 Bitmap bitmap = null; 327 Bitmap bitmap = null;
336 Graphics graph = null; 328 Graphics graph = null;
329 bool reuseable = false;
337 330
338 try 331 try
339 { 332 {
@@ -396,7 +389,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
396 e.Message, e.StackTrace); 389 e.Message, e.StackTrace);
397 } 390 }
398 391
399 return imageJ2000; 392 return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
393 data, extraParams, imageJ2000, new Size(width, height), reuseable);
400 } 394 }
401 finally 395 finally
402 { 396 {