diff options
author | Justin Clark-Casey (justincc) | 2012-08-28 23:06:53 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2012-08-28 23:06:53 +0100 |
commit | c1cece4b82d24a17a09b66c9ec3975190cc05d95 (patch) | |
tree | 702963505eb8a359d9e0ce6f92964b3a03ac3cbe /OpenSim/Region/CoreModules/Scripting/DynamicTexture | |
parent | Add IDynamicTextureManager.ConvertData() to match AsyncConvertData(). Remove... (diff) | |
download | opensim-SC_OLD-c1cece4b82d24a17a09b66c9ec3975190cc05d95.zip opensim-SC_OLD-c1cece4b82d24a17a09b66c9ec3975190cc05d95.tar.gz opensim-SC_OLD-c1cece4b82d24a17a09b66c9ec3975190cc05d95.tar.bz2 opensim-SC_OLD-c1cece4b82d24a17a09b66c9ec3975190cc05d95.tar.xz |
Add experimental DynamicTextureModule.ReuseTextures flag, currently only configurable on compile.
Disabled (status quo) by default.
This flag makes the dynamic texture module reuse cache previously dynamically generated textures given the same input commands and extra params for 24 hours.
This occurs as long as those commands would always generate the same texture (e.g. they do not contain commands to fetch data from the web).
This makes texture changing faster as a viewer-cached texture uuid is sent and may reduce simulator load in regions with generation of lots of dynamic textures.
A downside is that this stops expiry of old temporary dynamic textures from the cache,
Another downside is that a jpeg2000 generation that partially failed is currently not regenerated until restart or after 24 hours.
Diffstat (limited to 'OpenSim/Region/CoreModules/Scripting/DynamicTexture')
-rw-r--r-- | OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs | 169 |
1 files changed, 125 insertions, 44 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index 18bd018..13b7498 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs | |||
@@ -49,6 +49,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
49 | public const int DISP_EXPIRE = 1; | 49 | public const int DISP_EXPIRE = 1; |
50 | public const int DISP_TEMP = 2; | 50 | public const int DISP_TEMP = 2; |
51 | 51 | ||
52 | /// <summary> | ||
53 | /// If true then where possible dynamic textures are reused. | ||
54 | /// </summary> | ||
55 | public bool ReuseTextures { get; set; } | ||
56 | |||
52 | private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>(); | 57 | private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>(); |
53 | 58 | ||
54 | private Dictionary<string, IDynamicTextureRender> RenderPlugins = | 59 | private Dictionary<string, IDynamicTextureRender> RenderPlugins = |
@@ -56,6 +61,15 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
56 | 61 | ||
57 | private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>(); | 62 | private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>(); |
58 | 63 | ||
64 | /// <summary> | ||
65 | /// Record dynamic textures that we can reuse for a given data and parameter combination rather than | ||
66 | /// regenerate. | ||
67 | /// </summary> | ||
68 | /// <remarks> | ||
69 | /// Key is string.Format("{0}{1}", data | ||
70 | /// </remarks> | ||
71 | private Cache m_reuseableDynamicTextures; | ||
72 | |||
59 | #region IDynamicTextureManager Members | 73 | #region IDynamicTextureManager Members |
60 | 74 | ||
61 | public void RegisterRender(string handleType, IDynamicTextureRender render) | 75 | public void RegisterRender(string handleType, IDynamicTextureRender render) |
@@ -71,7 +85,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
71 | /// </summary> | 85 | /// </summary> |
72 | /// <param name="id"></param> | 86 | /// <param name="id"></param> |
73 | /// <param name="data"></param> | 87 | /// <param name="data"></param> |
74 | public void ReturnData(UUID id, byte[] data) | 88 | /// <param name="isReuseable">True if the data generated can be reused for subsequent identical requests</param> |
89 | public void ReturnData(UUID id, byte[] data, bool isReuseable) | ||
75 | { | 90 | { |
76 | DynamicTextureUpdater updater = null; | 91 | DynamicTextureUpdater updater = null; |
77 | 92 | ||
@@ -88,7 +103,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
88 | if (RegisteredScenes.ContainsKey(updater.SimUUID)) | 103 | if (RegisteredScenes.ContainsKey(updater.SimUUID)) |
89 | { | 104 | { |
90 | Scene scene = RegisteredScenes[updater.SimUUID]; | 105 | Scene scene = RegisteredScenes[updater.SimUUID]; |
91 | updater.DataReceived(data, scene); | 106 | UUID newTextureID = updater.DataReceived(data, scene); |
107 | |||
108 | if (ReuseTextures && isReuseable && !updater.BlendWithOldTexture) | ||
109 | m_reuseableDynamicTextures.Store( | ||
110 | GenerateReusableTextureKey(updater.BodyData, updater.Params), newTextureID); | ||
92 | } | 111 | } |
93 | } | 112 | } |
94 | 113 | ||
@@ -169,6 +188,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
169 | { | 188 | { |
170 | if (RenderPlugins.ContainsKey(contentType)) | 189 | if (RenderPlugins.ContainsKey(contentType)) |
171 | { | 190 | { |
191 | // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire | ||
192 | // them. | ||
193 | if (ReuseTextures) | ||
194 | disp = disp & ~DISP_EXPIRE; | ||
195 | |||
172 | DynamicTextureUpdater updater = new DynamicTextureUpdater(); | 196 | DynamicTextureUpdater updater = new DynamicTextureUpdater(); |
173 | updater.SimUUID = simID; | 197 | updater.SimUUID = simID; |
174 | updater.PrimID = primID; | 198 | updater.PrimID = primID; |
@@ -183,21 +207,49 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
183 | updater.Url = "Local image"; | 207 | updater.Url = "Local image"; |
184 | updater.Disp = disp; | 208 | updater.Disp = disp; |
185 | 209 | ||
186 | lock (Updaters) | 210 | object reusableTextureUUID = null; |
211 | |||
212 | if (ReuseTextures) | ||
213 | reusableTextureUUID | ||
214 | = m_reuseableDynamicTextures.Get(GenerateReusableTextureKey(data, extraParams)); | ||
215 | |||
216 | // We cannot reuse a dynamic texture if the data is going to be blended with something already there. | ||
217 | if (reusableTextureUUID == null || updater.BlendWithOldTexture) | ||
187 | { | 218 | { |
188 | if (!Updaters.ContainsKey(updater.UpdaterID)) | 219 | lock (Updaters) |
189 | { | 220 | { |
190 | Updaters.Add(updater.UpdaterID, updater); | 221 | if (!Updaters.ContainsKey(updater.UpdaterID)) |
222 | { | ||
223 | Updaters.Add(updater.UpdaterID, updater); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); | ||
228 | } | ||
229 | else | ||
230 | { | ||
231 | // No need to add to updaters as the texture is always the same. Not that this functionality | ||
232 | // apppears to be implemented anyway. | ||
233 | if (RegisteredScenes.ContainsKey(updater.SimUUID)) | ||
234 | { | ||
235 | SceneObjectPart part = RegisteredScenes[updater.SimUUID].GetSceneObjectPart(updater.PrimID); | ||
236 | |||
237 | if (part != null) | ||
238 | updater.UpdatePart(part, (UUID)reusableTextureUUID); | ||
191 | } | 239 | } |
192 | } | 240 | } |
193 | 241 | ||
194 | RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); | ||
195 | return updater.UpdaterID; | 242 | return updater.UpdaterID; |
196 | } | 243 | } |
197 | 244 | ||
198 | return UUID.Zero; | 245 | return UUID.Zero; |
199 | } | 246 | } |
200 | 247 | ||
248 | private string GenerateReusableTextureKey(string data, string extraParams) | ||
249 | { | ||
250 | return string.Format("{0}{1}", data, extraParams); | ||
251 | } | ||
252 | |||
201 | public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, | 253 | public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, |
202 | out double xSize, out double ySize) | 254 | out double xSize, out double ySize) |
203 | { | 255 | { |
@@ -224,6 +276,12 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
224 | 276 | ||
225 | public void PostInitialise() | 277 | public void PostInitialise() |
226 | { | 278 | { |
279 | // ReuseTextures = true; | ||
280 | if (ReuseTextures) | ||
281 | { | ||
282 | m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative); | ||
283 | m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0); | ||
284 | } | ||
227 | } | 285 | } |
228 | 286 | ||
229 | public void Close() | 287 | public void Close() |
@@ -269,9 +327,60 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
269 | } | 327 | } |
270 | 328 | ||
271 | /// <summary> | 329 | /// <summary> |
330 | /// Update the given part with the new texture. | ||
331 | /// </summary> | ||
332 | /// <returns> | ||
333 | /// The old texture UUID. | ||
334 | /// </returns> | ||
335 | public UUID UpdatePart(SceneObjectPart part, UUID textureID) | ||
336 | { | ||
337 | UUID oldID; | ||
338 | |||
339 | lock (part) | ||
340 | { | ||
341 | // mostly keep the values from before | ||
342 | Primitive.TextureEntry tmptex = part.Shape.Textures; | ||
343 | |||
344 | // FIXME: Need to return the appropriate ID if only a single face is replaced. | ||
345 | oldID = tmptex.DefaultTexture.TextureID; | ||
346 | |||
347 | if (Face == ALL_SIDES) | ||
348 | { | ||
349 | oldID = tmptex.DefaultTexture.TextureID; | ||
350 | tmptex.DefaultTexture.TextureID = textureID; | ||
351 | } | ||
352 | else | ||
353 | { | ||
354 | try | ||
355 | { | ||
356 | Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); | ||
357 | texface.TextureID = textureID; | ||
358 | tmptex.FaceTextures[Face] = texface; | ||
359 | } | ||
360 | catch (Exception) | ||
361 | { | ||
362 | tmptex.DefaultTexture.TextureID = textureID; | ||
363 | } | ||
364 | } | ||
365 | |||
366 | // I'm pretty sure we always want to force this to true | ||
367 | // I'm pretty sure noone whats to set fullbright true if it wasn't true before. | ||
368 | // tmptex.DefaultTexture.Fullbright = true; | ||
369 | |||
370 | part.UpdateTextureEntry(tmptex.GetBytes()); | ||
371 | } | ||
372 | |||
373 | return oldID; | ||
374 | } | ||
375 | |||
376 | /// <summary> | ||
272 | /// Called once new texture data has been received for this updater. | 377 | /// Called once new texture data has been received for this updater. |
273 | /// </summary> | 378 | /// </summary> |
274 | public void DataReceived(byte[] data, Scene scene) | 379 | /// <param name="data"></param> |
380 | /// <param name="scene"></param> | ||
381 | /// <param name="isReuseable">True if the data given is reuseable.</param> | ||
382 | /// <returns>The asset UUID given to the incoming data.</returns> | ||
383 | public UUID DataReceived(byte[] data, Scene scene) | ||
275 | { | 384 | { |
276 | SceneObjectPart part = scene.GetSceneObjectPart(PrimID); | 385 | SceneObjectPart part = scene.GetSceneObjectPart(PrimID); |
277 | 386 | ||
@@ -281,7 +390,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
281 | String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); | 390 | String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); |
282 | scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, | 391 | scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, |
283 | 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); | 392 | 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); |
284 | return; | 393 | |
394 | return UUID.Zero; | ||
285 | } | 395 | } |
286 | 396 | ||
287 | byte[] assetData = null; | 397 | byte[] assetData = null; |
@@ -323,52 +433,23 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
323 | cacheLayerDecode = null; | 433 | cacheLayerDecode = null; |
324 | } | 434 | } |
325 | 435 | ||
326 | UUID oldID = UUID.Zero; | 436 | UUID oldID = UpdatePart(part, asset.FullID); |
327 | |||
328 | lock (part) | ||
329 | { | ||
330 | // mostly keep the values from before | ||
331 | Primitive.TextureEntry tmptex = part.Shape.Textures; | ||
332 | |||
333 | // remove the old asset from the cache | ||
334 | oldID = tmptex.DefaultTexture.TextureID; | ||
335 | |||
336 | if (Face == ALL_SIDES) | ||
337 | { | ||
338 | tmptex.DefaultTexture.TextureID = asset.FullID; | ||
339 | } | ||
340 | else | ||
341 | { | ||
342 | try | ||
343 | { | ||
344 | Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); | ||
345 | texface.TextureID = asset.FullID; | ||
346 | tmptex.FaceTextures[Face] = texface; | ||
347 | } | ||
348 | catch (Exception) | ||
349 | { | ||
350 | tmptex.DefaultTexture.TextureID = asset.FullID; | ||
351 | } | ||
352 | } | ||
353 | |||
354 | // I'm pretty sure we always want to force this to true | ||
355 | // I'm pretty sure noone whats to set fullbright true if it wasn't true before. | ||
356 | // tmptex.DefaultTexture.Fullbright = true; | ||
357 | |||
358 | part.UpdateTextureEntry(tmptex.GetBytes()); | ||
359 | } | ||
360 | 437 | ||
361 | if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) | 438 | if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) |
362 | { | 439 | { |
363 | if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString()); | 440 | if (oldAsset == null) |
441 | oldAsset = scene.AssetService.Get(oldID.ToString()); | ||
442 | |||
364 | if (oldAsset != null) | 443 | if (oldAsset != null) |
365 | { | 444 | { |
366 | if (oldAsset.Temporary == true) | 445 | if (oldAsset.Temporary) |
367 | { | 446 | { |
368 | scene.AssetService.Delete(oldID.ToString()); | 447 | scene.AssetService.Delete(oldID.ToString()); |
369 | } | 448 | } |
370 | } | 449 | } |
371 | } | 450 | } |
451 | |||
452 | return asset.FullID; | ||
372 | } | 453 | } |
373 | 454 | ||
374 | private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) | 455 | private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) |