From 1369058280c4cf399d46df1508b80cad99f1247e Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Wed, 22 Aug 2012 23:04:17 +0100
Subject: Lock disposal of separate gdi+ objects under different threads since
this prevents malloc heap corruption seen under Ubuntu 10.04.1 and 11.04 -
probably a libcairo issue
In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously,
the native malloc heap can become corrupted, possibly due to a double free(). This may be due to
bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were
seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed
under lock.
---
.../Scripting/VectorRender/VectorRenderModule.cs | 68 +++++++++++++---------
1 file changed, 42 insertions(+), 26 deletions(-)
(limited to 'OpenSim/Region/CoreModules/Scripting')
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index ca320e1..c48a703 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -308,36 +308,44 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
try
{
- if (alpha == 256)
- bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
- else
- bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
-
- graph = Graphics.FromImage(bitmap);
-
- // this is really just to save people filling the
- // background color in their scripts, only do when fully opaque
- if (alpha >= 255)
+ // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously,
+ // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to
+ // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were
+ // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed
+ // under lock.
+ lock (this)
{
- using (SolidBrush bgFillBrush = new SolidBrush(bgColor))
+ if (alpha == 256)
+ bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
+ else
+ bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
+
+ graph = Graphics.FromImage(bitmap);
+
+ // this is really just to save people filling the
+ // background color in their scripts, only do when fully opaque
+ if (alpha >= 255)
{
- graph.FillRectangle(bgFillBrush, 0, 0, width, height);
+ using (SolidBrush bgFillBrush = new SolidBrush(bgColor))
+ {
+ graph.FillRectangle(bgFillBrush, 0, 0, width, height);
+ }
}
- }
-
- for (int w = 0; w < bitmap.Width; w++)
- {
- if (alpha <= 255)
+
+ for (int w = 0; w < bitmap.Width; w++)
{
- for (int h = 0; h < bitmap.Height; h++)
+ if (alpha <= 255)
{
- bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
+ for (int h = 0; h < bitmap.Height; h++)
+ {
+ bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
+ }
}
}
+
+ GDIDraw(data, graph, altDataDelim);
}
- GDIDraw(data, graph, altDataDelim);
-
byte[] imageJ2000 = new byte[0];
try
@@ -355,11 +363,19 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
}
finally
{
- if (graph != null)
- graph.Dispose();
-
- if (bitmap != null)
- bitmap.Dispose();
+ // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously,
+ // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to
+ // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were
+ // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed
+ // under lock.
+ lock (this)
+ {
+ if (graph != null)
+ graph.Dispose();
+
+ if (bitmap != null)
+ bitmap.Dispose();
+ }
}
}
--
cgit v1.1
From e90168c7382f7750faa001542652e2316841c961 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Mon, 27 Aug 2012 22:42:40 +0100
Subject: Add VectorRenderModuleTests.TestRepeatDraw()
---
.../VectorRender/Tests/VectorRenderModuleTests.cs | 59 ++++++++++++++++++----
1 file changed, 48 insertions(+), 11 deletions(-)
(limited to 'OpenSim/Region/CoreModules/Scripting')
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
index 9787c8c..f9b5a59 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -45,31 +45,68 @@ using OpenSim.Tests.Common.Mock;
namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
{
[TestFixture]
- public class VectorRenderModuleTests
+ public class VectorRenderModuleTests : OpenSimTestCase
{
+ Scene m_scene;
+ DynamicTextureModule m_dtm;
+ VectorRenderModule m_vrm;
+
+ [SetUp]
+ public void SetUp()
+ {
+ m_scene = new SceneHelpers().SetupScene();
+ m_dtm = new DynamicTextureModule();
+ m_vrm = new VectorRenderModule();
+ SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm);
+ }
+
[Test]
public void TestDraw()
{
TestHelpers.InMethod();
- Scene scene = new SceneHelpers().SetupScene();
- DynamicTextureModule dtm = new DynamicTextureModule();
- VectorRenderModule vrm = new VectorRenderModule();
- SceneHelpers.SetupSceneModules(scene, dtm, vrm);
-
- SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
- dtm.AddDynamicTextureData(
- scene.RegionInfo.RegionID,
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
so.UUID,
- vrm.GetContentType(),
+ m_vrm.GetContentType(),
"PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
"",
0);
-
Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
+
+ [Test]
+ public void TestRepeatDraw()
+ {
+ TestHelpers.InMethod();
+
+ string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
+
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+ }
}
}
\ No newline at end of file
--
cgit v1.1
From 3082fdd0f6d73fa07fe2266170fcd3e5e572f2a2 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Mon, 27 Aug 2012 22:58:20 +0100
Subject: Add VectorRenderModuleTests.TestRepeatDrawContainingImage()
---
.../VectorRender/Tests/VectorRenderModuleTests.cs | 31 ++++++++++++++++++++++
1 file changed, 31 insertions(+)
(limited to 'OpenSim/Region/CoreModules/Scripting')
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
index f9b5a59..21e1d54 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -108,5 +108,36 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
+
+ [Test]
+ public void TestRepeatDrawContainingImage()
+ {
+ TestHelpers.InMethod();
+
+ string dtText
+ = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
+
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+ }
}
}
\ No newline at end of file
--
cgit v1.1
From 4e26d039d6ffe03ae9509120015b39692bad44f9 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Mon, 27 Aug 2012 23:03:21 +0100
Subject: Add VectorRenderModule.TestRepeatSameDrawDifferentExtraParams()
---
.../VectorRender/Tests/VectorRenderModuleTests.cs | 34 ++++++++++++++++++++--
1 file changed, 32 insertions(+), 2 deletions(-)
(limited to 'OpenSim/Region/CoreModules/Scripting')
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
index 21e1d54..180ea9f 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -80,7 +80,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
}
[Test]
- public void TestRepeatDraw()
+ public void TestRepeatSameDraw()
{
TestHelpers.InMethod();
@@ -110,7 +110,37 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
}
[Test]
- public void TestRepeatDrawContainingImage()
+ public void TestRepeatSameDrawDifferentExtraParams()
+ {
+ TestHelpers.InMethod();
+
+ string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
+
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "alpha:250",
+ 0);
+
+ Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+ }
+
+ [Test]
+ public void TestRepeatSameDrawContainingImage()
{
TestHelpers.InMethod();
--
cgit v1.1
From ab9bfe5156d955ca02b7cfcb0ccb5919f6b0743d Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Mon, 27 Aug 2012 23:06:37 +0100
Subject: minor: Simplify return of vector render module name and some very
minor removal of unncessary syntax clutter
---
.../CoreModules/Scripting/VectorRender/VectorRenderModule.cs | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
(limited to 'OpenSim/Region/CoreModules/Scripting')
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index c48a703..f988c0e 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -47,7 +47,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- private string m_name = "VectorRenderModule";
private Scene m_scene;
private IDynamicTextureManager m_textureManager;
private Graphics m_graph;
@@ -61,12 +60,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
public string GetContentType()
{
- return ("vector");
+ return "vector";
}
public string GetName()
{
- return m_name;
+ return Name;
}
public bool SupportsAsynchronous()
@@ -152,7 +151,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
public string Name
{
- get { return m_name; }
+ get { return "VectorRenderModule"; }
}
public bool IsSharedModule
--
cgit v1.1
From aa44df9c04658cfa0af9a0f203faea5e493c6f25 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Tue, 28 Aug 2012 20:35:17 +0100
Subject: Add IDynamicTextureManager.ConvertData() to match AsyncConvertData().
Remove mismatching ConvertStream() where there is no AsyncConvertStream and
neither IDynamicTextureManager implementer implements this method.
---
.../CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs | 2 +-
.../CoreModules/Scripting/VectorRender/VectorRenderModule.cs | 11 ++++++-----
2 files changed, 7 insertions(+), 6 deletions(-)
(limited to 'OpenSim/Region/CoreModules/Scripting')
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
index 6f83948..6e38b3f 100644
--- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -72,7 +72,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
return null;
}
- public byte[] ConvertStream(Stream data, string extraParams)
+ public byte[] ConvertData(string bodyData, string extraParams)
{
return null;
}
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index f988c0e..3a758c5 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -78,9 +78,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
return null;
}
- public byte[] ConvertStream(Stream data, string extraParams)
+ public byte[] ConvertData(string bodyData, string extraParams)
{
- return null;
+ return Draw(bodyData, extraParams);
}
public bool AsyncConvertUrl(UUID id, string url, string extraParams)
@@ -90,7 +90,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
{
- Draw(bodyData, id, extraParams);
+ // XXX: This isn't actually being done asynchronously!
+ m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams));
return true;
}
@@ -161,7 +162,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
#endregion
- private void Draw(string data, UUID id, string extraParams)
+ private byte[] Draw(string data, string extraParams)
{
// 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
// we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
@@ -358,7 +359,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
e.Message, e.StackTrace);
}
- m_textureManager.ReturnData(id, imageJ2000);
+ return imageJ2000;
}
finally
{
--
cgit v1.1
From c1cece4b82d24a17a09b66c9ec3975190cc05d95 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Tue, 28 Aug 2012 23:06:53 +0100
Subject: 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.
---
.../DynamicTexture/DynamicTextureModule.cs | 169 +++++++++++++++------
.../Scripting/LoadImageURL/LoadImageURLModule.cs | 10 +-
.../VectorRender/Tests/VectorRenderModuleTests.cs | 125 ++++++++++++++-
.../Scripting/VectorRender/VectorRenderModule.cs | 48 +++++-
4 files changed, 297 insertions(+), 55 deletions(-)
(limited to 'OpenSim/Region/CoreModules/Scripting')
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
public const int DISP_EXPIRE = 1;
public const int DISP_TEMP = 2;
+ ///
+ /// If true then where possible dynamic textures are reused.
+ ///
+ public bool ReuseTextures { get; set; }
+
private Dictionary RegisteredScenes = new Dictionary();
private Dictionary RenderPlugins =
@@ -56,6 +61,15 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
private Dictionary Updaters = new Dictionary();
+ ///
+ /// Record dynamic textures that we can reuse for a given data and parameter combination rather than
+ /// regenerate.
+ ///
+ ///
+ /// Key is string.Format("{0}{1}", data
+ ///
+ private Cache m_reuseableDynamicTextures;
+
#region IDynamicTextureManager Members
public void RegisterRender(string handleType, IDynamicTextureRender render)
@@ -71,7 +85,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
///
///
///
- public void ReturnData(UUID id, byte[] data)
+ /// True if the data generated can be reused for subsequent identical requests
+ public void ReturnData(UUID id, byte[] data, bool isReuseable)
{
DynamicTextureUpdater updater = null;
@@ -88,7 +103,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
if (RegisteredScenes.ContainsKey(updater.SimUUID))
{
Scene scene = RegisteredScenes[updater.SimUUID];
- updater.DataReceived(data, scene);
+ UUID newTextureID = updater.DataReceived(data, scene);
+
+ if (ReuseTextures && isReuseable && !updater.BlendWithOldTexture)
+ m_reuseableDynamicTextures.Store(
+ GenerateReusableTextureKey(updater.BodyData, updater.Params), newTextureID);
}
}
@@ -169,6 +188,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
{
if (RenderPlugins.ContainsKey(contentType))
{
+ // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire
+ // them.
+ if (ReuseTextures)
+ disp = disp & ~DISP_EXPIRE;
+
DynamicTextureUpdater updater = new DynamicTextureUpdater();
updater.SimUUID = simID;
updater.PrimID = primID;
@@ -183,21 +207,49 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
updater.Url = "Local image";
updater.Disp = disp;
- lock (Updaters)
+ object reusableTextureUUID = null;
+
+ if (ReuseTextures)
+ reusableTextureUUID
+ = m_reuseableDynamicTextures.Get(GenerateReusableTextureKey(data, extraParams));
+
+ // We cannot reuse a dynamic texture if the data is going to be blended with something already there.
+ if (reusableTextureUUID == null || updater.BlendWithOldTexture)
{
- if (!Updaters.ContainsKey(updater.UpdaterID))
+ lock (Updaters)
{
- Updaters.Add(updater.UpdaterID, updater);
+ if (!Updaters.ContainsKey(updater.UpdaterID))
+ {
+ Updaters.Add(updater.UpdaterID, updater);
+ }
+ }
+
+ RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
+ }
+ else
+ {
+ // No need to add to updaters as the texture is always the same. Not that this functionality
+ // apppears to be implemented anyway.
+ if (RegisteredScenes.ContainsKey(updater.SimUUID))
+ {
+ SceneObjectPart part = RegisteredScenes[updater.SimUUID].GetSceneObjectPart(updater.PrimID);
+
+ if (part != null)
+ updater.UpdatePart(part, (UUID)reusableTextureUUID);
}
}
- RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
return updater.UpdaterID;
}
return UUID.Zero;
}
+ private string GenerateReusableTextureKey(string data, string extraParams)
+ {
+ return string.Format("{0}{1}", data, extraParams);
+ }
+
public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
out double xSize, out double ySize)
{
@@ -224,6 +276,12 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
public void PostInitialise()
{
+// ReuseTextures = true;
+ if (ReuseTextures)
+ {
+ m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative);
+ m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0);
+ }
}
public void Close()
@@ -269,9 +327,60 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
}
///
+ /// Update the given part with the new texture.
+ ///
+ ///
+ /// The old texture UUID.
+ ///
+ public UUID UpdatePart(SceneObjectPart part, UUID textureID)
+ {
+ UUID oldID;
+
+ lock (part)
+ {
+ // mostly keep the values from before
+ Primitive.TextureEntry tmptex = part.Shape.Textures;
+
+ // FIXME: Need to return the appropriate ID if only a single face is replaced.
+ oldID = tmptex.DefaultTexture.TextureID;
+
+ if (Face == ALL_SIDES)
+ {
+ oldID = tmptex.DefaultTexture.TextureID;
+ tmptex.DefaultTexture.TextureID = textureID;
+ }
+ else
+ {
+ try
+ {
+ Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
+ texface.TextureID = textureID;
+ tmptex.FaceTextures[Face] = texface;
+ }
+ catch (Exception)
+ {
+ tmptex.DefaultTexture.TextureID = textureID;
+ }
+ }
+
+ // I'm pretty sure we always want to force this to true
+ // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
+ // tmptex.DefaultTexture.Fullbright = true;
+
+ part.UpdateTextureEntry(tmptex.GetBytes());
+ }
+
+ return oldID;
+ }
+
+ ///
/// Called once new texture data has been received for this updater.
///
- public void DataReceived(byte[] data, Scene scene)
+ ///
+ ///
+ /// True if the data given is reuseable.
+ /// The asset UUID given to the incoming data.
+ public UUID DataReceived(byte[] data, Scene scene)
{
SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
@@ -281,7 +390,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url);
scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say,
0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false);
- return;
+
+ return UUID.Zero;
}
byte[] assetData = null;
@@ -323,52 +433,23 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
cacheLayerDecode = null;
}
- UUID oldID = UUID.Zero;
-
- lock (part)
- {
- // mostly keep the values from before
- Primitive.TextureEntry tmptex = part.Shape.Textures;
-
- // remove the old asset from the cache
- oldID = tmptex.DefaultTexture.TextureID;
-
- if (Face == ALL_SIDES)
- {
- tmptex.DefaultTexture.TextureID = asset.FullID;
- }
- else
- {
- try
- {
- Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
- texface.TextureID = asset.FullID;
- tmptex.FaceTextures[Face] = texface;
- }
- catch (Exception)
- {
- tmptex.DefaultTexture.TextureID = asset.FullID;
- }
- }
-
- // I'm pretty sure we always want to force this to true
- // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
- // tmptex.DefaultTexture.Fullbright = true;
-
- part.UpdateTextureEntry(tmptex.GetBytes());
- }
+ UUID oldID = UpdatePart(part, asset.FullID);
if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0))
{
- if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString());
+ if (oldAsset == null)
+ oldAsset = scene.AssetService.Get(oldID.ToString());
+
if (oldAsset != null)
{
- if (oldAsset.Temporary == true)
+ if (oldAsset.Temporary)
{
scene.AssetService.Delete(oldID.ToString());
}
}
}
+
+ return asset.FullID;
}
private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha)
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
index 6e38b3f..2b3a0f2 100644
--- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -67,6 +67,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
return true;
}
+// public bool AlwaysIdenticalConversion(string bodyData, string extraParams)
+// {
+// // We don't support conversion of body data.
+// return false;
+// }
+
public byte[] ConvertUrl(string url, string extraParams)
{
return null;
@@ -236,9 +242,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
stream.Close();
}
}
+
m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}",
imageJ2000.Length, state.RequestID);
- m_textureManager.ReturnData(state.RequestID, imageJ2000);
+
+ m_textureManager.ReturnData(state.RequestID, imageJ2000, false);
}
#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 180ea9f..b50c0bd 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -51,12 +51,15 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
DynamicTextureModule m_dtm;
VectorRenderModule m_vrm;
- [SetUp]
- public void SetUp()
+ private void SetupScene(bool reuseTextures)
{
m_scene = new SceneHelpers().SetupScene();
+
m_dtm = new DynamicTextureModule();
+ m_dtm.ReuseTextures = reuseTextures;
+
m_vrm = new VectorRenderModule();
+
SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm);
}
@@ -65,6 +68,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
{
TestHelpers.InMethod();
+ SetupScene(false);
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
@@ -86,6 +90,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
+ SetupScene(false);
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
m_dtm.AddDynamicTextureData(
@@ -116,6 +121,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
+ SetupScene(false);
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
m_dtm.AddDynamicTextureData(
@@ -147,6 +153,121 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
string dtText
= "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
+ SetupScene(false);
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+ }
+
+ [Test]
+ public void TestDrawReusingTexture()
+ {
+ TestHelpers.InMethod();
+
+ SetupScene(true);
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
+ UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
+ "",
+ 0);
+
+ Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+ }
+
+ [Test]
+ public void TestRepeatSameDrawReusingTexture()
+ {
+ TestHelpers.InMethod();
+
+ string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
+
+ SetupScene(true);
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+ }
+
+ [Test]
+ public void TestRepeatSameDrawDifferentExtraParamsReusingTexture()
+ {
+ TestHelpers.InMethod();
+
+ string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
+
+ SetupScene(true);
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "alpha:250",
+ 0);
+
+ Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+ }
+
+ [Test]
+ public void TestRepeatSameDrawContainingImageReusingTexture()
+ {
+ TestHelpers.InMethod();
+
+ string dtText
+ = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
+
+ SetupScene(true);
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
m_dtm.AddDynamicTextureData(
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index 3a758c5..4268f2e 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -30,6 +30,7 @@ using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
+using System.Linq;
using System.Net;
using Nini.Config;
using OpenMetaverse;
@@ -73,6 +74,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
return true;
}
+// public bool AlwaysIdenticalConversion(string bodyData, string extraParams)
+// {
+// string[] lines = GetLines(bodyData);
+// return lines.Any((str, r) => str.StartsWith("Image"));
+// }
+
public byte[] ConvertUrl(string url, string extraParams)
{
return null;
@@ -80,7 +87,13 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
public byte[] ConvertData(string bodyData, string extraParams)
{
- return Draw(bodyData, extraParams);
+ bool reuseable;
+ return Draw(bodyData, extraParams, out reuseable);
+ }
+
+ private byte[] ConvertData(string bodyData, string extraParams, out bool reuseable)
+ {
+ return Draw(bodyData, extraParams, out reuseable);
}
public bool AsyncConvertUrl(UUID id, string url, string extraParams)
@@ -91,7 +104,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
{
// XXX: This isn't actually being done asynchronously!
- m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams));
+ bool reuseable;
+ byte[] data = ConvertData(bodyData, extraParams, out reuseable);
+
+ m_textureManager.ReturnData(id, data, reuseable);
+
return true;
}
@@ -162,7 +179,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
#endregion
- private byte[] Draw(string data, string extraParams)
+ private byte[] Draw(string data, string extraParams, out bool reuseable)
{
// 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
// we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
@@ -343,7 +360,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
}
}
- GDIDraw(data, graph, altDataDelim);
+ GDIDraw(data, graph, altDataDelim, out reuseable);
}
byte[] imageJ2000 = new byte[0];
@@ -434,8 +451,21 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
}
*/
- private void GDIDraw(string data, Graphics graph, char dataDelim)
+ ///
+ /// Split input data into discrete command lines.
+ ///
+ ///
+ ///
+ ///
+ private string[] GetLines(string data, char dataDelim)
{
+ char[] lineDelimiter = { dataDelim };
+ return data.Split(lineDelimiter);
+ }
+
+ private void GDIDraw(string data, Graphics graph, char dataDelim, out bool reuseable)
+ {
+ reuseable = true;
Point startPoint = new Point(0, 0);
Point endPoint = new Point(0, 0);
Pen drawPen = null;
@@ -450,11 +480,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
myFont = new Font(fontName, fontSize);
myBrush = new SolidBrush(Color.Black);
- char[] lineDelimiter = {dataDelim};
char[] partsDelimiter = {','};
- string[] lines = data.Split(lineDelimiter);
- foreach (string line in lines)
+ foreach (string line in GetLines(data, dataDelim))
{
string nextLine = line.Trim();
//replace with switch, or even better, do some proper parsing
@@ -485,6 +513,10 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
}
else if (nextLine.StartsWith("Image"))
{
+ // We cannot reuse any generated texture involving fetching an image via HTTP since that image
+ // can change.
+ reuseable = false;
+
float x = 0;
float y = 0;
GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y);
--
cgit v1.1
From 3d736d575ff9670ac813f13eb1cff07dea10328b Mon Sep 17 00:00:00 2001
From: Mic Bowman
Date: Wed, 29 Aug 2012 14:56:51 -0700
Subject: This partially implements the LSL function to set the response type
for an HTTP request. Since the "official" LSL function limits the use of the
response type, it is implemented as osSetContentType with a string for the
content mime type and a threat level of high. With this function you should
be able to implement rather functional media-on-a-prim application with much
less difficulty.
---
.../CoreModules/Scripting/LSLHttp/UrlModule.cs | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
(limited to 'OpenSim/Region/CoreModules/Scripting')
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 05d54f0..53a9679 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -84,6 +84,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
public string body;
public int responseCode;
public string responseBody;
+ public string responseType = "text/plain";
//public ManualResetEvent ev;
public bool requestDone;
public int startTime;
@@ -302,6 +303,22 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
}
}
+ public void HttpContentType(UUID request, string type)
+ {
+ lock (m_UrlMap)
+ {
+ if (m_RequestMap.ContainsKey(request))
+ {
+ UrlData urlData = m_RequestMap[request];
+ urlData.requests[request].responseType = type;
+ }
+ else
+ {
+ m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
+ }
+ }
+ }
+
public void HttpResponse(UUID request, int status, string body)
{
lock (m_UrlMap)
@@ -504,7 +521,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
//put response
response["int_response_code"] = requestData.responseCode;
response["str_response_string"] = requestData.responseBody;
- response["content_type"] = "text/plain";
+ response["content_type"] = requestData.responseType;
+ // response["content_type"] = "text/plain";
response["keepalive"] = false;
response["reusecontext"] = false;
--
cgit v1.1
From d89b974680af52a2d950237962240dde82ff4a85 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Thu, 30 Aug 2012 22:28:45 +0100
Subject: If the compile-time DynamicTextureModule.ReuseTextures flag is set,
check metadata still exists for any reused asset in case some other process
has removed it from the cache.
---
.../DynamicTexture/DynamicTextureModule.cs | 102 ++++++++++++---------
1 file changed, 59 insertions(+), 43 deletions(-)
(limited to 'OpenSim/Region/CoreModules/Scripting')
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
index 13b7498..f169117 100644
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -186,63 +186,79 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face)
{
- if (RenderPlugins.ContainsKey(contentType))
- {
- // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire
- // them.
- if (ReuseTextures)
- disp = disp & ~DISP_EXPIRE;
+ if (!RenderPlugins.ContainsKey(contentType))
+ return UUID.Zero;
- DynamicTextureUpdater updater = new DynamicTextureUpdater();
- updater.SimUUID = simID;
- updater.PrimID = primID;
- updater.ContentType = contentType;
- updater.BodyData = data;
- updater.UpdateTimer = updateTimer;
- updater.UpdaterID = UUID.Random();
- updater.Params = extraParams;
- updater.BlendWithOldTexture = SetBlending;
- updater.FrontAlpha = AlphaValue;
- updater.Face = face;
- updater.Url = "Local image";
- updater.Disp = disp;
+ Scene scene;
+ RegisteredScenes.TryGetValue(simID, out scene);
+
+ if (scene == null)
+ return UUID.Zero;
- object reusableTextureUUID = null;
+ SceneObjectPart part = scene.GetSceneObjectPart(primID);
- if (ReuseTextures)
- reusableTextureUUID
- = m_reuseableDynamicTextures.Get(GenerateReusableTextureKey(data, extraParams));
+ if (part == null)
+ return UUID.Zero;
+
+ // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire
+ // them.
+ if (ReuseTextures)
+ disp = disp & ~DISP_EXPIRE;
+
+ DynamicTextureUpdater updater = new DynamicTextureUpdater();
+ updater.SimUUID = simID;
+ updater.PrimID = primID;
+ updater.ContentType = contentType;
+ updater.BodyData = data;
+ updater.UpdateTimer = updateTimer;
+ updater.UpdaterID = UUID.Random();
+ updater.Params = extraParams;
+ updater.BlendWithOldTexture = SetBlending;
+ updater.FrontAlpha = AlphaValue;
+ updater.Face = face;
+ updater.Url = "Local image";
+ updater.Disp = disp;
+
+ object objReusableTextureUUID = null;
+
+ if (ReuseTextures && !updater.BlendWithOldTexture)
+ {
+ string reuseableTextureKey = GenerateReusableTextureKey(data, extraParams);
+ objReusableTextureUUID = m_reuseableDynamicTextures.Get(reuseableTextureKey);
- // We cannot reuse a dynamic texture if the data is going to be blended with something already there.
- if (reusableTextureUUID == null || updater.BlendWithOldTexture)
+ if (objReusableTextureUUID != null)
{
- lock (Updaters)
+ // If something else has removed this temporary asset from the cache, detect and invalidate
+ // our cached uuid.
+ if (scene.AssetService.GetMetadata(objReusableTextureUUID.ToString()) == null)
{
- if (!Updaters.ContainsKey(updater.UpdaterID))
- {
- Updaters.Add(updater.UpdaterID, updater);
- }
+ m_reuseableDynamicTextures.Invalidate(reuseableTextureKey);
+ objReusableTextureUUID = null;
}
-
- RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
}
- else
+ }
+
+ // We cannot reuse a dynamic texture if the data is going to be blended with something already there.
+ if (objReusableTextureUUID == null)
+ {
+ lock (Updaters)
{
- // No need to add to updaters as the texture is always the same. Not that this functionality
- // apppears to be implemented anyway.
- if (RegisteredScenes.ContainsKey(updater.SimUUID))
+ if (!Updaters.ContainsKey(updater.UpdaterID))
{
- SceneObjectPart part = RegisteredScenes[updater.SimUUID].GetSceneObjectPart(updater.PrimID);
-
- if (part != null)
- updater.UpdatePart(part, (UUID)reusableTextureUUID);
+ Updaters.Add(updater.UpdaterID, updater);
}
}
- return updater.UpdaterID;
+ RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
}
-
- return UUID.Zero;
+ else
+ {
+ // No need to add to updaters as the texture is always the same. Not that this functionality
+ // apppears to be implemented anyway.
+ updater.UpdatePart(part, (UUID)objReusableTextureUUID);
+ }
+
+ return updater.UpdaterID;
}
private string GenerateReusableTextureKey(string data, string extraParams)
--
cgit v1.1
From 3ed0d79b00c313eacb2a7df7d5519e840d2fc5c4 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Thu, 30 Aug 2012 22:57:40 +0100
Subject: Make ReuseDynamicTextures an experimental config setting in
[Textures]. Default is false, as before.
If true, this setting reuses dynamically generated textures (i.e. created through osSetDynamicTextureData() and similar OSSL functions) where possible rather than always regenerating them.
This results in much quicker updates viewer-side but may bloat the asset cache (though this is fixable).
Also, sometimes issue have been seen where dynamic textures do not transfer to the viewer properly (permanently blurry).
If this happens and that flag is set then they are not regenerated, the viewer has to clear cache or wait for 24 hours before all cached uuids are invalidated.
CUrrently experimental. Default is false, as before.
---
.../CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
(limited to 'OpenSim/Region/CoreModules/Scripting')
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
index f169117..3eedf49 100644
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -283,6 +283,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
public void Initialise(Scene scene, IConfigSource config)
{
+ IConfig texturesConfig = config.Configs["Textures"];
+ if (texturesConfig != null)
+ ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false);
+
if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
{
RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
@@ -292,7 +296,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
public void PostInitialise()
{
-// ReuseTextures = true;
if (ReuseTextures)
{
m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative);
--
cgit v1.1
From a0d0c9f751f45d54772af2e33866b27c9be33511 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Thu, 6 Sep 2012 00:11:47 +0100
Subject: If the GetTexture capability receives a request for a range of data
beyond that of an otherwise valid asset, return HTTP PartialContent rather
than RequestedRangeNotSatisfiable.
This is because recent viewers (3.2.1, 3.3.4) and probably earlier ones using the http GetTexture capability will sometimes make such invalid range requests.
This appears to happen if the viewer's estimate of texture sizes at discard levels > 0 (chiefly 2) exceeds the total texture size.
I believe this does not normally happen but can occur for dynamic textures with are large but mainly blank.
If this happens, returning a RequestedRangeNotSatisfiable will cause the viewer to not render the texture at the final resolution.
However, returning a PartialContent (or OK) even with 0 data will allow the viewer to render the final texture.
---
.../Scripting/DynamicTexture/DynamicTextureModule.cs | 16 +++++++++++++---
.../Scripting/VectorRender/VectorRenderModule.cs | 20 ++++++++++++++++++++
2 files changed, 33 insertions(+), 3 deletions(-)
(limited to 'OpenSim/Region/CoreModules/Scripting')
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
index 3eedf49..e09f1a9 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
{
public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
{
- //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private const int ALL_SIDES = -1;
@@ -249,10 +249,18 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
}
}
+// m_log.DebugFormat(
+// "[DYNAMIC TEXTURE MODULE]: Requesting generation of new dynamic texture for {0} in {1}",
+// part.Name, part.ParentGroup.Scene.Name);
+
RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
}
else
{
+// m_log.DebugFormat(
+// "[DYNAMIC TEXTURE MODULE]: Reusing cached texture {0} for {1} in {2}",
+// objReusableTextureUUID, part.Name, part.ParentGroup.Scene.Name);
+
// No need to add to updaters as the texture is always the same. Not that this functionality
// apppears to be implemented anyway.
updater.UpdatePart(part, (UUID)objReusableTextureUUID);
@@ -448,8 +456,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface();
if (cacheLayerDecode != null)
{
- cacheLayerDecode.Decode(asset.FullID, asset.Data);
- cacheLayerDecode = null;
+ if (!cacheLayerDecode.Decode(asset.FullID, asset.Data))
+ m_log.WarnFormat(
+ "[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed",
+ asset.ID, part.Name, part.ParentGroup.Scene.Name);
}
UUID oldID = UpdatePart(part, asset.FullID);
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index 4268f2e..0e7051e 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -46,6 +46,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
{
public class VectorRenderModule : IRegionModule, IDynamicTextureRender
{
+ // These fields exist for testing purposes, please do not remove.
+// private static bool s_flipper;
+// private static byte[] s_asset1Data;
+// private static byte[] s_asset2Data;
+
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene;
@@ -161,6 +166,13 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
{
m_textureManager.RegisterRender(GetContentType(), this);
}
+
+ // This code exists for testing purposes, please do not remove.
+// s_asset1Data = m_scene.AssetService.Get("00000000-0000-1111-9999-000000000001").Data;
+// s_asset1Data = m_scene.AssetService.Get("9f4acf0d-1841-4e15-bdb8-3a12efc9dd8f").Data;
+
+ // Terrain dirt - smallest bin/assets file (6004 bytes)
+// s_asset2Data = m_scene.AssetService.Get("b8d3965a-ad78-bf43-699b-bff8eca6c975").Data;
}
public void Close()
@@ -364,6 +376,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
}
byte[] imageJ2000 = new byte[0];
+
+ // This code exists for testing purposes, please do not remove.
+// if (s_flipper)
+// imageJ2000 = s_asset1Data;
+// else
+// imageJ2000 = s_asset2Data;
+//
+// s_flipper = !s_flipper;
try
{
--
cgit v1.1
From 8f02fd926e14dfad7f5eb77a67a6701f449511e0 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Thu, 6 Sep 2012 22:12:05 +0100
Subject: 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.
---
.../DynamicTexture/DynamicTextureModule.cs | 59 ++++++++++++++++++----
.../Scripting/LoadImageURL/LoadImageURLModule.cs | 41 +++++++++------
.../VectorRender/Tests/VectorRenderModuleTests.cs | 42 +++++++++++++++
.../Scripting/VectorRender/VectorRenderModule.cs | 24 ++++-----
4 files changed, 125 insertions(+), 41 deletions(-)
(limited to 'OpenSim/Region/CoreModules/Scripting')
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
{
public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
{
-// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private const int ALL_SIDES = -1;
@@ -54,6 +54,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
///
public bool ReuseTextures { get; set; }
+ ///
+ /// If false, then textures which have a low data size are not reused when ReuseTextures = true.
+ ///
+ ///
+ /// LL viewers 3.3.4 and before appear to not fully render textures pulled from the viewer cache if those
+ /// textures have a relatively high pixel surface but a small data size. Typically, this appears to happen
+ /// if the data size is smaller than the viewer's discard level 2 size estimate. So if this is setting is
+ /// false, textures smaller than the calculation in IsSizeReuseable are always regenerated rather than reused
+ /// to work around this problem.
+ public bool ReuseLowDataTextures { get; set; }
+
private Dictionary RegisteredScenes = new Dictionary();
private Dictionary RenderPlugins =
@@ -83,18 +94,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
///
/// Called by code which actually renders the dynamic texture to supply texture data.
///
- ///
- ///
- /// True if the data generated can be reused for subsequent identical requests
- public void ReturnData(UUID id, byte[] data, bool isReuseable)
+ ///
+ ///
+ public void ReturnData(UUID updaterId, IDynamicTexture texture)
{
DynamicTextureUpdater updater = null;
lock (Updaters)
{
- if (Updaters.ContainsKey(id))
+ if (Updaters.ContainsKey(updaterId))
{
- updater = Updaters[id];
+ updater = Updaters[updaterId];
}
}
@@ -103,11 +113,16 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
if (RegisteredScenes.ContainsKey(updater.SimUUID))
{
Scene scene = RegisteredScenes[updater.SimUUID];
- UUID newTextureID = updater.DataReceived(data, scene);
+ UUID newTextureID = updater.DataReceived(texture.Data, scene);
- if (ReuseTextures && isReuseable && !updater.BlendWithOldTexture)
+ if (ReuseTextures
+ && !updater.BlendWithOldTexture
+ && texture.IsReuseable
+ && (ReuseLowDataTextures || IsDataSizeReuseable(texture)))
+ {
m_reuseableDynamicTextures.Store(
- GenerateReusableTextureKey(updater.BodyData, updater.Params), newTextureID);
+ GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID);
+ }
}
}
@@ -123,6 +138,27 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
}
}
+ ///
+ /// Determines whether the texture is reuseable based on its data size.
+ ///
+ ///
+ /// This is a workaround for a viewer bug where very small data size textures relative to their pixel size
+ /// are not redisplayed properly when pulled from cache. The calculation here is based on the typical discard
+ /// level of 2, a 'rate' of 0.125 and 4 components (which makes for a factor of 0.5).
+ ///
+ ///
+ private bool IsDataSizeReuseable(IDynamicTexture texture)
+ {
+// Console.WriteLine("{0} {1}", texture.Size.Width, texture.Size.Height);
+ int discardLevel2DataThreshold = (int)Math.Ceiling((texture.Size.Width >> 2) * (texture.Size.Height >> 2) * 0.5);
+
+// m_log.DebugFormat(
+// "[DYNAMIC TEXTURE MODULE]: Discard level 2 threshold {0}, texture data length {1}",
+// discardLevel2DataThreshold, texture.Data.Length);
+
+ return discardLevel2DataThreshold < texture.Data.Length;
+ }
+
public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
string extraParams, int updateTimer)
{
@@ -293,7 +329,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
{
IConfig texturesConfig = config.Configs["Textures"];
if (texturesConfig != null)
+ {
ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false);
+ ReuseLowDataTextures = texturesConfig.GetBoolean("ReuseDynamicLowDataTextures", false);
+ }
if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
{
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;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.Imaging;
+using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using log4net;
@@ -73,12 +74,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
// return false;
// }
- public byte[] ConvertUrl(string url, string extraParams)
+ public IDynamicTexture ConvertUrl(string url, string extraParams)
{
return null;
}
- public byte[] ConvertData(string bodyData, string extraParams)
+ public IDynamicTexture ConvertData(string bodyData, string extraParams)
{
return null;
}
@@ -171,11 +172,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
private void HttpRequestReturn(IAsyncResult result)
{
-
RequestState state = (RequestState) result.AsyncState;
WebRequest request = (WebRequest) state.Request;
Stream stream = null;
byte[] imageJ2000 = new byte[0];
+ Size newSize = new Size(0, 0);
try
{
@@ -188,37 +189,43 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
try
{
Bitmap image = new Bitmap(stream);
- Size newsize;
// TODO: make this a bit less hard coded
if ((image.Height < 64) && (image.Width < 64))
{
- newsize = new Size(32, 32);
+ newSize.Width = 32;
+ newSize.Height = 32;
}
else if ((image.Height < 128) && (image.Width < 128))
{
- newsize = new Size(64, 64);
+ newSize.Width = 64;
+ newSize.Height = 64;
}
else if ((image.Height < 256) && (image.Width < 256))
{
- newsize = new Size(128, 128);
+ newSize.Width = 128;
+ newSize.Height = 128;
}
else if ((image.Height < 512 && image.Width < 512))
{
- newsize = new Size(256, 256);
+ newSize.Width = 256;
+ newSize.Height = 256;
}
else if ((image.Height < 1024 && image.Width < 1024))
{
- newsize = new Size(512, 512);
+ newSize.Width = 512;
+ newSize.Height = 512;
}
else
{
- newsize = new Size(1024, 1024);
+ newSize.Width = 1024;
+ newSize.Height = 1024;
}
- Bitmap resize = new Bitmap(image, newsize);
-
- imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
+ using (Bitmap resize = new Bitmap(image, newSize))
+ {
+ imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
+ }
}
catch (Exception)
{
@@ -233,7 +240,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
}
catch (WebException)
{
-
}
finally
{
@@ -243,10 +249,13 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
}
}
- m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}",
+ m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}",
imageJ2000.Length, state.RequestID);
- m_textureManager.ReturnData(state.RequestID, imageJ2000, false);
+ m_textureManager.ReturnData(
+ state.RequestID,
+ new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
+ request.RequestUri, null, imageJ2000, newSize, false));
}
#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
m_dtm = new DynamicTextureModule();
m_dtm.ReuseTextures = reuseTextures;
+// m_dtm.ReuseLowDataTextures = reuseTextures;
m_vrm = new VectorRenderModule();
@@ -201,6 +202,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
public void TestRepeatSameDrawReusingTexture()
{
TestHelpers.InMethod();
+// TestHelpers.EnableLogging();
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
@@ -228,6 +230,46 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
+ ///
+ /// Test a low data dynamically generated texture such that it is treated as a low data texture that causes
+ /// problems for current viewers.
+ ///
+ ///
+ /// As we do not set DynamicTextureModule.ReuseLowDataTextures = true in this test, it should not reuse the
+ /// texture
+ ///
+ [Test]
+ public void TestRepeatSameDrawLowDataTexture()
+ {
+ TestHelpers.InMethod();
+// TestHelpers.EnableLogging();
+
+ string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
+
+ SetupScene(true);
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "1024",
+ 0);
+
+ UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "1024",
+ 0);
+
+ Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+ }
+
[Test]
public void TestRepeatSameDrawDifferentExtraParamsReusingTexture()
{
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;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.Imaging;
+using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using log4net;
@@ -85,20 +86,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
// return lines.Any((str, r) => str.StartsWith("Image"));
// }
- public byte[] ConvertUrl(string url, string extraParams)
+ public IDynamicTexture ConvertUrl(string url, string extraParams)
{
return null;
}
- public byte[] ConvertData(string bodyData, string extraParams)
+ public IDynamicTexture ConvertData(string bodyData, string extraParams)
{
- bool reuseable;
- return Draw(bodyData, extraParams, out reuseable);
- }
-
- private byte[] ConvertData(string bodyData, string extraParams, out bool reuseable)
- {
- return Draw(bodyData, extraParams, out reuseable);
+ return Draw(bodyData, extraParams);
}
public bool AsyncConvertUrl(UUID id, string url, string extraParams)
@@ -109,10 +104,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
{
// XXX: This isn't actually being done asynchronously!
- bool reuseable;
- byte[] data = ConvertData(bodyData, extraParams, out reuseable);
-
- m_textureManager.ReturnData(id, data, reuseable);
+ m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams));
return true;
}
@@ -191,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
#endregion
- private byte[] Draw(string data, string extraParams, out bool reuseable)
+ private IDynamicTexture Draw(string data, string extraParams)
{
// 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
// 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
Bitmap bitmap = null;
Graphics graph = null;
+ bool reuseable = false;
try
{
@@ -396,7 +389,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
e.Message, e.StackTrace);
}
- return imageJ2000;
+ return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
+ data, extraParams, imageJ2000, new Size(width, height), reuseable);
}
finally
{
--
cgit v1.1
From d2b00749ef71729555d393da7fef1dcdb84f5cbc Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Thu, 6 Sep 2012 23:14:48 +0100
Subject: Add missing DynamicTexture.cs file from last commit
---
.../Scripting/DynamicTexture/DynamicTexture.cs | 61 ++++++++++++++++++++++
1 file changed, 61 insertions(+)
create mode 100644 OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
(limited to 'OpenSim/Region/CoreModules/Scripting')
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
new file mode 100644
index 0000000..fce9490
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Drawing;
+using OpenSim.Region.Framework.Interfaces;
+
+namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
+{
+ public class DynamicTexture : IDynamicTexture
+ {
+ public string InputCommands { get; private set; }
+ public Uri InputUri { get; private set; }
+ public string InputParams { get; private set; }
+ public byte[] Data { get; private set; }
+ public Size Size { get; private set; }
+ public bool IsReuseable { get; private set; }
+
+ public DynamicTexture(string inputCommands, string inputParams, byte[] data, Size size, bool isReuseable)
+ {
+ InputCommands = inputCommands;
+ InputParams = inputParams;
+ Data = data;
+ Size = size;
+ IsReuseable = isReuseable;
+ }
+
+ public DynamicTexture(Uri inputUri, string inputParams, byte[] data, Size size, bool isReuseable)
+ {
+ InputUri = inputUri;
+ InputParams = inputParams;
+ Data = data;
+ Size = size;
+ IsReuseable = isReuseable;
+ }
+ }
+}
\ No newline at end of file
--
cgit v1.1
From 91312daeb2974c75ede3e53c9d7a1d9ca0300201 Mon Sep 17 00:00:00 2001
From: Mic Bowman
Date: Mon, 17 Sep 2012 09:04:54 -0700
Subject: Moving ScriptModuleComms into the CoreModules tree.
---
.../ScriptModuleComms/ScriptModuleCommsModule.cs | 367 +++++++++++++++++++++
1 file changed, 367 insertions(+)
create mode 100644 OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
(limited to 'OpenSim/Region/CoreModules/Scripting')
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
new file mode 100644
index 0000000..98396ff
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Reflection;
+using System.Collections.Generic;
+using Nini.Config;
+using log4net;
+using OpenSim.Framework;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.Framework.Scenes;
+using Mono.Addins;
+using OpenMetaverse;
+using System.Linq;
+using System.Linq.Expressions;
+
+namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
+{
+ [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")]
+ class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms
+ {
+ private static readonly ILog m_log =
+ LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ private Dictionary m_constants = new Dictionary();
+
+#region ScriptInvocation
+ protected class ScriptInvocationData
+ {
+ public Delegate ScriptInvocationDelegate { get; private set; }
+ public string FunctionName { get; private set; }
+ public Type[] TypeSignature { get; private set; }
+ public Type ReturnType { get; private set; }
+
+ public ScriptInvocationData(string fname, Delegate fn, Type[] callsig, Type returnsig)
+ {
+ FunctionName = fname;
+ ScriptInvocationDelegate = fn;
+ TypeSignature = callsig;
+ ReturnType = returnsig;
+ }
+ }
+
+ private Dictionary m_scriptInvocation = new Dictionary();
+#endregion
+
+ private IScriptModule m_scriptModule = null;
+ public event ScriptCommand OnScriptCommand;
+
+#region RegionModuleInterface
+ public void Initialise(IConfigSource config)
+ {
+ }
+
+ public void AddRegion(Scene scene)
+ {
+ scene.RegisterModuleInterface(this);
+ }
+
+ public void RemoveRegion(Scene scene)
+ {
+ }
+
+ public void RegionLoaded(Scene scene)
+ {
+ m_scriptModule = scene.RequestModuleInterface();
+
+ if (m_scriptModule != null)
+ m_log.Info("[MODULE COMMANDS]: Script engine found, module active");
+ }
+
+ public string Name
+ {
+ get { return "ScriptModuleCommsModule"; }
+ }
+
+ public Type ReplaceableInterface
+ {
+ get { return null; }
+ }
+
+ public void Close()
+ {
+ }
+#endregion
+
+#region ScriptModuleComms
+
+ public void RaiseEvent(UUID script, string id, string module, string command, string k)
+ {
+ ScriptCommand c = OnScriptCommand;
+
+ if (c == null)
+ return;
+
+ c(script, id, module, command, k);
+ }
+
+ public void DispatchReply(UUID script, int code, string text, string k)
+ {
+ if (m_scriptModule == null)
+ return;
+
+ Object[] args = new Object[] {-1, code, text, k};
+
+ m_scriptModule.PostScriptEvent(script, "link_message", args);
+ }
+
+ private static MethodInfo GetMethodInfoFromType(Type target, string meth, bool searchInstanceMethods)
+ {
+ BindingFlags getMethodFlags =
+ BindingFlags.NonPublic | BindingFlags.Public;
+
+ if (searchInstanceMethods)
+ getMethodFlags |= BindingFlags.Instance;
+ else
+ getMethodFlags |= BindingFlags.Static;
+
+ return target.GetMethod(meth, getMethodFlags);
+ }
+
+ public void RegisterScriptInvocation(object target, string meth)
+ {
+ MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true);
+ if (mi == null)
+ {
+ m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth);
+ return;
+ }
+
+ RegisterScriptInvocation(target, mi);
+ }
+
+ public void RegisterScriptInvocation(object target, string[] meth)
+ {
+ foreach (string m in meth)
+ RegisterScriptInvocation(target, m);
+ }
+
+ public void RegisterScriptInvocation(object target, MethodInfo mi)
+ {
+ m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name);
+
+ Type delegateType;
+ List typeArgs = mi.GetParameters()
+ .Select(p => p.ParameterType)
+ .ToList();
+
+ if (mi.ReturnType == typeof(void))
+ {
+ delegateType = Expression.GetActionType(typeArgs.ToArray());
+ }
+ else
+ {
+ typeArgs.Add(mi.ReturnType);
+ delegateType = Expression.GetFuncType(typeArgs.ToArray());
+ }
+
+ Delegate fcall;
+ if (!(target is Type))
+ fcall = Delegate.CreateDelegate(delegateType, target, mi);
+ else
+ fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name);
+
+ lock (m_scriptInvocation)
+ {
+ ParameterInfo[] parameters = fcall.Method.GetParameters();
+ if (parameters.Length < 2) // Must have two UUID params
+ return;
+
+ // Hide the first two parameters
+ Type[] parmTypes = new Type[parameters.Length - 2];
+ for (int i = 2; i < parameters.Length; i++)
+ parmTypes[i - 2] = parameters[i].ParameterType;
+ m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType);
+ }
+ }
+
+ public void RegisterScriptInvocation(Type target, string[] methods)
+ {
+ foreach (string method in methods)
+ {
+ MethodInfo mi = GetMethodInfoFromType(target, method, false);
+ if (mi == null)
+ m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", method);
+ else
+ RegisterScriptInvocation(target, mi);
+ }
+ }
+
+ public void RegisterScriptInvocations(IRegionModuleBase target)
+ {
+ foreach(MethodInfo method in target.GetType().GetMethods(
+ BindingFlags.Public | BindingFlags.Instance |
+ BindingFlags.Static))
+ {
+ if(method.GetCustomAttributes(
+ typeof(ScriptInvocationAttribute), true).Any())
+ {
+ if(method.IsStatic)
+ RegisterScriptInvocation(target.GetType(), method);
+ else
+ RegisterScriptInvocation(target, method);
+ }
+ }
+ }
+
+ public Delegate[] GetScriptInvocationList()
+ {
+ List ret = new List();
+
+ lock (m_scriptInvocation)
+ {
+ foreach (ScriptInvocationData d in m_scriptInvocation.Values)
+ ret.Add(d.ScriptInvocationDelegate);
+ }
+ return ret.ToArray();
+ }
+
+ public string LookupModInvocation(string fname)
+ {
+ lock (m_scriptInvocation)
+ {
+ ScriptInvocationData sid;
+ if (m_scriptInvocation.TryGetValue(fname,out sid))
+ {
+ if (sid.ReturnType == typeof(string))
+ return "modInvokeS";
+ else if (sid.ReturnType == typeof(int))
+ return "modInvokeI";
+ else if (sid.ReturnType == typeof(float))
+ return "modInvokeF";
+ else if (sid.ReturnType == typeof(UUID))
+ return "modInvokeK";
+ else if (sid.ReturnType == typeof(OpenMetaverse.Vector3))
+ return "modInvokeV";
+ else if (sid.ReturnType == typeof(OpenMetaverse.Quaternion))
+ return "modInvokeR";
+ else if (sid.ReturnType == typeof(object[]))
+ return "modInvokeL";
+
+ m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name);
+ }
+ }
+
+ return null;
+ }
+
+ public Delegate LookupScriptInvocation(string fname)
+ {
+ lock (m_scriptInvocation)
+ {
+ ScriptInvocationData sid;
+ if (m_scriptInvocation.TryGetValue(fname,out sid))
+ return sid.ScriptInvocationDelegate;
+ }
+
+ return null;
+ }
+
+ public Type[] LookupTypeSignature(string fname)
+ {
+ lock (m_scriptInvocation)
+ {
+ ScriptInvocationData sid;
+ if (m_scriptInvocation.TryGetValue(fname,out sid))
+ return sid.TypeSignature;
+ }
+
+ return null;
+ }
+
+ public Type LookupReturnType(string fname)
+ {
+ lock (m_scriptInvocation)
+ {
+ ScriptInvocationData sid;
+ if (m_scriptInvocation.TryGetValue(fname,out sid))
+ return sid.ReturnType;
+ }
+
+ return null;
+ }
+
+ public object InvokeOperation(UUID hostid, UUID scriptid, string fname, params object[] parms)
+ {
+ List