From 8617e1a786c3c4efc7ce1978aab1f5d66102d2bb Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Sun, 31 Mar 2013 18:42:20 -0700 Subject: [PATCH 01/21] Implement GraphicsDevice's DepthStencilState, RasterizerState, Textures and SamplerStates properties on PlayStation Mobile. --- .../Graphics/SamplerStateCollection.cs | 29 +++++++++++++++ .../Graphics/States/DepthStencilState.cs | 37 ++++++++++++++++++- .../Graphics/States/RasterizerState.cs | 14 ++++++- .../Graphics/TextureCollection.cs | 7 ++++ 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/MonoGame.Framework/Graphics/SamplerStateCollection.cs b/MonoGame.Framework/Graphics/SamplerStateCollection.cs index 3d61a8fce10..a99668e4e89 100644 --- a/MonoGame.Framework/Graphics/SamplerStateCollection.cs +++ b/MonoGame.Framework/Graphics/SamplerStateCollection.cs @@ -169,6 +169,35 @@ internal void SetSamplers(GraphicsDevice device) texture.glLastSamplerState = sampler; } } +#elif PSM + for (var i = 0; i < _samplers.Length; i++) + { + var sampler = _samplers[i]; + var texture = device.Textures[i] as Texture2D; + if (texture == null) + continue; + + var psmTexture = texture._texture2D; + + // FIXME: Handle mip attributes + + // FIXME: Separable filters + psmTexture.SetFilter( + sampler.Filter == TextureFilter.Point + ? Sce.PlayStation.Core.Graphics.TextureFilterMode.Nearest + : Sce.PlayStation.Core.Graphics.TextureFilterMode.Linear + ); + // FIXME: The third address mode + psmTexture.SetWrap( + sampler.AddressU == TextureAddressMode.Clamp + ? Sce.PlayStation.Core.Graphics.TextureWrapMode.ClampToEdge + : Sce.PlayStation.Core.Graphics.TextureWrapMode.Repeat, + sampler.AddressV == TextureAddressMode.Clamp + ? Sce.PlayStation.Core.Graphics.TextureWrapMode.ClampToEdge + : Sce.PlayStation.Core.Graphics.TextureWrapMode.Repeat + ); + + } #endif } } diff --git a/MonoGame.Framework/Graphics/States/DepthStencilState.cs b/MonoGame.Framework/Graphics/States/DepthStencilState.cs index e5048d3a6ce..5e29662583e 100644 --- a/MonoGame.Framework/Graphics/States/DepthStencilState.cs +++ b/MonoGame.Framework/Graphics/States/DepthStencilState.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Collections.Generic; #if OPENGL #if MONOMAC @@ -379,9 +380,43 @@ static private SharpDX.Direct3D11.StencilOperation GetStencilOp(StencilOperation #endif // DIRECTX #if PSM + static readonly Dictionary MapDepthCompareFunction = new Dictionary { + { CompareFunction.Always, DepthFuncMode.Always }, + { CompareFunction.Equal, DepthFuncMode.Equal }, + { CompareFunction.GreaterEqual, DepthFuncMode.GEqual }, + { CompareFunction.Greater, DepthFuncMode.Greater }, + { CompareFunction.LessEqual, DepthFuncMode.LEqual }, + { CompareFunction.Less, DepthFuncMode.Less }, + { CompareFunction.NotEqual, DepthFuncMode.NotEequal }, + { CompareFunction.Never, DepthFuncMode.Never }, + }; + + static readonly Dictionary MapStencilCompareFunction = new Dictionary { + { CompareFunction.Always, StencilFuncMode.Always }, + { CompareFunction.Equal, StencilFuncMode.Equal }, + { CompareFunction.GreaterEqual, StencilFuncMode.GEqual }, + { CompareFunction.Greater, StencilFuncMode.Greater }, + { CompareFunction.LessEqual, StencilFuncMode.LEqual }, + { CompareFunction.Less, StencilFuncMode.Less }, + { CompareFunction.NotEqual, StencilFuncMode.NotEequal }, + { CompareFunction.Never, StencilFuncMode.Never }, + }; + internal void ApplyState(GraphicsDevice device) { - #warning Unimplemented + var g = device._graphics; + + // FIXME: More advanced stencil attributes + + g.SetDepthFunc( + MapDepthCompareFunction[DepthBufferFunction], + DepthBufferWriteEnable + ); + + g.SetStencilFunc( + MapStencilCompareFunction[StencilFunction], + ReferenceStencil, StencilMask, StencilWriteMask + ); } #endif } diff --git a/MonoGame.Framework/Graphics/States/RasterizerState.cs b/MonoGame.Framework/Graphics/States/RasterizerState.cs index d0a06f0055e..8b9f7cab3bd 100644 --- a/MonoGame.Framework/Graphics/States/RasterizerState.cs +++ b/MonoGame.Framework/Graphics/States/RasterizerState.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Collections.Generic; #if OPENGL #if MONOMAC @@ -189,9 +190,20 @@ internal void ApplyState(GraphicsDevice device) #endif // DIRECTX #if PSM + // FIXME: What does CullFaceMode actually specify? Cull that face or don't cull that face? Stupid sony. + static readonly Dictionary MapCullMode = new Dictionary { + {CullMode.None, CullFaceMode.None}, + {CullMode.CullClockwiseFace, CullFaceMode.Front}, // Cull cw + {CullMode.CullCounterClockwiseFace, CullFaceMode.Back}, // Cull ccw + }; + internal void ApplyState(GraphicsDevice device) { - #warning Unimplemented + var g = device._graphics; + + g.SetCullFace(MapCullMode[CullMode], CullFaceDirection.Cw); // Front == cw + + // FIXME: Everything else } #endif } diff --git a/MonoGame.Framework/Graphics/TextureCollection.cs b/MonoGame.Framework/Graphics/TextureCollection.cs index 8ad057c00f3..ffebe5b417b 100644 --- a/MonoGame.Framework/Graphics/TextureCollection.cs +++ b/MonoGame.Framework/Graphics/TextureCollection.cs @@ -116,6 +116,13 @@ internal void SetTextures(GraphicsDevice device) pixelShaderStage.SetShaderResource(i, null); else pixelShaderStage.SetShaderResource(i, _textures[i].GetShaderResourceView()); +#elif PSM + // FIXME: 1d/3d textures + var texture2d = _textures[i] as Texture2D; + if (texture2d == null) + device._graphics.SetTexture(i, null); + else + device._graphics.SetTexture(i, texture2d._texture2D); #endif _dirty &= ~mask; From 3eac67ab97b2a875d61ad94edc4831778e686ee9 Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Sun, 10 Feb 2013 02:41:12 -0800 Subject: [PATCH 02/21] Correct the number of texture stages on PlayStation Mobile. --- MonoGame.Framework/Graphics/GraphicsDevice.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/MonoGame.Framework/Graphics/GraphicsDevice.cs b/MonoGame.Framework/Graphics/GraphicsDevice.cs index cabc1b9dff7..9c649db9794 100644 --- a/MonoGame.Framework/Graphics/GraphicsDevice.cs +++ b/MonoGame.Framework/Graphics/GraphicsDevice.cs @@ -328,8 +328,13 @@ public GraphicsDevice () _viewport = new Viewport (0, 0, DisplayMode.Width, DisplayMode.Height); _viewport.MaxDepth = 1.0f; - + +#if PSM + MaxTextureSlots = 8; +#else MaxTextureSlots = 16; +#endif + #if OPENGL #if GLES GL.GetInteger(All.MaxTextureImageUnits, ref MaxTextureSlots); From 59b40d2136825083c6c5ca34e69e2143969e0cb5 Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Sun, 10 Feb 2013 02:44:35 -0800 Subject: [PATCH 03/21] Implement DepthBufferEnable and StencilEnable on PlayStation Mobile. --- MonoGame.Framework/Graphics/States/DepthStencilState.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/MonoGame.Framework/Graphics/States/DepthStencilState.cs b/MonoGame.Framework/Graphics/States/DepthStencilState.cs index 5e29662583e..e4f1a9f05d3 100644 --- a/MonoGame.Framework/Graphics/States/DepthStencilState.cs +++ b/MonoGame.Framework/Graphics/States/DepthStencilState.cs @@ -409,12 +409,16 @@ internal void ApplyState(GraphicsDevice device) // FIXME: More advanced stencil attributes g.SetDepthFunc( - MapDepthCompareFunction[DepthBufferFunction], + DepthBufferEnable + ? MapDepthCompareFunction[DepthBufferFunction] + : DepthFuncMode.Always, DepthBufferWriteEnable ); g.SetStencilFunc( - MapStencilCompareFunction[StencilFunction], + StencilEnable + ? MapStencilCompareFunction[StencilFunction] + : StencilFuncMode.Always, ReferenceStencil, StencilMask, StencilWriteMask ); } From eb48c7448f5a5a43dbec45fade968b1697e0ff18 Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Sun, 31 Mar 2013 18:44:39 -0700 Subject: [PATCH 04/21] Add missing Enable calls on PlayStation Mobile --- .../Graphics/States/DepthStencilState.cs | 12 ++++++------ .../Graphics/States/RasterizerState.cs | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/MonoGame.Framework/Graphics/States/DepthStencilState.cs b/MonoGame.Framework/Graphics/States/DepthStencilState.cs index e4f1a9f05d3..945129a17dc 100644 --- a/MonoGame.Framework/Graphics/States/DepthStencilState.cs +++ b/MonoGame.Framework/Graphics/States/DepthStencilState.cs @@ -409,18 +409,18 @@ internal void ApplyState(GraphicsDevice device) // FIXME: More advanced stencil attributes g.SetDepthFunc( - DepthBufferEnable - ? MapDepthCompareFunction[DepthBufferFunction] - : DepthFuncMode.Always, + MapDepthCompareFunction[DepthBufferFunction], DepthBufferWriteEnable ); + g.Enable(EnableMode.DepthTest, DepthBufferEnable); + g.SetStencilFunc( - StencilEnable - ? MapStencilCompareFunction[StencilFunction] - : StencilFuncMode.Always, + MapStencilCompareFunction[StencilFunction], ReferenceStencil, StencilMask, StencilWriteMask ); + + g.Enable(EnableMode.StencilTest, StencilEnable); } #endif } diff --git a/MonoGame.Framework/Graphics/States/RasterizerState.cs b/MonoGame.Framework/Graphics/States/RasterizerState.cs index 8b9f7cab3bd..5bc494adde6 100644 --- a/MonoGame.Framework/Graphics/States/RasterizerState.cs +++ b/MonoGame.Framework/Graphics/States/RasterizerState.cs @@ -202,6 +202,7 @@ internal void ApplyState(GraphicsDevice device) var g = device._graphics; g.SetCullFace(MapCullMode[CullMode], CullFaceDirection.Cw); // Front == cw + g.Enable(EnableMode.CullFace, this.CullMode != CullMode.None); // FIXME: Everything else } From 1408647020775c7d9f4bdbba80ac816e5ca56550 Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Sun, 10 Feb 2013 02:49:57 -0800 Subject: [PATCH 05/21] Implement GraphicsDevice.Viewport on PlayStation Mobile --- MonoGame.Framework/Graphics/GraphicsDevice.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MonoGame.Framework/Graphics/GraphicsDevice.cs b/MonoGame.Framework/Graphics/GraphicsDevice.cs index 9c649db9794..1a480f3bd6a 100644 --- a/MonoGame.Framework/Graphics/GraphicsDevice.cs +++ b/MonoGame.Framework/Graphics/GraphicsDevice.cs @@ -1487,6 +1487,10 @@ public Viewport Viewport // In OpenGL we have to re-apply the special "posFixup" // vertex shader uniform if the viewport changes. _vertexShaderDirty = true; +#elif PSM + _graphics.SetViewport( + value.X, value.Y, value.Width, value.Height + ); #endif } } From 03c383e38fe0e0db053d407727d399d1e25b172b Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Sat, 9 Feb 2013 22:21:24 -0800 Subject: [PATCH 06/21] Get Effect and EffectParameter closer to actually working and remove the BasicEffect hacks. --- MonoGame.Framework/Graphics/Effect/Effect.cs | 67 +++++++++++++------ .../Graphics/Effect/EffectParameter.cs | 10 +++ .../Graphics/Effect/EffectPass.cs | 14 ++-- 3 files changed, 60 insertions(+), 31 deletions(-) diff --git a/MonoGame.Framework/Graphics/Effect/Effect.cs b/MonoGame.Framework/Graphics/Effect/Effect.cs index 45ed26b6f9f..8d65f0774f4 100644 --- a/MonoGame.Framework/Graphics/Effect/Effect.cs +++ b/MonoGame.Framework/Graphics/Effect/Effect.cs @@ -159,6 +159,10 @@ private void Clone(Effect cloneSource) break; } } + + // HACK + if (CurrentTechnique == null) + CurrentTechnique = Techniques[0]; // Take a reference to the original shader list. _shaderList = cloneSource._shaderList; @@ -495,24 +499,6 @@ internal void ReadEffect(BinaryReader reader) { Parameters.Add(EffectParameterForUniform(shaderProgram, i)); } - - #warning Hacks for BasicEffect as we don't have these parameters yet - Parameters.Add (new EffectParameter( - EffectParameterClass.Vector, EffectParameterType.Single, "SpecularColor", - 3, 1, "float3", - new EffectAnnotationCollection(), new EffectParameterCollection(), new EffectParameterCollection(), new float[3])); - Parameters.Add (new EffectParameter( - EffectParameterClass.Scalar, EffectParameterType.Single, "SpecularPower", - 1, 1, "float", - new EffectAnnotationCollection(), new EffectParameterCollection(), new EffectParameterCollection(), 0.0f)); - Parameters.Add (new EffectParameter( - EffectParameterClass.Vector, EffectParameterType.Single, "FogVector", - 4, 1, "float4", - new EffectAnnotationCollection(), new EffectParameterCollection(), new EffectParameterCollection(), new float[4])); - Parameters.Add (new EffectParameter( - EffectParameterClass.Vector, EffectParameterType.Single, "DiffuseColor", - 4, 1, "float4", - new EffectAnnotationCollection(), new EffectParameterCollection(), new EffectParameterCollection(), new float[4])); Techniques = new EffectTechniqueCollection(); var effectPassCollection = new EffectPassCollection(); @@ -534,27 +520,66 @@ internal EffectParameter EffectParameterForUniform(ShaderProgram shaderProgram, //EffectParameter.Semantic => COLOR0 / POSITION0 etc + EffectParameter result = null; + //FIXME: bufferOffset in below lines is 0 but should probably be something else switch (type) { case ShaderUniformType.Float4x4: - return new EffectParameter( + result = new EffectParameter( EffectParameterClass.Matrix, EffectParameterType.Single, name, 4, 4, "float4x4", new EffectAnnotationCollection(), new EffectParameterCollection(), new EffectParameterCollection(), new float[4 * 4]); + result.InternalSet = (p, sp) => { + var pssm = PSSHelper.ToPssMatrix4((float[])p.Data); + pssm = pssm.Transpose(); + sp.SetUniformValue(index, ref pssm); + }; + break; + case ShaderUniformType.Float: + result = new EffectParameter( + EffectParameterClass.Scalar, EffectParameterType.Single, name, + 1, 1, "float", + new EffectAnnotationCollection(), new EffectParameterCollection(), new EffectParameterCollection(), new float[1]); + result.InternalSet = (p, sp) => + sp.SetUniformValue(index, (float)p.Data); + break; + case ShaderUniformType.Float2: + result = new EffectParameter( + EffectParameterClass.Vector, EffectParameterType.Single, name, + 2, 1, "float2", + new EffectAnnotationCollection(), new EffectParameterCollection(), new EffectParameterCollection(), new float[2]); + result.InternalSet = (p, sp) => + sp.SetUniformValue(index, (float[])p.Data); + break; + case ShaderUniformType.Float3: + result = new EffectParameter( + EffectParameterClass.Vector, EffectParameterType.Single, name, + 3, 1, "float3", + new EffectAnnotationCollection(), new EffectParameterCollection(), new EffectParameterCollection(), new float[3]); + result.InternalSet = (p, sp) => + sp.SetUniformValue(index, (float[])p.Data); + break; case ShaderUniformType.Float4: - return new EffectParameter( + result = new EffectParameter( EffectParameterClass.Vector, EffectParameterType.Single, name, 4, 1, "float4", new EffectAnnotationCollection(), new EffectParameterCollection(), new EffectParameterCollection(), new float[4]); + result.InternalSet = (p, sp) => + sp.SetUniformValue(index, (float[])p.Data); + break; case ShaderUniformType.Sampler2D: - return new EffectParameter( + result = new EffectParameter( EffectParameterClass.Object, EffectParameterType.Texture2D, name, 1, 1, "texture2d", new EffectAnnotationCollection(), new EffectParameterCollection(), new EffectParameterCollection(), null); + // FIXME: No InternalSet + break; default: throw new Exception("Uniform Type " + type + " Not yet implemented (" + name + ")"); } + + return result; } #endif diff --git a/MonoGame.Framework/Graphics/Effect/EffectParameter.cs b/MonoGame.Framework/Graphics/Effect/EffectParameter.cs index 922496abeeb..d55687e0124 100644 --- a/MonoGame.Framework/Graphics/Effect/EffectParameter.cs +++ b/MonoGame.Framework/Graphics/Effect/EffectParameter.cs @@ -4,6 +4,10 @@ using System.Text; using System.Diagnostics; +#if PSM +using Sce.PlayStation.Core.Graphics; +#endif + namespace Microsoft.Xna.Framework.Graphics { [DebuggerDisplay("{ParameterClass} {ParameterType} {Name} : {Semantic}")] @@ -600,5 +604,11 @@ public void SetValue (Vector4[] value) Elements[i].SetValue (value[i]); StateKey = unchecked(NextStateKey++); } + +#if PSM + internal delegate void InternalSetDelegate (EffectParameter parameter, ShaderProgram shaderProgram); + + internal InternalSetDelegate InternalSet = null; +#endif } } diff --git a/MonoGame.Framework/Graphics/Effect/EffectPass.cs b/MonoGame.Framework/Graphics/Effect/EffectPass.cs index 0359cdc0053..7b7be900e87 100644 --- a/MonoGame.Framework/Graphics/Effect/EffectPass.cs +++ b/MonoGame.Framework/Graphics/Effect/EffectPass.cs @@ -149,16 +149,10 @@ public void Apply() #if PSM _effect.GraphicsDevice._graphics.SetShaderProgram(_shaderProgram); - #warning We are only setting one hardcoded parameter here. Need to do this properly by iterating _effect.Parameters (Happens in Shader) - - float[] data; - if (_effect.Parameters["WorldViewProj"] != null) - data = (float[])_effect.Parameters["WorldViewProj"].Data; - else - data = (float[])_effect.Parameters["MatrixTransform"].Data; - Sce.PlayStation.Core.Matrix4 matrix4 = PSSHelper.ToPssMatrix4(data); - matrix4 = matrix4.Transpose (); //When .Data is set the matrix is transposed, we need to do it again to undo it - _shaderProgram.SetUniformValue(0, ref matrix4); + foreach (var parameter in _effect.Parameters) { + if (parameter.InternalSet != null) + parameter.InternalSet(parameter, _shaderProgram); + } #endif } From b9063f3303cef349cfba9a1b6ecc6b8d29e580a7 Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Sun, 10 Feb 2013 01:18:40 -0800 Subject: [PATCH 07/21] Fix EffectParameter.InternalSet not being copied during cloning --- MonoGame.Framework/Graphics/Effect/EffectParameter.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MonoGame.Framework/Graphics/Effect/EffectParameter.cs b/MonoGame.Framework/Graphics/Effect/EffectParameter.cs index d55687e0124..3157030c3fe 100644 --- a/MonoGame.Framework/Graphics/Effect/EffectParameter.cs +++ b/MonoGame.Framework/Graphics/Effect/EffectParameter.cs @@ -67,6 +67,8 @@ internal EffectParameter(EffectParameter cloneSource) if (array != null) Data = array.Clone(); StateKey = unchecked(NextStateKey++); + + InternalSet = cloneSource.InternalSet; } public string Name { get; private set; } From f9fd6d9e5db27e6a6cf4aed1beab842f6de5f960 Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Sun, 10 Feb 2013 02:53:08 -0800 Subject: [PATCH 08/21] The PSM effect reader should not be setting arbitrary states on effect passes; this is definitely not something that I can find any evidence of Windows XNA doing and it breaks things. --- MonoGame.Framework/Graphics/Effect/Effect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MonoGame.Framework/Graphics/Effect/Effect.cs b/MonoGame.Framework/Graphics/Effect/Effect.cs index 8d65f0774f4..f9f64eb9c17 100644 --- a/MonoGame.Framework/Graphics/Effect/Effect.cs +++ b/MonoGame.Framework/Graphics/Effect/Effect.cs @@ -491,7 +491,7 @@ private static EffectParameterCollection ReadParameters(BinaryReader reader) #else //PSM internal void ReadEffect(BinaryReader reader) { - var effectPass = new EffectPass(this, "Pass", null, null, BlendState.AlphaBlend, DepthStencilState.Default, RasterizerState.CullNone, new EffectAnnotationCollection()); + var effectPass = new EffectPass(this, "Pass", null, null, null, null, null, new EffectAnnotationCollection()); effectPass._shaderProgram = new ShaderProgram(reader.ReadBytes((int)reader.BaseStream.Length)); var shaderProgram = effectPass._shaderProgram; Parameters = new EffectParameterCollection(); From c765c357abea0c95a3fdc78ed1bd35db2aead2e6 Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Sat, 23 Mar 2013 19:04:53 -0700 Subject: [PATCH 09/21] Add missing PSM ifdef around InternalSet for EffectParameter --- MonoGame.Framework/Graphics/Effect/EffectParameter.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MonoGame.Framework/Graphics/Effect/EffectParameter.cs b/MonoGame.Framework/Graphics/Effect/EffectParameter.cs index 3157030c3fe..278b47cd27c 100644 --- a/MonoGame.Framework/Graphics/Effect/EffectParameter.cs +++ b/MonoGame.Framework/Graphics/Effect/EffectParameter.cs @@ -68,7 +68,9 @@ internal EffectParameter(EffectParameter cloneSource) Data = array.Clone(); StateKey = unchecked(NextStateKey++); +#if PSM InternalSet = cloneSource.InternalSet; +#endif } public string Name { get; private set; } From 2beac52b96a7aa158e1ea21d5316aebf21b272b8 Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Sun, 31 Mar 2013 19:09:55 -0700 Subject: [PATCH 10/21] Remove the samples and starter kits submodules since we don't want them and they are ENORMOUS. --- .gitmodules | 6 ------ Samples | 1 - StarterKits | 1 - 3 files changed, 8 deletions(-) delete mode 160000 Samples delete mode 160000 StarterKits diff --git a/.gitmodules b/.gitmodules index ef761fcf59c..59169e44ee2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,12 +1,6 @@ [submodule "ThirdParty/Libs"] path = ThirdParty/Libs url = https://github.com/kungfubanana/MonoGame-Dependencies.git -[submodule "Samples"] - path = Samples - url = https://github.com/CartBlanche/MonoGame-Samples.git -[submodule "StarterKits"] - path = StarterKits - url = https://github.com/kungfubanana/MonoGame-StarterKits.git [submodule "ThirdParty/Kickstart"] path = ThirdParty/Kickstart url = https://github.com/OutOfOrder/MonoKickstart.git diff --git a/Samples b/Samples deleted file mode 160000 index 59c3a0ab2af..00000000000 --- a/Samples +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 59c3a0ab2af2944c0ac225d960593078aee9de8f diff --git a/StarterKits b/StarterKits deleted file mode 160000 index 9f77c394547..00000000000 --- a/StarterKits +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9f77c394547ed325c34e98f9ef7f1987b8a9cc18 From 3a73669ef24bc8d3a70f8b28c4650dfecb0d12eb Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Sun, 10 Feb 2013 05:20:14 -0800 Subject: [PATCH 11/21] More hacks to make it possible to use SpriteFont without SpriteBatch. --- MonoGame.Framework/Graphics/SpriteFont.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MonoGame.Framework/Graphics/SpriteFont.cs b/MonoGame.Framework/Graphics/SpriteFont.cs index 728ae8b5878..f2c9ee52a9a 100644 --- a/MonoGame.Framework/Graphics/SpriteFont.cs +++ b/MonoGame.Framework/Graphics/SpriteFont.cs @@ -74,7 +74,6 @@ additional consumer rights under your local laws which this license cannot namespace Microsoft.Xna.Framework.Graphics { - public sealed class SpriteFont { static class Errors @@ -116,6 +115,10 @@ internal SpriteFont ( _glyphs.Add (glyph.Character, glyph); } } + + public bool GetGlyph (char ch, out Glyph result) { + return _glyphs.TryGetValue(ch, out result); + } private ReadOnlyCollection _characters; @@ -375,7 +378,7 @@ public char this [int index] } } - struct Glyph + public struct Glyph { public char Character; public Rectangle BoundsInTexture; From d8e37ff556e71902d14ddaac9da3742670349137 Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Sun, 10 Feb 2013 05:23:04 -0800 Subject: [PATCH 12/21] Expose SpriteFont.Texture --- MonoGame.Framework/Graphics/SpriteFont.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MonoGame.Framework/Graphics/SpriteFont.cs b/MonoGame.Framework/Graphics/SpriteFont.cs index f2c9ee52a9a..1164eebffcf 100644 --- a/MonoGame.Framework/Graphics/SpriteFont.cs +++ b/MonoGame.Framework/Graphics/SpriteFont.cs @@ -119,6 +119,8 @@ internal SpriteFont ( public bool GetGlyph (char ch, out Glyph result) { return _glyphs.TryGetValue(ch, out result); } + + public Texture2D Texture { get { return _texture; } } private ReadOnlyCollection _characters; From 7a44391e6a46730fb68a0e97f8cb18543d2e5e3e Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Mon, 11 Feb 2013 01:58:32 -0800 Subject: [PATCH 13/21] Make PSSHelper public --- MonoGame.Framework/PSSuite/PSSHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MonoGame.Framework/PSSuite/PSSHelper.cs b/MonoGame.Framework/PSSuite/PSSHelper.cs index b9caa9cf8f6..7f7fd9a78f6 100644 --- a/MonoGame.Framework/PSSuite/PSSHelper.cs +++ b/MonoGame.Framework/PSSuite/PSSHelper.cs @@ -8,7 +8,7 @@ namespace Microsoft.Xna.Framework.Graphics { - internal static class PSSHelper + public static class PSSHelper { public static PssPixelFormat ToFormat(SurfaceFormat format) { From 5f712769dc29789e47557a5633ca50318550325c Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Tue, 12 Feb 2013 03:12:53 -0800 Subject: [PATCH 14/21] Implement left-side overhang compensation for the first character of a string in SpriteFont.Measure and DrawInto. --- MonoGame.Framework/Graphics/SpriteFont.cs | 34 ++++++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/MonoGame.Framework/Graphics/SpriteFont.cs b/MonoGame.Framework/Graphics/SpriteFont.cs index 1164eebffcf..42cf1202794 100644 --- a/MonoGame.Framework/Graphics/SpriteFont.cs +++ b/MonoGame.Framework/Graphics/SpriteFont.cs @@ -195,6 +195,7 @@ private void MeasureString(ref CharacterSource text, out Vector2 size) var currentGlyph = Glyph.Empty; var offset = Vector2.Zero; var hasCurrentGlyph = false; + var firstGlyphOfLine = true; for (var i = 0; i < text.Length; ++i) { @@ -213,11 +214,23 @@ private void MeasureString(ref CharacterSource text, out Vector2 size) offset.X = 0; offset.Y = LineSpacing * fullLineCount; hasCurrentGlyph = false; + firstGlyphOfLine = true; continue; } - if (hasCurrentGlyph) - offset.X += Spacing + currentGlyph.WidthIncludingBearings; + if (hasCurrentGlyph) { + offset.X += Spacing + currentGlyph.LeftSideBearing; + + // The first character on a line might have a negative left side bearing. + // In this scenario, SpriteBatch/SpriteFont normally offset the text to the right, + // so that text does not hang off the left side of its rectangle. + if (firstGlyphOfLine) { + offset.X = Math.Max(offset.X, 0); + firstGlyphOfLine = false; + } + + offset.X += currentGlyph.Width + currentGlyph.RightSideBearing; + } hasCurrentGlyph = _glyphs.TryGetValue(c, out currentGlyph); if (!hasCurrentGlyph) @@ -291,6 +304,7 @@ internal void DrawInto( SpriteBatch spriteBatch, ref CharacterSource text, Vecto var currentGlyph = Glyph.Empty; var offset = Vector2.Zero; var hasCurrentGlyph = false; + var firstGlyphOfLine = true; for (var i = 0; i < text.Length; ++i) { @@ -306,11 +320,23 @@ internal void DrawInto( SpriteBatch spriteBatch, ref CharacterSource text, Vecto offset.X = 0; offset.Y += LineSpacing; hasCurrentGlyph = false; + firstGlyphOfLine = true; continue; } - if (hasCurrentGlyph) - offset.X += Spacing + currentGlyph.Width + currentGlyph.RightSideBearing; + if (hasCurrentGlyph) { + offset.X += Spacing; + + // The first character on a line might have a negative left side bearing. + // In this scenario, SpriteBatch/SpriteFont normally offset the text to the right, + // so that text does not hang off the left side of its rectangle. + if (firstGlyphOfLine) { + offset.X = Math.Max(offset.X, 0); + firstGlyphOfLine = false; + } + + offset.X += currentGlyph.Width + currentGlyph.RightSideBearing; + } hasCurrentGlyph = _glyphs.TryGetValue(c, out currentGlyph); if (!hasCurrentGlyph) From 6abfc20d8dd7caf6d6673ea22ce23a9cec108b88 Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Tue, 12 Feb 2013 13:03:27 -0800 Subject: [PATCH 15/21] Add a workaround for MonoGame not properly setting states on the PSM GraphicsDevice --- MonoGame.Framework/Graphics/GraphicsDevice.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/MonoGame.Framework/Graphics/GraphicsDevice.cs b/MonoGame.Framework/Graphics/GraphicsDevice.cs index 1a480f3bd6a..eecc2bad6cc 100644 --- a/MonoGame.Framework/Graphics/GraphicsDevice.cs +++ b/MonoGame.Framework/Graphics/GraphicsDevice.cs @@ -91,6 +91,10 @@ namespace Microsoft.Xna.Framework.Graphics { public class GraphicsDevice : IDisposable { +#if PSM + public static GraphicsContext ExistingGraphicsContext = null; +#endif + private Viewport _viewport; private bool _isDisposed; @@ -437,7 +441,7 @@ internal void Initialize() #endif #elif PSM - _graphics = new GraphicsContext(); + _graphics = ExistingGraphicsContext ?? new GraphicsContext(); #elif OPENGL _viewport = new Viewport(0, 0, PresentationParameters.BackBufferWidth, PresentationParameters.BackBufferHeight); #endif @@ -1126,6 +1130,15 @@ public void Clear(ClearOptions options, Vector4 color, float depth, int stencil) } #elif PSM + // Workaround for MonoGame not setting state correctly + _blendStateDirty = true; + _depthStencilStateDirty = true; + _indexBufferDirty = true; + _pixelShaderDirty = true; + _vertexShaderDirty = true; + _vertexBufferDirty = true; + _rasterizerStateDirty = true; + _scissorRectangleDirty = true; _graphics.SetClearColor(color.ToPssVector4()); _graphics.Clear(); From ad4257a99355fa374feef89311441b4e6a00b4bd Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Sun, 31 Mar 2013 19:34:20 -0700 Subject: [PATCH 16/21] Make various internals accessible so that Sully can run. --- MonoGame.Framework/Graphics/Effect/EffectPass.cs | 2 +- MonoGame.Framework/Graphics/GraphicsDevice.cs | 4 ++-- MonoGame.Framework/Graphics/RenderTarget2D.cs | 2 +- MonoGame.Framework/Graphics/SamplerStateCollection.cs | 2 +- MonoGame.Framework/Graphics/TextureCollection.cs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MonoGame.Framework/Graphics/Effect/EffectPass.cs b/MonoGame.Framework/Graphics/Effect/EffectPass.cs index 7b7be900e87..540da8acf31 100644 --- a/MonoGame.Framework/Graphics/Effect/EffectPass.cs +++ b/MonoGame.Framework/Graphics/Effect/EffectPass.cs @@ -27,7 +27,7 @@ public class EffectPass public EffectAnnotationCollection Annotations { get; private set; } #if PSM - internal ShaderProgram _shaderProgram; + public ShaderProgram _shaderProgram; #endif internal EffectPass( Effect effect, diff --git a/MonoGame.Framework/Graphics/GraphicsDevice.cs b/MonoGame.Framework/Graphics/GraphicsDevice.cs index eecc2bad6cc..e8756bd450b 100644 --- a/MonoGame.Framework/Graphics/GraphicsDevice.cs +++ b/MonoGame.Framework/Graphics/GraphicsDevice.cs @@ -210,7 +210,7 @@ public class GraphicsDevice : IDisposable #elif PSM - internal GraphicsContext _graphics; + public GraphicsContext _graphics; internal List _availableVertexBuffers = new List(); internal List _usedVertexBuffers = new List(); #endif @@ -1969,7 +1969,7 @@ private void ActivateShaderProgram() public bool ResourcesLost { get; set; } - internal void ApplyState(bool applyShaders) + public void ApplyState(bool applyShaders) { #if DIRECTX // NOTE: This code assumes _d3dContext has been locked by the caller. diff --git a/MonoGame.Framework/Graphics/RenderTarget2D.cs b/MonoGame.Framework/Graphics/RenderTarget2D.cs index a52eea5383f..20407da72cf 100644 --- a/MonoGame.Framework/Graphics/RenderTarget2D.cs +++ b/MonoGame.Framework/Graphics/RenderTarget2D.cs @@ -101,7 +101,7 @@ public RenderTarget2D (GraphicsDevice graphicsDevice, int width, int height, boo // Create a view interface on the rendertarget to use on bind. _renderTargetView = new RenderTargetView(graphicsDevice._d3dDevice, _texture); #elif PSM - _frameBuffer = new FrameBuffer(); + _frameBuffer = new FrameBuffer(); _frameBuffer.SetColorTarget(_texture2D,0); #endif diff --git a/MonoGame.Framework/Graphics/SamplerStateCollection.cs b/MonoGame.Framework/Graphics/SamplerStateCollection.cs index a99668e4e89..5d0df413f0b 100644 --- a/MonoGame.Framework/Graphics/SamplerStateCollection.cs +++ b/MonoGame.Framework/Graphics/SamplerStateCollection.cs @@ -113,7 +113,7 @@ internal void Dirty() #endif } - internal void SetSamplers(GraphicsDevice device) + public void SetSamplers(GraphicsDevice device) { #if DIRECTX // Skip out if nothing has changed. diff --git a/MonoGame.Framework/Graphics/TextureCollection.cs b/MonoGame.Framework/Graphics/TextureCollection.cs index ffebe5b417b..ca49134342e 100644 --- a/MonoGame.Framework/Graphics/TextureCollection.cs +++ b/MonoGame.Framework/Graphics/TextureCollection.cs @@ -70,7 +70,7 @@ internal void Dirty() _dirty = int.MaxValue; } - internal void SetTextures(GraphicsDevice device) + public void SetTextures(GraphicsDevice device) { #if !DIRECTX Threading.EnsureUIThread(); From e7db7050d1ab13a645a6f1aa14ced7d19a8cefe8 Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Sun, 31 Mar 2013 19:34:51 -0700 Subject: [PATCH 17/21] Fix GraphicsDevice.SetRenderTarget and GraphicsDevice.SetRenderTargets on PlayStation Mobile. --- MonoGame.Framework/Graphics/GraphicsDevice.cs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/MonoGame.Framework/Graphics/GraphicsDevice.cs b/MonoGame.Framework/Graphics/GraphicsDevice.cs index e8756bd450b..7ed9ec17bce 100644 --- a/MonoGame.Framework/Graphics/GraphicsDevice.cs +++ b/MonoGame.Framework/Graphics/GraphicsDevice.cs @@ -1530,17 +1530,9 @@ public Rectangle ScissorRectangle public void SetRenderTarget(RenderTarget2D renderTarget) { if (renderTarget == null) -#if PSM - _graphics.SetFrameBuffer(null); -#else SetRenderTargets(null); -#endif else -#if PSM - _graphics.SetFrameBuffer(renderTarget._frameBuffer); -#else SetRenderTargets(new RenderTargetBinding(renderTarget)); -#endif } public void SetRenderTarget(RenderTargetCube renderTarget, CubeMapFace cubeMapFace) @@ -1629,6 +1621,8 @@ internal void ApplyRenderTargets(RenderTargetBinding[] renderTargets) #elif OPENGL GL.BindFramebuffer(GLFramebuffer, this.glFramebuffer); GraphicsExtensions.CheckGLError(); +#elif PSM + _graphics.SetFrameBuffer(_graphics.Screen); #endif clearTarget = true; @@ -1725,16 +1719,16 @@ internal void ApplyRenderTargets(RenderTargetBinding[] renderTargets) } throw new InvalidOperationException(message); } - +#elif PSM + var renderTarget = (RenderTarget2D)_currentRenderTargetBindings[0].RenderTarget; + _graphics.SetFrameBuffer(renderTarget._frameBuffer); #endif -#if !PSM // Set the viewport to the size of the first render target. Viewport = new Viewport(0, 0, renderTarget.Width, renderTarget.Height); // We clear the render target if asked. clearTarget = renderTarget.RenderTargetUsage == RenderTargetUsage.DiscardContents; -#endif } // In XNA 4, because of hardware limitations on Xbox, when From c79eab841ecbd6cb38f9da3e792c2d82b94550eb Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Mon, 29 Apr 2013 06:26:56 -0700 Subject: [PATCH 18/21] Add an interactive test case for issue #1355. --- .../Windows/Issue1355/Issue1355.sln | 35 ++++ .../Windows/Issue1355/Issue1355/Game.cs | 68 ++++++++ .../Issue1355/Issue1355/Issue1355.csproj | 160 ++++++++++++++++++ .../Issue1355/Issue1355_MonoGame.csproj | 64 +++++++ .../DutchAndHarley.spritefont | 60 +++++++ .../Issue1355Content.contentproj | 59 +++++++ 6 files changed, 446 insertions(+) create mode 100644 Test/Interactive/Windows/Issue1355/Issue1355.sln create mode 100644 Test/Interactive/Windows/Issue1355/Issue1355/Game.cs create mode 100644 Test/Interactive/Windows/Issue1355/Issue1355/Issue1355.csproj create mode 100644 Test/Interactive/Windows/Issue1355/Issue1355/Issue1355_MonoGame.csproj create mode 100644 Test/Interactive/Windows/Issue1355/Issue1355Content/DutchAndHarley.spritefont create mode 100644 Test/Interactive/Windows/Issue1355/Issue1355Content/Issue1355Content.contentproj diff --git a/Test/Interactive/Windows/Issue1355/Issue1355.sln b/Test/Interactive/Windows/Issue1355/Issue1355.sln new file mode 100644 index 00000000000..e2ed4774219 --- /dev/null +++ b/Test/Interactive/Windows/Issue1355/Issue1355.sln @@ -0,0 +1,35 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Issue1355", "Issue1355\Issue1355.csproj", "{0650BBB1-A078-4536-850B-182BC3A78B81}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Issue1355Content", "Issue1355Content\Issue1355Content.contentproj", "{2C0E7626-F641-4C10-9682-28CDC9F6EA70}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Issue1355_MonoGame", "Issue1355\Issue1355_MonoGame.csproj", "{0650BBB1-A078-4536-850B-182BC3A78B82}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoGame.Framework.Windows", "..\..\..\..\MonoGame.Framework\MonoGame.Framework.Windows.csproj", "{7DE47032-A904-4C29-BD22-2D235E8D91BA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0650BBB1-A078-4536-850B-182BC3A78B81}.Debug|x86.ActiveCfg = Debug|x86 + {0650BBB1-A078-4536-850B-182BC3A78B81}.Debug|x86.Build.0 = Debug|x86 + {0650BBB1-A078-4536-850B-182BC3A78B81}.Release|x86.ActiveCfg = Release|x86 + {0650BBB1-A078-4536-850B-182BC3A78B81}.Release|x86.Build.0 = Release|x86 + {2C0E7626-F641-4C10-9682-28CDC9F6EA70}.Debug|x86.ActiveCfg = Debug|x86 + {2C0E7626-F641-4C10-9682-28CDC9F6EA70}.Release|x86.ActiveCfg = Release|x86 + {0650BBB1-A078-4536-850B-182BC3A78B82}.Debug|x86.ActiveCfg = Debug|x86 + {0650BBB1-A078-4536-850B-182BC3A78B82}.Debug|x86.Build.0 = Debug|x86 + {0650BBB1-A078-4536-850B-182BC3A78B82}.Release|x86.ActiveCfg = Release|x86 + {0650BBB1-A078-4536-850B-182BC3A78B82}.Release|x86.Build.0 = Release|x86 + {7DE47032-A904-4C29-BD22-2D235E8D91BA}.Debug|x86.ActiveCfg = Debug|Any CPU + {7DE47032-A904-4C29-BD22-2D235E8D91BA}.Debug|x86.Build.0 = Debug|Any CPU + {7DE47032-A904-4C29-BD22-2D235E8D91BA}.Release|x86.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Test/Interactive/Windows/Issue1355/Issue1355/Game.cs b/Test/Interactive/Windows/Issue1355/Issue1355/Game.cs new file mode 100644 index 00000000000..8926d1e1646 --- /dev/null +++ b/Test/Interactive/Windows/Issue1355/Issue1355/Game.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Audio; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.GamerServices; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Media; + +namespace Issue1355 { + /// + /// This is the main type for your game + /// + public class Game : Microsoft.Xna.Framework.Game { + GraphicsDeviceManager Graphics; + SpriteBatch SpriteBatch; + Texture2D White; + SpriteFont Font; + + public Game () { + Graphics = new GraphicsDeviceManager(this); + Graphics.PreferredBackBufferWidth = 700; + Graphics.PreferredBackBufferHeight = 200; + + Content.RootDirectory = "Content"; + +#if MONOGAME + Window.Title = "Issue1355 (MonoGame)"; +#else + Window.Title = "Issue1355 (XNA)"; +#endif + } + + protected override void LoadContent () { + SpriteBatch = new SpriteBatch(GraphicsDevice); + + White = new Texture2D(GraphicsDevice, 1, 1); + White.SetData(new[] { Color.White }); + + Font = Content.Load("DutchAndHarley"); + } + + protected override void Draw (GameTime gameTime) { + GraphicsDevice.Clear(Color.Black); + + const string testText = "{Dutch & Harley}"; + + SpriteBatch.Begin(); + + var textSize = Font.MeasureString(testText); + var textPosition = new Vector2(32, 32); + + SpriteBatch.Draw(White, textPosition, null, Color.Red * 0.25f, 0, Vector2.Zero, textSize, SpriteEffects.None, 0); + + SpriteBatch.DrawString(Font, testText, textPosition, Color.White); + + SpriteBatch.End(); + + base.Draw(gameTime); + } + + public static void Main () { + new Game().Run(); + } + } +} diff --git a/Test/Interactive/Windows/Issue1355/Issue1355/Issue1355.csproj b/Test/Interactive/Windows/Issue1355/Issue1355/Issue1355.csproj new file mode 100644 index 00000000000..21316eb442f --- /dev/null +++ b/Test/Interactive/Windows/Issue1355/Issue1355/Issue1355.csproj @@ -0,0 +1,160 @@ + + + + {0650BBB1-A078-4536-850B-182BC3A78B81} + {6D335F3A-9D43-41b4-9D22-F6F17C4BE596};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Debug + x86 + WinExe + Properties + Issue1355 + Issue1355 + v4.0 + Client + v4.0 + Windows + HiDef + 5ddec1ed-3b22-4d4f-afee-dc1a63970f5d + Game + + + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\x86\Debug + DEBUG;TRACE;WINDOWS + prompt + 4 + true + false + x86 + false + + + pdbonly + true + bin\x86\Release + TRACE;WINDOWS + prompt + 4 + true + false + x86 + true + + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + + + + + + Issue1355Content + Content + + + + + False + Microsoft .NET Framework 4 Client Profile %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + False + Microsoft XNA Framework Redistributable 4.0 + true + + + + + + + + + \ No newline at end of file diff --git a/Test/Interactive/Windows/Issue1355/Issue1355/Issue1355_MonoGame.csproj b/Test/Interactive/Windows/Issue1355/Issue1355/Issue1355_MonoGame.csproj new file mode 100644 index 00000000000..9215261c863 --- /dev/null +++ b/Test/Interactive/Windows/Issue1355/Issue1355/Issue1355_MonoGame.csproj @@ -0,0 +1,64 @@ + + + + {0650BBB1-A078-4536-850B-182BC3A78B82} + Debug + x86 + WinExe + Properties + Issue1355 + Issue1355_MonoGame + v4.0 + + + + + true + full + false + bin\x86\Debug + TRACE;DEBUG;WINDOWS;MONOGAME + prompt + 4 + true + false + x86 + false + + + pdbonly + true + bin\x86\Release + TRACE;WINDOWS;MONOGAME + prompt + 4 + true + false + x86 + true + + + + False + + + False + + + False + + + + + + + + {7DE47032-A904-4C29-BD22-2D235E8D91BA} + MonoGame.Framework.Windows + + + + + + + \ No newline at end of file diff --git a/Test/Interactive/Windows/Issue1355/Issue1355Content/DutchAndHarley.spritefont b/Test/Interactive/Windows/Issue1355/Issue1355Content/DutchAndHarley.spritefont new file mode 100644 index 00000000000..7599a39281a --- /dev/null +++ b/Test/Interactive/Windows/Issue1355/Issue1355Content/DutchAndHarley.spritefont @@ -0,0 +1,60 @@ + + + + + + + Dutch & Harley + + + 48 + + + 0 + + + true + + + + + + + + + + + + þ + + + + diff --git a/Test/Interactive/Windows/Issue1355/Issue1355Content/Issue1355Content.contentproj b/Test/Interactive/Windows/Issue1355/Issue1355Content/Issue1355Content.contentproj new file mode 100644 index 00000000000..8cfb4fe06f2 --- /dev/null +++ b/Test/Interactive/Windows/Issue1355/Issue1355Content/Issue1355Content.contentproj @@ -0,0 +1,59 @@ + + + + {2C0E7626-F641-4C10-9682-28CDC9F6EA70} + {96E2B04D-8817-42c6-938A-82C39BA4D311};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Debug + x86 + Library + Properties + v4.0 + v4.0 + bin\$(Platform)\$(Configuration) + Content + + + x86 + + + x86 + + + Issue1355Content + + + + False + + + False + + + False + + + False + + + False + + + False + + + + + DutchAndHarley + FontDescriptionImporter + FontDescriptionProcessor + + + + + \ No newline at end of file From 9ce6a0187c3b77e880b82fd95bed1f74b08fa9fe Mon Sep 17 00:00:00 2001 From: Kevin Gadd Date: Mon, 29 Apr 2013 06:34:46 -0700 Subject: [PATCH 19/21] Fix DrawInto not properly handling left side overhang of characters. Fix SpriteFont.Measure not completely compensating for negative left side overhang of characters. --- MonoGame.Framework/Graphics/SpriteFont.cs | 32 +++++++++++++---------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/MonoGame.Framework/Graphics/SpriteFont.cs b/MonoGame.Framework/Graphics/SpriteFont.cs index 42cf1202794..6cd68fe0efd 100644 --- a/MonoGame.Framework/Graphics/SpriteFont.cs +++ b/MonoGame.Framework/Graphics/SpriteFont.cs @@ -219,14 +219,16 @@ private void MeasureString(ref CharacterSource text, out Vector2 size) } if (hasCurrentGlyph) { - offset.X += Spacing + currentGlyph.LeftSideBearing; + offset.X += Spacing; // The first character on a line might have a negative left side bearing. // In this scenario, SpriteBatch/SpriteFont normally offset the text to the right, // so that text does not hang off the left side of its rectangle. if (firstGlyphOfLine) { - offset.X = Math.Max(offset.X, 0); + offset.X = Math.Max(offset.X + Math.Abs(currentGlyph.LeftSideBearing), 0); firstGlyphOfLine = false; + } else { + offset.X += currentGlyph.LeftSideBearing; } offset.X += currentGlyph.Width + currentGlyph.RightSideBearing; @@ -325,17 +327,7 @@ internal void DrawInto( SpriteBatch spriteBatch, ref CharacterSource text, Vecto } if (hasCurrentGlyph) { - offset.X += Spacing; - - // The first character on a line might have a negative left side bearing. - // In this scenario, SpriteBatch/SpriteFont normally offset the text to the right, - // so that text does not hang off the left side of its rectangle. - if (firstGlyphOfLine) { - offset.X = Math.Max(offset.X, 0); - firstGlyphOfLine = false; - } - - offset.X += currentGlyph.Width + currentGlyph.RightSideBearing; + offset.X += Spacing + currentGlyph.Width + currentGlyph.RightSideBearing; } hasCurrentGlyph = _glyphs.TryGetValue(c, out currentGlyph); @@ -347,7 +339,19 @@ internal void DrawInto( SpriteBatch spriteBatch, ref CharacterSource text, Vecto currentGlyph = defaultGlyph.Value; hasCurrentGlyph = true; } - offset.X += currentGlyph.LeftSideBearing; + + if (hasCurrentGlyph) { + // The first character on a line might have a negative left side bearing. + // In this scenario, SpriteBatch/SpriteFont normally offset the text to the right, + // so that text does not hang off the left side of its rectangle. + if (firstGlyphOfLine) { + offset.X = Math.Max(offset.X, 0); + firstGlyphOfLine = false; + } else { + offset.X += currentGlyph.LeftSideBearing; + } + } + var p = offset; if (flippedHorz) From 520409fcde1cfe66741c1a01d47457fbaf3741c1 Mon Sep 17 00:00:00 2001 From: John Weng Date: Mon, 7 Jul 2014 13:31:43 -0700 Subject: [PATCH 20/21] Fixed a bug that prevented Texture2D (on PSM) from properly disposing their unmanaged resources. Added some debug tracking for PSM textures. --- MonoGame.Framework/Content/ContentManager.cs | 1 + MonoGame.Framework/Graphics/Texture2D.cs | 2194 +++++++++--------- 2 files changed, 1107 insertions(+), 1088 deletions(-) diff --git a/MonoGame.Framework/Content/ContentManager.cs b/MonoGame.Framework/Content/ContentManager.cs index 0ab0d8cf1ef..c2449cbc6b5 100644 --- a/MonoGame.Framework/Content/ContentManager.cs +++ b/MonoGame.Framework/Content/ContentManager.cs @@ -206,6 +206,7 @@ public virtual T Load(string assetName) { return (T)asset; } + else { throw new Exception("Attempted to Load an asset (with ContentManager) that already exists, but as a different type! This would cause an unmanaged memory leak, so it's not allowed."); } } // Load the asset. diff --git a/MonoGame.Framework/Graphics/Texture2D.cs b/MonoGame.Framework/Graphics/Texture2D.cs index 3472c6f816b..31d3bd4a455 100644 --- a/MonoGame.Framework/Graphics/Texture2D.cs +++ b/MonoGame.Framework/Graphics/Texture2D.cs @@ -1,1094 +1,1112 @@ -#region License -/* -Microsoft Public License (Ms-PL) -MonoGame - Copyright © 2009 The MonoGame Team - -All rights reserved. - -This license governs use of the accompanying software. If you use the software, you accept this license. If you do not -accept the license, do not use the software. - -1. Definitions -The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under -U.S. copyright law. - -A "contribution" is the original software, or any additions or changes to the software. -A "contributor" is any person that distributes its contribution under this license. -"Licensed patents" are a contributor's patent claims that read directly on its contribution. - -2. Grant of Rights -(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, -each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. -(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, -each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. - -3. Conditions and Limitations -(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. -(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, -your patent license from such contributor to the software ends automatically. -(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution -notices that are present in the software. -(D) If you distribute any portion of the software in source code form, you may do so only under this license by including -a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object -code form, you may only do so under a license that complies with this license. -(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees -or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent -permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular -purpose and non-infringement. -*/ -#endregion License - -using System; -#if !PSM -using System.Drawing; -#else -using Sce.PlayStation.Core.Graphics; -#endif -using System.IO; -using System.Runtime.InteropServices; - -#if MONOMAC -using MonoMac.AppKit; -using MonoMac.CoreGraphics; -using MonoMac.Foundation; -#elif IOS -using MonoTouch.UIKit; -using MonoTouch.CoreGraphics; -using MonoTouch.Foundation; -#endif - -#if OPENGL -#if MONOMAC -using MonoMac.OpenGL; -using GLPixelFormat = MonoMac.OpenGL.PixelFormat; -#elif WINDOWS || LINUX -using OpenTK.Graphics.OpenGL; -using GLPixelFormat = OpenTK.Graphics.OpenGL.PixelFormat; -#elif GLES -using OpenTK.Graphics.ES20; -using GLPixelFormat = OpenTK.Graphics.ES20.All; -using TextureTarget = OpenTK.Graphics.ES20.All; -using TextureParameterName = OpenTK.Graphics.ES20.All; -using TextureMinFilter = OpenTK.Graphics.ES20.All; -using PixelInternalFormat = OpenTK.Graphics.ES20.All; -using PixelType = OpenTK.Graphics.ES20.All; -using PixelStoreParameter = OpenTK.Graphics.ES20.All; -using ErrorCode = OpenTK.Graphics.ES20.All; -#endif -#elif PSM -using PssTexture2D = Sce.PlayStation.Core.Graphics.Texture2D; -#endif - -#if WINDOWS || LINUX || MONOMAC -using System.Drawing.Imaging; -#endif -using Microsoft.Xna.Framework.Content; -using System.Diagnostics; - -#if WINRT -#if WINDOWS_PHONE -using System.Threading; -using System.Windows; -using System.Windows.Media.Imaging; -#else -using Windows.Graphics.Imaging; -using Windows.UI.Xaml.Media.Imaging; -#endif -using Windows.Storage.Streams; -using System.Threading.Tasks; -#endif - -#if ANDROID -using Android.Graphics; -#endif - -namespace Microsoft.Xna.Framework.Graphics -{ - public class Texture2D : Texture - { - protected int width; - protected int height; - -#if PSM - internal PssTexture2D _texture2D; - -#elif OPENGL - PixelInternalFormat glInternalFormat; - GLPixelFormat glFormat; - PixelType glType; -#endif - - public Rectangle Bounds - { - get - { - return new Rectangle(0, 0, this.width, this.height); - } - } - - public Texture2D(GraphicsDevice graphicsDevice, int width, int height, bool mipmap, SurfaceFormat format) - : this(graphicsDevice, width, height, mipmap, format, false) - { - } - - internal Texture2D(GraphicsDevice graphicsDevice, int width, int height, bool mipmap, SurfaceFormat format, bool renderTarget) - { - if (graphicsDevice == null) - throw new ArgumentNullException("Graphics Device Cannot Be Null"); - - this.GraphicsDevice = graphicsDevice; - this.width = width; - this.height = height; - this.format = format; - this.levelCount = mipmap ? CalculateMipLevels(width, height) : 1; - -#if DIRECTX - - // TODO: Move this to SetData() if we want to make Immutable textures! - var desc = new SharpDX.Direct3D11.Texture2DDescription(); - desc.Width = width; - desc.Height = height; - desc.MipLevels = levelCount; - desc.ArraySize = 1; - desc.Format = SharpDXHelper.ToFormat(format); - desc.BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource; - desc.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None; - desc.SampleDescription.Count = 1; - desc.SampleDescription.Quality = 0; - desc.Usage = SharpDX.Direct3D11.ResourceUsage.Default; - desc.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None; - - if (renderTarget) - { - desc.BindFlags |= SharpDX.Direct3D11.BindFlags.RenderTarget; - if (mipmap) - { - // Note: XNA 4 does not have a method Texture.GenerateMipMaps() - // because generation of mipmaps is not supported on the Xbox 360. - // TODO: New method Texture.GenerateMipMaps() required. - desc.OptionFlags |= SharpDX.Direct3D11.ResourceOptionFlags.GenerateMipMaps; - } - } - - _texture = new SharpDX.Direct3D11.Texture2D(graphicsDevice._d3dDevice, desc); - -#elif PSM - PixelBufferOption option = PixelBufferOption.None; - if (renderTarget) - option = PixelBufferOption.Renderable; - _texture2D = new Sce.PlayStation.Core.Graphics.Texture2D(width, height, mipmap, PSSHelper.ToFormat(format),option); -#else - - this.glTarget = TextureTarget.Texture2D; - - Threading.BlockOnUIThread(() => - { - // Store the current bound texture. - var prevTexture = GraphicsExtensions.GetBoundTexture2D(); - - GenerateGLTextureIfRequired(); - - format.GetGLFormat(out glInternalFormat, out glFormat, out glType); - - if (glFormat == (GLPixelFormat)All.CompressedTextureFormats) - { - var imageSize = 0; - switch (format) - { - case SurfaceFormat.RgbPvrtc2Bpp: - case SurfaceFormat.RgbaPvrtc2Bpp: - imageSize = (Math.Max(this.width, 8) * Math.Max(this.height, 8) * 2 + 7) / 8; - break; - case SurfaceFormat.RgbPvrtc4Bpp: - case SurfaceFormat.RgbaPvrtc4Bpp: - imageSize = (Math.Max(this.width, 16) * Math.Max(this.height, 8) * 4 + 7) / 8; - break; - case SurfaceFormat.Dxt1: - imageSize = ((this.width + 3) / 4) * ((this.height + 3) / 4) * 8 * 1; - break; - case SurfaceFormat.Dxt3: - case SurfaceFormat.Dxt5: - imageSize = ((this.width + 3) / 4) * ((this.height + 3) / 4) * 16 * 1; - break; - default: - throw new NotImplementedException(); - } - - GL.CompressedTexImage2D(TextureTarget.Texture2D, 0, glInternalFormat, - this.width, this.height, 0, - imageSize, IntPtr.Zero); - GraphicsExtensions.CheckGLError(); - } - else - { - GL.TexImage2D(TextureTarget.Texture2D, 0, -#if IOS || ANDROID - (int)glInternalFormat, -#else - glInternalFormat, -#endif - this.width, this.height, 0, - glFormat, glType, IntPtr.Zero); - GraphicsExtensions.CheckGLError(); - } - - // Restore the bound texture. - GL.BindTexture(TextureTarget.Texture2D, prevTexture); - GraphicsExtensions.CheckGLError(); - }); -#endif - } - -#if PSM - private Texture2D(GraphicsDevice graphicsDevice, Stream stream) - { - byte[] bytes = new byte[stream.Length]; - stream.Read(bytes, 0, (int)stream.Length); - _texture2D = new PssTexture2D(bytes, false); - width = _texture2D.Width; - height = _texture2D.Height; - this.format = SurfaceFormat.Color; //FIXME HACK - this.levelCount = 1; - } -#endif - - public Texture2D(GraphicsDevice graphicsDevice, int width, int height) - : this(graphicsDevice, width, height, false, SurfaceFormat.Color, false) - { - } - - public int Width - { - get - { - return width; - } - } - - public int Height - { - get - { - return height; - } - } - - public void SetData(int level, Rectangle? rect, T[] data, int startIndex, int elementCount) where T : struct - { - if (data == null) - throw new ArgumentNullException("data"); - -#if OPENGL - Threading.BlockOnUIThread(() => - { -#endif -#if !PSM - var elementSizeInByte = Marshal.SizeOf(typeof(T)); - var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); - var startBytes = startIndex * elementSizeInByte; - var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes); -#endif - int x, y, w, h; - if (rect.HasValue) - { - x = rect.Value.X; - y = rect.Value.Y; - w = rect.Value.Width; - h = rect.Value.Height; - } - else - { - x = 0; - y = 0; - w = Math.Max(width >> level, 1); - h = Math.Max(height >> level, 1); - -#if DIRECTX - // For DXT textures the width and height of each level is a multiply of 4. - if (format == SurfaceFormat.Dxt1 || format == SurfaceFormat.Dxt3 || format == SurfaceFormat.Dxt5) - { - w = ((w + 3) / 4) * 4; - h = ((h + 3) / 4) * 4; - } -#endif - } - -#if DIRECTX - - var box = new SharpDX.DataBox(dataPtr, GetPitch(w), 0); - - var region = new SharpDX.Direct3D11.ResourceRegion(); - region.Top = y; - region.Front = 0; - region.Back = 1; - region.Bottom = y + h; - region.Left = x; - region.Right = x + w; - - // TODO: We need to deal with threaded contexts here! - var d3dContext = GraphicsDevice._d3dContext; - lock (d3dContext) - d3dContext.UpdateSubresource(box, _texture, level, region); - -#elif PSM - _texture2D.SetPixels(level, data, _texture2D.Format, startIndex, 0, x, y, w, h); - -#elif OPENGL - - // Store the current bound texture. - var prevTexture = GraphicsExtensions.GetBoundTexture2D(); - - GenerateGLTextureIfRequired(); - - GL.BindTexture(TextureTarget.Texture2D, this.glTexture); - GraphicsExtensions.CheckGLError(); - if (glFormat == (GLPixelFormat)All.CompressedTextureFormats) - { - if (rect.HasValue) - { - GL.CompressedTexSubImage2D(TextureTarget.Texture2D, - level, x, y, w, h, -#if GLES - glInternalFormat, -#else - glFormat, -#endif - data.Length - startBytes, dataPtr); - GraphicsExtensions.CheckGLError(); - } - else - { - GL.CompressedTexImage2D(TextureTarget.Texture2D, level, glInternalFormat, w, h, 0, data.Length - startBytes, dataPtr); - GraphicsExtensions.CheckGLError(); - } - } - else - { - // Set pixel alignment to match texel size in bytes - GL.PixelStore(PixelStoreParameter.UnpackAlignment, GraphicsExtensions.Size(this.Format)); - if (rect.HasValue) - { - GL.TexSubImage2D(TextureTarget.Texture2D, level, - x, y, w, h, - glFormat, glType, dataPtr); - GraphicsExtensions.CheckGLError(); - } - else - { - GL.TexImage2D(TextureTarget.Texture2D, level, -#if GLES - (int)glInternalFormat, -#else - glInternalFormat, -#endif - w, h, 0, glFormat, glType, dataPtr); - GraphicsExtensions.CheckGLError(); - } - // Return to default pixel alignment - GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4); - } - -#if !ANDROID - GL.Finish(); - GraphicsExtensions.CheckGLError(); -#endif - // Restore the bound texture. - GL.BindTexture(TextureTarget.Texture2D, prevTexture); - GraphicsExtensions.CheckGLError(); - -#endif // OPENGL - -#if !PSM - dataHandle.Free(); -#endif - -#if OPENGL -#if !ANDROID - // Required to make sure that any texture uploads on a thread are completed - // before the main thread tries to use the texture. - GL.Finish(); -#endif - }); -#endif - } - - public void SetData(T[] data, int startIndex, int elementCount) where T : struct - { - this.SetData(0, null, data, startIndex, elementCount); - } - - public void SetData(T[] data) where T : struct - { - this.SetData(0, null, data, 0, data.Length); - } - - public void GetData(int level, Rectangle? rect, T[] data, int startIndex, int elementCount) where T : struct - { - if (data == null || data.Length == 0) - throw new ArgumentException("data cannot be null"); - if (data.Length < startIndex + elementCount) - throw new ArgumentException("The data passed has a length of " + data.Length + " but " + elementCount + " pixels have been requested."); - -#if IOS - - // Reading back a texture from GPU memory is unsupported - // in OpenGL ES 2.0 and no work around has been implemented. - throw new NotSupportedException("OpenGL ES 2.0 does not support texture reads."); - -#elif ANDROID - - Rectangle r; - if (rect != null) - { - r = rect.Value; - } - else - { - r = new Rectangle(0, 0, Width, Height); - } - - // Get the Color values - if (typeof(T) == typeof(uint)) - { - Color[] colors = new Color[elementCount]; - GetData(level, rect, colors, startIndex, elementCount); - uint[] final = data as uint[]; - for (int i = 0; i < final.Length; i++) - { - final[i] = (uint) - ( +#region License +/* +Microsoft Public License (Ms-PL) +MonoGame - Copyright © 2009 The MonoGame Team + +All rights reserved. + +This license governs use of the accompanying software. If you use the software, you accept this license. If you do not +accept the license, do not use the software. + +1. Definitions +The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under +U.S. copyright law. + +A "contribution" is the original software, or any additions or changes to the software. +A "contributor" is any person that distributes its contribution under this license. +"Licensed patents" are a contributor's patent claims that read directly on its contribution. + +2. Grant of Rights +(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, +each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. +(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, +each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. + +3. Conditions and Limitations +(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. +(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, +your patent license from such contributor to the software ends automatically. +(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution +notices that are present in the software. +(D) If you distribute any portion of the software in source code form, you may do so only under this license by including +a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object +code form, you may only do so under a license that complies with this license. +(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees +or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent +permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular +purpose and non-infringement. +*/ +#endregion License + +using System; +#if !PSM +using System.Drawing; +#else +using Sce.PlayStation.Core.Graphics; +#endif +using System.IO; +using System.Runtime.InteropServices; + +#if MONOMAC +using MonoMac.AppKit; +using MonoMac.CoreGraphics; +using MonoMac.Foundation; +#elif IOS +using MonoTouch.UIKit; +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +#endif + +#if OPENGL +#if MONOMAC +using MonoMac.OpenGL; +using GLPixelFormat = MonoMac.OpenGL.PixelFormat; +#elif WINDOWS || LINUX +using OpenTK.Graphics.OpenGL; +using GLPixelFormat = OpenTK.Graphics.OpenGL.PixelFormat; +#elif GLES +using OpenTK.Graphics.ES20; +using GLPixelFormat = OpenTK.Graphics.ES20.All; +using TextureTarget = OpenTK.Graphics.ES20.All; +using TextureParameterName = OpenTK.Graphics.ES20.All; +using TextureMinFilter = OpenTK.Graphics.ES20.All; +using PixelInternalFormat = OpenTK.Graphics.ES20.All; +using PixelType = OpenTK.Graphics.ES20.All; +using PixelStoreParameter = OpenTK.Graphics.ES20.All; +using ErrorCode = OpenTK.Graphics.ES20.All; +#endif +#elif PSM +using PssTexture2D = Sce.PlayStation.Core.Graphics.Texture2D; +#endif + +#if WINDOWS || LINUX || MONOMAC +using System.Drawing.Imaging; +#endif +using Microsoft.Xna.Framework.Content; +using System.Diagnostics; + +#if WINRT +#if WINDOWS_PHONE +using System.Threading; +using System.Windows; +using System.Windows.Media.Imaging; +#else +using Windows.Graphics.Imaging; +using Windows.UI.Xaml.Media.Imaging; +#endif +using Windows.Storage.Streams; +using System.Threading.Tasks; +#endif + +#if ANDROID +using Android.Graphics; +#endif + +namespace Microsoft.Xna.Framework.Graphics +{ + public class Texture2D : Texture + { + protected int width; + protected int height; + +#if PSM + internal PssTexture2D _texture2D; + public static System.Collections.Generic.List EveryPsmTextureEver = new System.Collections.Generic.List(); +#elif OPENGL + PixelInternalFormat glInternalFormat; + GLPixelFormat glFormat; + PixelType glType; +#endif + + public Rectangle Bounds + { + get + { + return new Rectangle(0, 0, this.width, this.height); + } + } + + public Texture2D(GraphicsDevice graphicsDevice, int width, int height, bool mipmap, SurfaceFormat format) + : this(graphicsDevice, width, height, mipmap, format, false) + { + } + + public void Dispose() + { + this.Dispose(true); // Dispose of unmanaged resources. + GC.SuppressFinalize(this); // Suppress finalization. + } + protected override void Dispose (bool disposing) + { + base.Dispose (disposing); +#if PSM + if(_texture2D != null) + _texture2D.Dispose(); // Dispose internal PssTexture2D (PSM) +#endif + } + ~Texture2D() { + this.Dispose( false ); // False indicates it's from finalizer instead of Dispose + } + + internal Texture2D(GraphicsDevice graphicsDevice, int width, int height, bool mipmap, SurfaceFormat format, bool renderTarget) + { + if (graphicsDevice == null) + throw new ArgumentNullException("Graphics Device Cannot Be Null"); + + this.GraphicsDevice = graphicsDevice; + this.width = width; + this.height = height; + this.format = format; + this.levelCount = mipmap ? CalculateMipLevels(width, height) : 1; + +#if DIRECTX + + // TODO: Move this to SetData() if we want to make Immutable textures! + var desc = new SharpDX.Direct3D11.Texture2DDescription(); + desc.Width = width; + desc.Height = height; + desc.MipLevels = levelCount; + desc.ArraySize = 1; + desc.Format = SharpDXHelper.ToFormat(format); + desc.BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource; + desc.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None; + desc.SampleDescription.Count = 1; + desc.SampleDescription.Quality = 0; + desc.Usage = SharpDX.Direct3D11.ResourceUsage.Default; + desc.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None; + + if (renderTarget) + { + desc.BindFlags |= SharpDX.Direct3D11.BindFlags.RenderTarget; + if (mipmap) + { + // Note: XNA 4 does not have a method Texture.GenerateMipMaps() + // because generation of mipmaps is not supported on the Xbox 360. + // TODO: New method Texture.GenerateMipMaps() required. + desc.OptionFlags |= SharpDX.Direct3D11.ResourceOptionFlags.GenerateMipMaps; + } + } + + _texture = new SharpDX.Direct3D11.Texture2D(graphicsDevice._d3dDevice, desc); + +#elif PSM + PixelBufferOption option = PixelBufferOption.None; + if (renderTarget) + option = PixelBufferOption.Renderable; + _texture2D = new Sce.PlayStation.Core.Graphics.Texture2D(width, height, mipmap, PSSHelper.ToFormat(format),option); + EveryPsmTextureEver.Add(this); // Add to texture tracker +#else + + this.glTarget = TextureTarget.Texture2D; + + Threading.BlockOnUIThread(() => + { + // Store the current bound texture. + var prevTexture = GraphicsExtensions.GetBoundTexture2D(); + + GenerateGLTextureIfRequired(); + + format.GetGLFormat(out glInternalFormat, out glFormat, out glType); + + if (glFormat == (GLPixelFormat)All.CompressedTextureFormats) + { + var imageSize = 0; + switch (format) + { + case SurfaceFormat.RgbPvrtc2Bpp: + case SurfaceFormat.RgbaPvrtc2Bpp: + imageSize = (Math.Max(this.width, 8) * Math.Max(this.height, 8) * 2 + 7) / 8; + break; + case SurfaceFormat.RgbPvrtc4Bpp: + case SurfaceFormat.RgbaPvrtc4Bpp: + imageSize = (Math.Max(this.width, 16) * Math.Max(this.height, 8) * 4 + 7) / 8; + break; + case SurfaceFormat.Dxt1: + imageSize = ((this.width + 3) / 4) * ((this.height + 3) / 4) * 8 * 1; + break; + case SurfaceFormat.Dxt3: + case SurfaceFormat.Dxt5: + imageSize = ((this.width + 3) / 4) * ((this.height + 3) / 4) * 16 * 1; + break; + default: + throw new NotImplementedException(); + } + + GL.CompressedTexImage2D(TextureTarget.Texture2D, 0, glInternalFormat, + this.width, this.height, 0, + imageSize, IntPtr.Zero); + GraphicsExtensions.CheckGLError(); + } + else + { + GL.TexImage2D(TextureTarget.Texture2D, 0, +#if IOS || ANDROID + (int)glInternalFormat, +#else + glInternalFormat, +#endif + this.width, this.height, 0, + glFormat, glType, IntPtr.Zero); + GraphicsExtensions.CheckGLError(); + } + + // Restore the bound texture. + GL.BindTexture(TextureTarget.Texture2D, prevTexture); + GraphicsExtensions.CheckGLError(); + }); +#endif + } + +#if PSM + private Texture2D(GraphicsDevice graphicsDevice, Stream stream) + { + byte[] bytes = new byte[stream.Length]; + stream.Read(bytes, 0, (int)stream.Length); + _texture2D = new PssTexture2D(bytes, false); + width = _texture2D.Width; + height = _texture2D.Height; + this.format = SurfaceFormat.Color; //FIXME HACK + this.levelCount = 1; + } +#endif + + public Texture2D(GraphicsDevice graphicsDevice, int width, int height) + : this(graphicsDevice, width, height, false, SurfaceFormat.Color, false) + { + } + + public int Width + { + get + { + return width; + } + } + + public int Height + { + get + { + return height; + } + } + + public void SetData(int level, Rectangle? rect, T[] data, int startIndex, int elementCount) where T : struct + { + if (data == null) + throw new ArgumentNullException("data"); + +#if OPENGL + Threading.BlockOnUIThread(() => + { +#endif +#if !PSM + var elementSizeInByte = Marshal.SizeOf(typeof(T)); + var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); + var startBytes = startIndex * elementSizeInByte; + var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes); +#endif + int x, y, w, h; + if (rect.HasValue) + { + x = rect.Value.X; + y = rect.Value.Y; + w = rect.Value.Width; + h = rect.Value.Height; + } + else + { + x = 0; + y = 0; + w = Math.Max(width >> level, 1); + h = Math.Max(height >> level, 1); + +#if DIRECTX + // For DXT textures the width and height of each level is a multiply of 4. + if (format == SurfaceFormat.Dxt1 || format == SurfaceFormat.Dxt3 || format == SurfaceFormat.Dxt5) + { + w = ((w + 3) / 4) * 4; + h = ((h + 3) / 4) * 4; + } +#endif + } + +#if DIRECTX + + var box = new SharpDX.DataBox(dataPtr, GetPitch(w), 0); + + var region = new SharpDX.Direct3D11.ResourceRegion(); + region.Top = y; + region.Front = 0; + region.Back = 1; + region.Bottom = y + h; + region.Left = x; + region.Right = x + w; + + // TODO: We need to deal with threaded contexts here! + var d3dContext = GraphicsDevice._d3dContext; + lock (d3dContext) + d3dContext.UpdateSubresource(box, _texture, level, region); + +#elif PSM + _texture2D.SetPixels(level, data, _texture2D.Format, startIndex, 0, x, y, w, h); + +#elif OPENGL + + // Store the current bound texture. + var prevTexture = GraphicsExtensions.GetBoundTexture2D(); + + GenerateGLTextureIfRequired(); + + GL.BindTexture(TextureTarget.Texture2D, this.glTexture); + GraphicsExtensions.CheckGLError(); + if (glFormat == (GLPixelFormat)All.CompressedTextureFormats) + { + if (rect.HasValue) + { + GL.CompressedTexSubImage2D(TextureTarget.Texture2D, + level, x, y, w, h, +#if GLES + glInternalFormat, +#else + glFormat, +#endif + data.Length - startBytes, dataPtr); + GraphicsExtensions.CheckGLError(); + } + else + { + GL.CompressedTexImage2D(TextureTarget.Texture2D, level, glInternalFormat, w, h, 0, data.Length - startBytes, dataPtr); + GraphicsExtensions.CheckGLError(); + } + } + else + { + // Set pixel alignment to match texel size in bytes + GL.PixelStore(PixelStoreParameter.UnpackAlignment, GraphicsExtensions.Size(this.Format)); + if (rect.HasValue) + { + GL.TexSubImage2D(TextureTarget.Texture2D, level, + x, y, w, h, + glFormat, glType, dataPtr); + GraphicsExtensions.CheckGLError(); + } + else + { + GL.TexImage2D(TextureTarget.Texture2D, level, +#if GLES + (int)glInternalFormat, +#else + glInternalFormat, +#endif + w, h, 0, glFormat, glType, dataPtr); + GraphicsExtensions.CheckGLError(); + } + // Return to default pixel alignment + GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4); + } + +#if !ANDROID + GL.Finish(); + GraphicsExtensions.CheckGLError(); +#endif + // Restore the bound texture. + GL.BindTexture(TextureTarget.Texture2D, prevTexture); + GraphicsExtensions.CheckGLError(); + +#endif // OPENGL + +#if !PSM + dataHandle.Free(); +#endif + +#if OPENGL +#if !ANDROID + // Required to make sure that any texture uploads on a thread are completed + // before the main thread tries to use the texture. + GL.Finish(); +#endif + }); +#endif + } + + public void SetData(T[] data, int startIndex, int elementCount) where T : struct + { + this.SetData(0, null, data, startIndex, elementCount); + } + + public void SetData(T[] data) where T : struct + { + this.SetData(0, null, data, 0, data.Length); + } + + public void GetData(int level, Rectangle? rect, T[] data, int startIndex, int elementCount) where T : struct + { + if (data == null || data.Length == 0) + throw new ArgumentException("data cannot be null"); + if (data.Length < startIndex + elementCount) + throw new ArgumentException("The data passed has a length of " + data.Length + " but " + elementCount + " pixels have been requested."); + +#if IOS + + // Reading back a texture from GPU memory is unsupported + // in OpenGL ES 2.0 and no work around has been implemented. + throw new NotSupportedException("OpenGL ES 2.0 does not support texture reads."); + +#elif ANDROID + + Rectangle r; + if (rect != null) + { + r = rect.Value; + } + else + { + r = new Rectangle(0, 0, Width, Height); + } + + // Get the Color values + if (typeof(T) == typeof(uint)) + { + Color[] colors = new Color[elementCount]; + GetData(level, rect, colors, startIndex, elementCount); + uint[] final = data as uint[]; + for (int i = 0; i < final.Length; i++) + { + final[i] = (uint) + ( // use correct xna byte order (and remember to convert it yourself as needed) colors[i].A << 24 | colors[i].B << 16 | colors[i].G << 8 | - colors[i].R - ); - } - } - // Get the Color values - else if ((typeof(T) == typeof(Color))) - { - byte[] imageInfo = GetTextureData(0); - - int rWidth = r.Width; - int rHeight = r.Height; - - // Loop through and extract the data but we need to load it - var dataRowColOffset = 0; - var sz = 0; - var pixelOffset = 0; - for (int y = r.Top; y < rHeight; y++) - { - for (int x = r.Left; x < rWidth; x++) - { - var result = new Color(0, 0, 0, 0); - dataRowColOffset = ((y * r.Width) + x); - switch (Format) - { - case SurfaceFormat.Color: //kTexture2DPixelFormat_RGBA8888 - case SurfaceFormat.Dxt3: - sz = 4; - pixelOffset = dataRowColOffset * sz; - result.R = imageInfo[pixelOffset]; - result.G = imageInfo[pixelOffset + 1]; - result.B = imageInfo[pixelOffset + 2]; - result.A = imageInfo[pixelOffset + 3]; - break; - case SurfaceFormat.Bgra4444: //kTexture2DPixelFormat_RGBA4444 - // sz = 2; - // pos = ((y * imageSize.Width) + x) * sz; - // pixelOffset = new IntPtr (imageData.ToInt64 () + pos); - // - // Marshal.Copy (pixelOffset, pixel, 0, 4); - // - // result.R = pixel [0]; - // result.G = pixel [1]; - // result.B = pixel [2]; - // result.A = pixel [3]; - sz = 2; - pixelOffset = dataRowColOffset * sz; - result.R = imageInfo[pixelOffset]; - result.G = imageInfo[pixelOffset + 1]; - result.B = imageInfo[pixelOffset + 2]; - result.A = imageInfo[pixelOffset + 3]; - break; - case SurfaceFormat.Bgra5551: //kTexture2DPixelFormat_RGB5A1 - // sz = 2; - // pos = ((y * imageSize.Width) + x) * sz; - // pixelOffset = new IntPtr (imageData.ToInt64 () + pos); - // Marshal.Copy (pixelOffset, pixel, 0, 4); - // - // result.R = pixel [0]; - // result.G = pixel [1]; - // result.B = pixel [2]; - // result.A = pixel [3]; - sz = 2; - pixelOffset = dataRowColOffset * sz; - result.R = imageInfo[pixelOffset]; - result.G = imageInfo[pixelOffset + 1]; - result.B = imageInfo[pixelOffset + 2]; - result.A = imageInfo[pixelOffset + 3]; - break; - case SurfaceFormat.Alpha8: // kTexture2DPixelFormat_A8 - // sz = 1; - // pos = ((y * imageSize.Width) + x) * sz; - // pixelOffset = new IntPtr (imageData.ToInt64 () + pos); - // Marshal.Copy (pixelOffset, pixel, 0, 4); - // - // result.A = pixel [0]; - sz = 1; - pixelOffset = dataRowColOffset * sz; - result.A = imageInfo[pixelOffset]; - break; - default: - throw new NotSupportedException("Texture format"); - } - data[dataRowColOffset] = (T)(object)result; - } - } - } - else - { - throw new NotImplementedException("GetData not implemented for type."); - } -#elif PSM - - throw new NotImplementedException(); - -#elif DIRECTX - - // Create a temp staging resource for copying the data. - // - // TODO: We should probably be pooling these staging resources - // and not creating a new one each time. - // - var desc = new SharpDX.Direct3D11.Texture2DDescription(); - desc.Width = width; - desc.Height = height; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = SharpDXHelper.ToFormat(format); - desc.BindFlags = SharpDX.Direct3D11.BindFlags.None; - desc.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.Read; - desc.SampleDescription.Count = 1; - desc.SampleDescription.Quality = 0; - desc.Usage = SharpDX.Direct3D11.ResourceUsage.Staging; - desc.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None; - - var d3dContext = GraphicsDevice._d3dContext; - using (var stagingTex = new SharpDX.Direct3D11.Texture2D(GraphicsDevice._d3dDevice, desc)) - lock (d3dContext) - { - // Copy the data from the GPU to the staging texture. - if (rect.HasValue) - { - // TODO: Need to deal with subregion copies! - throw new NotImplementedException(); - } - else - d3dContext.CopySubresourceRegion(_texture, level, null, stagingTex, 0, 0, 0, 0); - - // Copy the data to the array. - SharpDX.DataStream stream; - d3dContext.MapSubresource(stagingTex, 0, SharpDX.Direct3D11.MapMode.Read, SharpDX.Direct3D11.MapFlags.None, out stream); - stream.ReadRange(data, startIndex, elementCount); - stream.Dispose(); - } - + colors[i].R + ); + } + } + // Get the Color values + else if ((typeof(T) == typeof(Color))) + { + byte[] imageInfo = GetTextureData(0); + + int rWidth = r.Width; + int rHeight = r.Height; + + // Loop through and extract the data but we need to load it + var dataRowColOffset = 0; + var sz = 0; + var pixelOffset = 0; + for (int y = r.Top; y < rHeight; y++) + { + for (int x = r.Left; x < rWidth; x++) + { + var result = new Color(0, 0, 0, 0); + dataRowColOffset = ((y * r.Width) + x); + switch (Format) + { + case SurfaceFormat.Color: //kTexture2DPixelFormat_RGBA8888 + case SurfaceFormat.Dxt3: + sz = 4; + pixelOffset = dataRowColOffset * sz; + result.R = imageInfo[pixelOffset]; + result.G = imageInfo[pixelOffset + 1]; + result.B = imageInfo[pixelOffset + 2]; + result.A = imageInfo[pixelOffset + 3]; + break; + case SurfaceFormat.Bgra4444: //kTexture2DPixelFormat_RGBA4444 + // sz = 2; + // pos = ((y * imageSize.Width) + x) * sz; + // pixelOffset = new IntPtr (imageData.ToInt64 () + pos); + // + // Marshal.Copy (pixelOffset, pixel, 0, 4); + // + // result.R = pixel [0]; + // result.G = pixel [1]; + // result.B = pixel [2]; + // result.A = pixel [3]; + sz = 2; + pixelOffset = dataRowColOffset * sz; + result.R = imageInfo[pixelOffset]; + result.G = imageInfo[pixelOffset + 1]; + result.B = imageInfo[pixelOffset + 2]; + result.A = imageInfo[pixelOffset + 3]; + break; + case SurfaceFormat.Bgra5551: //kTexture2DPixelFormat_RGB5A1 + // sz = 2; + // pos = ((y * imageSize.Width) + x) * sz; + // pixelOffset = new IntPtr (imageData.ToInt64 () + pos); + // Marshal.Copy (pixelOffset, pixel, 0, 4); + // + // result.R = pixel [0]; + // result.G = pixel [1]; + // result.B = pixel [2]; + // result.A = pixel [3]; + sz = 2; + pixelOffset = dataRowColOffset * sz; + result.R = imageInfo[pixelOffset]; + result.G = imageInfo[pixelOffset + 1]; + result.B = imageInfo[pixelOffset + 2]; + result.A = imageInfo[pixelOffset + 3]; + break; + case SurfaceFormat.Alpha8: // kTexture2DPixelFormat_A8 + // sz = 1; + // pos = ((y * imageSize.Width) + x) * sz; + // pixelOffset = new IntPtr (imageData.ToInt64 () + pos); + // Marshal.Copy (pixelOffset, pixel, 0, 4); + // + // result.A = pixel [0]; + sz = 1; + pixelOffset = dataRowColOffset * sz; + result.A = imageInfo[pixelOffset]; + break; + default: + throw new NotSupportedException("Texture format"); + } + data[dataRowColOffset] = (T)(object)result; + } + } + } + else + { + throw new NotImplementedException("GetData not implemented for type."); + } +#elif PSM + + throw new NotImplementedException(); + +#elif DIRECTX + + // Create a temp staging resource for copying the data. + // + // TODO: We should probably be pooling these staging resources + // and not creating a new one each time. + // + var desc = new SharpDX.Direct3D11.Texture2DDescription(); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = SharpDXHelper.ToFormat(format); + desc.BindFlags = SharpDX.Direct3D11.BindFlags.None; + desc.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.Read; + desc.SampleDescription.Count = 1; + desc.SampleDescription.Quality = 0; + desc.Usage = SharpDX.Direct3D11.ResourceUsage.Staging; + desc.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None; + + var d3dContext = GraphicsDevice._d3dContext; + using (var stagingTex = new SharpDX.Direct3D11.Texture2D(GraphicsDevice._d3dDevice, desc)) + lock (d3dContext) + { + // Copy the data from the GPU to the staging texture. + if (rect.HasValue) + { + // TODO: Need to deal with subregion copies! + throw new NotImplementedException(); + } + else + d3dContext.CopySubresourceRegion(_texture, level, null, stagingTex, 0, 0, 0, 0); + + // Copy the data to the array. + SharpDX.DataStream stream; + d3dContext.MapSubresource(stagingTex, 0, SharpDX.Direct3D11.MapMode.Read, SharpDX.Direct3D11.MapFlags.None, out stream); + stream.ReadRange(data, startIndex, elementCount); + stream.Dispose(); + } + #else - GL.BindTexture(TextureTarget.Texture2D, this.glTexture); - - if (rect.HasValue) { - throw new NotImplementedException(); - } - - if (glFormat == (GLPixelFormat)All.CompressedTextureFormats) { - throw new NotImplementedException(); - } else { - GL.GetTexImage(TextureTarget.Texture2D, level, this.glFormat, this.glType, data); - } - -#endif - } - - public void GetData(T[] data, int startIndex, int elementCount) where T : struct - { - this.GetData(0, null, data, startIndex, elementCount); - } - - public void GetData (T[] data) where T : struct - { - this.GetData(0, null, data, 0, data.Length); - } - - public static Texture2D FromStream(GraphicsDevice graphicsDevice, Stream stream) - { - //todo: partial classes would be cleaner -#if IOS || MONOMAC - - - -#if IOS - using (var uiImage = UIImage.LoadFromData(NSData.FromStream(stream))) -#elif MONOMAC - using (var nsImage = NSImage.FromStream (stream)) -#endif - { -#if IOS - var cgImage = uiImage.CGImage; -#elif MONOMAC - var cgImage = nsImage.AsCGImage (RectangleF.Empty, null, null); -#endif - - var width = cgImage.Width; - var height = cgImage.Height; - - var data = new byte[width * height * 4]; - - var colorSpace = CGColorSpace.CreateDeviceRGB(); - var bitmapContext = new CGBitmapContext(data, width, height, 8, width * 4, colorSpace, CGBitmapFlags.PremultipliedLast); - bitmapContext.DrawImage(new RectangleF(0, 0, width, height), cgImage); - bitmapContext.Dispose(); - colorSpace.Dispose(); - - Texture2D texture = null; - Threading.BlockOnUIThread(() => - { - texture = new Texture2D(graphicsDevice, width, height, false, SurfaceFormat.Color); - texture.SetData(data); - }); - - return texture; - } -#elif ANDROID - using (Bitmap image = BitmapFactory.DecodeStream(stream, null, new BitmapFactory.Options - { - InScaled = false, - InDither = false, - InJustDecodeBounds = false, - InPurgeable = true, - InInputShareable = true, - })) - { - var width = image.Width; - var height = image.Height; - - int[] pixels = new int[width * height]; - if ((width != image.Width) || (height != image.Height)) - { - using (Bitmap imagePadded = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888)) - { - Canvas canvas = new Canvas(imagePadded); - canvas.DrawARGB(0, 0, 0, 0); - canvas.DrawBitmap(image, 0, 0, null); - imagePadded.GetPixels(pixels, 0, width, 0, 0, width, height); - imagePadded.Recycle(); - } - } - else - { - image.GetPixels(pixels, 0, width, 0, 0, width, height); - } - image.Recycle(); - - // Convert from ARGB to ABGR - for (int i = 0; i < width * height; ++i) - { - uint pixel = (uint)pixels[i]; - pixels[i] = (int)((pixel & 0xFF00FF00) | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16)); - } - - Texture2D texture = null; - Threading.BlockOnUIThread(() => - { - texture = new Texture2D(graphicsDevice, width, height, false, SurfaceFormat.Color); - texture.SetData(pixels); - }); - - return texture; - } - -#elif WINDOWS_STOREAPP - - // For reference this implementation was ultimately found through this post: - // http://stackoverflow.com/questions/9602102/loading-textures-with-sharpdx-in-metro - Texture2D toReturn = null; - SharpDX.WIC.BitmapDecoder decoder; - - using(var bitmap = LoadBitmap(stream, out decoder)) - using (decoder) - { - SharpDX.Direct3D11.Texture2D sharpDxTexture = CreateTex2DFromBitmap(bitmap, graphicsDevice); - - toReturn = new Texture2D(graphicsDevice, bitmap.Size.Width, bitmap.Size.Height); - - toReturn._texture = sharpDxTexture; - } - return toReturn; -#elif DIRECTX - throw new NotImplementedException(); -#elif PSM - return new Texture2D(graphicsDevice, stream); -#else - using (Bitmap image = (Bitmap)Bitmap.FromStream(stream)) - { - // Fix up the Image to match the expected format - image.RGBToBGR(); - - var data = new byte[image.Width * image.Height * 4]; - - BitmapData bitmapData = image.LockBits(new System.Drawing.Rectangle(0, 0, image.Width, image.Height), - ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - if (bitmapData.Stride != image.Width * 4) throw new NotImplementedException(); - Marshal.Copy(bitmapData.Scan0, data, 0, data.Length); - image.UnlockBits(bitmapData); - - Texture2D texture = null; - texture = new Texture2D(graphicsDevice, image.Width, image.Height); - texture.SetData(data); - - return texture; - } -#endif - } - - private void FillTextureFromStream(Stream stream) - { -#if ANDROID - using (Bitmap image = BitmapFactory.DecodeStream(stream, null, new BitmapFactory.Options - { - InScaled = false, - InDither = false, - InJustDecodeBounds = false, - InPurgeable = true, - InInputShareable = true, - })) - { - var width = image.Width; - var height = image.Height; - - int[] pixels = new int[width * height]; - image.GetPixels(pixels, 0, width, 0, 0, width, height); - - // Convert from ARGB to ABGR - for (int i = 0; i < width * height; ++i) - { - uint pixel = (uint)pixels[i]; - pixels[i] = (int)((pixel & 0xFF00FF00) | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16)); - } - - this.SetData(pixels); - image.Recycle(); - } -#endif - } - - public void SaveAsJpeg(Stream stream, int width, int height) - { -#if WINDOWS_STOREAPP - SaveAsImage(BitmapEncoder.JpegEncoderId, stream, width, height); -#elif WINDOWS_PHONE - - var pixelData = new byte[Width * Height * GraphicsExtensions.Size(Format)]; - GetData(pixelData); - - var waitEvent = new ManualResetEventSlim(false); - Deployment.Current.Dispatcher.BeginInvoke(() => - { - var bitmap = new WriteableBitmap(width, height); - System.Buffer.BlockCopy(pixelData, 0, bitmap.Pixels, 0, pixelData.Length); - bitmap.SaveJpeg(stream, width, height, 0, 100); - waitEvent.Set(); - }); - - waitEvent.Wait(); -#elif MONOMAC - SaveAsImage(stream, width, height, ImageFormat.Jpeg); -#else - throw new NotImplementedException(); -#endif - } - - public void SaveAsPng(Stream stream, int width, int height) - { -#if WINDOWS_STOREAPP - SaveAsImage(BitmapEncoder.PngEncoderId, stream, width, height); -#elif MONOMAC - SaveAsImage(stream, width, height, ImageFormat.Png); -#else - // TODO: We need to find a simple stand alone - // PNG encoder if we want to support this. - throw new NotImplementedException(); -#endif - } - -#if MONOMAC - private void SaveAsImage(Stream stream, int width, int height, ImageFormat format) - { - if (stream == null) - { - throw new ArgumentNullException("stream", "'stream' cannot be null (Nothing in Visual Basic)"); - } - if (width <= 0) - { - throw new ArgumentOutOfRangeException("width", width, "'width' cannot be less than or equal to zero"); - } - if (height <= 0) - { - throw new ArgumentOutOfRangeException("height", height, "'height' cannot be less than or equal to zero"); - } - if (format == null) - { - throw new ArgumentNullException("format", "'format' cannot be null (Nothing in Visual Basic)"); - } - - byte[] data = null; - GCHandle? handle = null; - Bitmap bitmap = null; - try - { - data = new byte[width * height * 4]; - handle = GCHandle.Alloc(data, GCHandleType.Pinned); - GetData(data); - - // internal structure is BGR while bitmap expects RGB - for(int i = 0; i < data.Length; i += 4) - { - byte temp = data[i + 0]; - data[i + 0] = data[i + 2]; - data[i + 2] = temp; - } - - bitmap = new Bitmap(width, height, width * 4, System.Drawing.Imaging.PixelFormat.Format32bppArgb, handle.Value.AddrOfPinnedObject()); - - bitmap.Save(stream, format); - } - finally - { - if (bitmap != null) - { - bitmap.Dispose(); - } - if (handle.HasValue) - { - handle.Value.Free(); - } - if (data != null) - { - data = null; - } - } - } -#endif - -#if WINDOWS_STOREAPP - - private void SaveAsImage(Guid encoderId, Stream stream, int width, int height) - { - var pixelData = new byte[Width * Height * GraphicsExtensions.Size(Format)]; - GetData(pixelData); - - // TODO: We need to convert from Format to R8G8B8A8! - - // TODO: We should implement async SaveAsPng() for WinRT. - Task.Run(async () => - { - // Create a temporary memory stream for writing the png. - var memstream = new InMemoryRandomAccessStream(); - - // Write the png. - var encoder = await BitmapEncoder.CreateAsync(encoderId, memstream); - encoder.SetPixelData(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Ignore, (uint)width, (uint)height, 96, 96, pixelData); - await encoder.FlushAsync(); - - // Copy the memory stream into the real output stream. - memstream.Seek(0); - memstream.AsStreamForRead().CopyTo(stream); - - }).Wait(); - } - - public static SharpDX.Direct3D11.Texture2D CreateTex2DFromBitmap(SharpDX.WIC.BitmapSource bsource, GraphicsDevice device) - { - - SharpDX.Direct3D11.Texture2DDescription desc; - desc.Width = bsource.Size.Width; - desc.Height = bsource.Size.Height; - desc.ArraySize = 1; - desc.BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource; - desc.Usage = SharpDX.Direct3D11.ResourceUsage.Default; - desc.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None; - desc.Format = SharpDX.DXGI.Format.R8G8B8A8_UNorm; - desc.MipLevels = 1; - desc.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None; - desc.SampleDescription.Count = 1; - desc.SampleDescription.Quality = 0; - - SharpDX.Direct3D11.Texture2D dx11Texture; - - using(SharpDX.DataStream s = new SharpDX.DataStream(bsource.Size.Height * bsource.Size.Width * 4, true, true)) - { - bsource.CopyPixels(bsource.Size.Width * 4, s); - - SharpDX.DataRectangle rect = new SharpDX.DataRectangle(s.DataPointer, bsource.Size.Width * 4); - - dx11Texture = new SharpDX.Direct3D11.Texture2D(device._d3dDevice, desc, rect); - } - - return dx11Texture; - } - - static SharpDX.WIC.ImagingFactory imgfactory = null; - private static SharpDX.WIC.BitmapSource LoadBitmap(Stream stream, out SharpDX.WIC.BitmapDecoder decoder) - { - if (imgfactory == null) - { - imgfactory = new SharpDX.WIC.ImagingFactory(); - } - - SharpDX.WIC.FormatConverter fconv = null; - - decoder = new SharpDX.WIC.BitmapDecoder( - imgfactory, - stream, - SharpDX.WIC.DecodeOptions.CacheOnDemand - ); - - fconv = new SharpDX.WIC.FormatConverter(imgfactory); - - fconv.Initialize( - decoder.GetFrame(0), - SharpDX.WIC.PixelFormat.Format32bppPRGBA, - SharpDX.WIC.BitmapDitherType.None, null, - 0.0, SharpDX.WIC.BitmapPaletteType.Custom); - - return fconv; - } - - -#endif // WINRT - - // This method allows games that use Texture2D.FromStream - // to reload their textures after the GL context is lost. - internal void Reload(Stream textureStream) - { -#if OPENGL - GenerateGLTextureIfRequired(); - FillTextureFromStream(textureStream); -#endif - } - -#if OPENGL - private void GenerateGLTextureIfRequired() - { - if (this.glTexture < 0) - { -#if IOS || ANDROID - GL.GenTextures(1, ref this.glTexture); -#else - GL.GenTextures(1, out this.glTexture); -#endif - GraphicsExtensions.CheckGLError(); - - // For best compatibility and to keep the default wrap mode of XNA, only set ClampToEdge if either - // dimension is not a power of two. - var wrap = TextureWrapMode.Repeat; - if (((width & (width - 1)) != 0) || ((height & (height - 1)) != 0)) - wrap = TextureWrapMode.ClampToEdge; - - GL.BindTexture(TextureTarget.Texture2D, this.glTexture); - GraphicsExtensions.CheckGLError(); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, - (levelCount > 1) ? (int)TextureMinFilter.LinearMipmapLinear : (int)TextureMinFilter.Linear); - GraphicsExtensions.CheckGLError(); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, - (int)TextureMagFilter.Linear); - GraphicsExtensions.CheckGLError(); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)wrap); - GraphicsExtensions.CheckGLError(); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)wrap); - GraphicsExtensions.CheckGLError(); - } - } -#endif - -#if ANDROID - private byte[] GetTextureData(int ThreadPriorityLevel) - { - int framebufferId = -1; - int renderBufferID = -1; - - GL.GenFramebuffers(1, ref framebufferId); - GraphicsExtensions.CheckGLError(); - GL.BindFramebuffer(All.Framebuffer, framebufferId); - GraphicsExtensions.CheckGLError(); - //renderBufferIDs = new int[currentRenderTargets]; - GL.GenRenderbuffers(1, ref renderBufferID); - GraphicsExtensions.CheckGLError(); - - // attach the texture to FBO color attachment point - GL.FramebufferTexture2D(All.Framebuffer, All.ColorAttachment0, - All.Texture2D, this.glTexture, 0); - GraphicsExtensions.CheckGLError(); - - // create a renderbuffer object to store depth info - GL.BindRenderbuffer(All.Renderbuffer, renderBufferID); - GraphicsExtensions.CheckGLError(); - GL.RenderbufferStorage(All.Renderbuffer, All.DepthComponent24Oes, - Width, Height); - GraphicsExtensions.CheckGLError(); - - // attach the renderbuffer to depth attachment point - GL.FramebufferRenderbuffer(All.Framebuffer, All.DepthAttachment, - All.Renderbuffer, renderBufferID); - GraphicsExtensions.CheckGLError(); - - All status = GL.CheckFramebufferStatus(All.Framebuffer); - - if (status != All.FramebufferComplete) - throw new Exception("Error creating framebuffer: " + status); - byte[] imageInfo; - int sz = 0; - - switch (this.Format) - { - case SurfaceFormat.Color: //kTexture2DPixelFormat_RGBA8888 - case SurfaceFormat.Dxt3: - - sz = 4; - imageInfo = new byte[(Width * Height) * sz]; - break; - case SurfaceFormat.Bgra4444: //kTexture2DPixelFormat_RGBA4444 - sz = 2; - imageInfo = new byte[(Width * Height) * sz]; - - break; - case SurfaceFormat.Bgra5551: //kTexture2DPixelFormat_RGB5A1 - sz = 2; - imageInfo = new byte[(Width * Height) * sz]; - break; - case SurfaceFormat.Alpha8: // kTexture2DPixelFormat_A8 - sz = 1; - imageInfo = new byte[(Width * Height) * sz]; - break; - default: - throw new NotSupportedException("Texture format"); - } - - GL.ReadPixels(0,0,Width, Height, All.Rgba, All.UnsignedByte, imageInfo); - GraphicsExtensions.CheckGLError(); - GL.FramebufferRenderbuffer(All.Framebuffer, All.DepthAttachment, All.Renderbuffer, 0); - GraphicsExtensions.CheckGLError(); - GL.DeleteRenderbuffers(1, ref renderBufferID); - GraphicsExtensions.CheckGLError(); - GL.DeleteFramebuffers(1, ref framebufferId); - GraphicsExtensions.CheckGLError(); - GL.BindFramebuffer(All.Framebuffer, 0); - GraphicsExtensions.CheckGLError(); - return imageInfo; - } -#endif - } -} - + GL.BindTexture(TextureTarget.Texture2D, this.glTexture); + + if (rect.HasValue) { + throw new NotImplementedException(); + } + + if (glFormat == (GLPixelFormat)All.CompressedTextureFormats) { + throw new NotImplementedException(); + } else { + GL.GetTexImage(TextureTarget.Texture2D, level, this.glFormat, this.glType, data); + } + +#endif + } + + public void GetData(T[] data, int startIndex, int elementCount) where T : struct + { + this.GetData(0, null, data, startIndex, elementCount); + } + + public void GetData (T[] data) where T : struct + { + this.GetData(0, null, data, 0, data.Length); + } + + public static Texture2D FromStream(GraphicsDevice graphicsDevice, Stream stream) + { + //todo: partial classes would be cleaner +#if IOS || MONOMAC + + + +#if IOS + using (var uiImage = UIImage.LoadFromData(NSData.FromStream(stream))) +#elif MONOMAC + using (var nsImage = NSImage.FromStream (stream)) +#endif + { +#if IOS + var cgImage = uiImage.CGImage; +#elif MONOMAC + var cgImage = nsImage.AsCGImage (RectangleF.Empty, null, null); +#endif + + var width = cgImage.Width; + var height = cgImage.Height; + + var data = new byte[width * height * 4]; + + var colorSpace = CGColorSpace.CreateDeviceRGB(); + var bitmapContext = new CGBitmapContext(data, width, height, 8, width * 4, colorSpace, CGBitmapFlags.PremultipliedLast); + bitmapContext.DrawImage(new RectangleF(0, 0, width, height), cgImage); + bitmapContext.Dispose(); + colorSpace.Dispose(); + + Texture2D texture = null; + Threading.BlockOnUIThread(() => + { + texture = new Texture2D(graphicsDevice, width, height, false, SurfaceFormat.Color); + texture.SetData(data); + }); + + return texture; + } +#elif ANDROID + using (Bitmap image = BitmapFactory.DecodeStream(stream, null, new BitmapFactory.Options + { + InScaled = false, + InDither = false, + InJustDecodeBounds = false, + InPurgeable = true, + InInputShareable = true, + })) + { + var width = image.Width; + var height = image.Height; + + int[] pixels = new int[width * height]; + if ((width != image.Width) || (height != image.Height)) + { + using (Bitmap imagePadded = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888)) + { + Canvas canvas = new Canvas(imagePadded); + canvas.DrawARGB(0, 0, 0, 0); + canvas.DrawBitmap(image, 0, 0, null); + imagePadded.GetPixels(pixels, 0, width, 0, 0, width, height); + imagePadded.Recycle(); + } + } + else + { + image.GetPixels(pixels, 0, width, 0, 0, width, height); + } + image.Recycle(); + + // Convert from ARGB to ABGR + for (int i = 0; i < width * height; ++i) + { + uint pixel = (uint)pixels[i]; + pixels[i] = (int)((pixel & 0xFF00FF00) | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16)); + } + + Texture2D texture = null; + Threading.BlockOnUIThread(() => + { + texture = new Texture2D(graphicsDevice, width, height, false, SurfaceFormat.Color); + texture.SetData(pixels); + }); + + return texture; + } + +#elif WINDOWS_STOREAPP + + // For reference this implementation was ultimately found through this post: + // http://stackoverflow.com/questions/9602102/loading-textures-with-sharpdx-in-metro + Texture2D toReturn = null; + SharpDX.WIC.BitmapDecoder decoder; + + using(var bitmap = LoadBitmap(stream, out decoder)) + using (decoder) + { + SharpDX.Direct3D11.Texture2D sharpDxTexture = CreateTex2DFromBitmap(bitmap, graphicsDevice); + + toReturn = new Texture2D(graphicsDevice, bitmap.Size.Width, bitmap.Size.Height); + + toReturn._texture = sharpDxTexture; + } + return toReturn; +#elif DIRECTX + throw new NotImplementedException(); +#elif PSM + return new Texture2D(graphicsDevice, stream); +#else + using (Bitmap image = (Bitmap)Bitmap.FromStream(stream)) + { + // Fix up the Image to match the expected format + image.RGBToBGR(); + + var data = new byte[image.Width * image.Height * 4]; + + BitmapData bitmapData = image.LockBits(new System.Drawing.Rectangle(0, 0, image.Width, image.Height), + ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); + if (bitmapData.Stride != image.Width * 4) throw new NotImplementedException(); + Marshal.Copy(bitmapData.Scan0, data, 0, data.Length); + image.UnlockBits(bitmapData); + + Texture2D texture = null; + texture = new Texture2D(graphicsDevice, image.Width, image.Height); + texture.SetData(data); + + return texture; + } +#endif + } + + private void FillTextureFromStream(Stream stream) + { +#if ANDROID + using (Bitmap image = BitmapFactory.DecodeStream(stream, null, new BitmapFactory.Options + { + InScaled = false, + InDither = false, + InJustDecodeBounds = false, + InPurgeable = true, + InInputShareable = true, + })) + { + var width = image.Width; + var height = image.Height; + + int[] pixels = new int[width * height]; + image.GetPixels(pixels, 0, width, 0, 0, width, height); + + // Convert from ARGB to ABGR + for (int i = 0; i < width * height; ++i) + { + uint pixel = (uint)pixels[i]; + pixels[i] = (int)((pixel & 0xFF00FF00) | ((pixel & 0x00FF0000) >> 16) | ((pixel & 0x000000FF) << 16)); + } + + this.SetData(pixels); + image.Recycle(); + } +#endif + } + + public void SaveAsJpeg(Stream stream, int width, int height) + { +#if WINDOWS_STOREAPP + SaveAsImage(BitmapEncoder.JpegEncoderId, stream, width, height); +#elif WINDOWS_PHONE + + var pixelData = new byte[Width * Height * GraphicsExtensions.Size(Format)]; + GetData(pixelData); + + var waitEvent = new ManualResetEventSlim(false); + Deployment.Current.Dispatcher.BeginInvoke(() => + { + var bitmap = new WriteableBitmap(width, height); + System.Buffer.BlockCopy(pixelData, 0, bitmap.Pixels, 0, pixelData.Length); + bitmap.SaveJpeg(stream, width, height, 0, 100); + waitEvent.Set(); + }); + + waitEvent.Wait(); +#elif MONOMAC + SaveAsImage(stream, width, height, ImageFormat.Jpeg); +#else + throw new NotImplementedException(); +#endif + } + + public void SaveAsPng(Stream stream, int width, int height) + { +#if WINDOWS_STOREAPP + SaveAsImage(BitmapEncoder.PngEncoderId, stream, width, height); +#elif MONOMAC + SaveAsImage(stream, width, height, ImageFormat.Png); +#else + // TODO: We need to find a simple stand alone + // PNG encoder if we want to support this. + throw new NotImplementedException(); +#endif + } + +#if MONOMAC + private void SaveAsImage(Stream stream, int width, int height, ImageFormat format) + { + if (stream == null) + { + throw new ArgumentNullException("stream", "'stream' cannot be null (Nothing in Visual Basic)"); + } + if (width <= 0) + { + throw new ArgumentOutOfRangeException("width", width, "'width' cannot be less than or equal to zero"); + } + if (height <= 0) + { + throw new ArgumentOutOfRangeException("height", height, "'height' cannot be less than or equal to zero"); + } + if (format == null) + { + throw new ArgumentNullException("format", "'format' cannot be null (Nothing in Visual Basic)"); + } + + byte[] data = null; + GCHandle? handle = null; + Bitmap bitmap = null; + try + { + data = new byte[width * height * 4]; + handle = GCHandle.Alloc(data, GCHandleType.Pinned); + GetData(data); + + // internal structure is BGR while bitmap expects RGB + for(int i = 0; i < data.Length; i += 4) + { + byte temp = data[i + 0]; + data[i + 0] = data[i + 2]; + data[i + 2] = temp; + } + + bitmap = new Bitmap(width, height, width * 4, System.Drawing.Imaging.PixelFormat.Format32bppArgb, handle.Value.AddrOfPinnedObject()); + + bitmap.Save(stream, format); + } + finally + { + if (bitmap != null) + { + bitmap.Dispose(); + } + if (handle.HasValue) + { + handle.Value.Free(); + } + if (data != null) + { + data = null; + } + } + } +#endif + +#if WINDOWS_STOREAPP + + private void SaveAsImage(Guid encoderId, Stream stream, int width, int height) + { + var pixelData = new byte[Width * Height * GraphicsExtensions.Size(Format)]; + GetData(pixelData); + + // TODO: We need to convert from Format to R8G8B8A8! + + // TODO: We should implement async SaveAsPng() for WinRT. + Task.Run(async () => + { + // Create a temporary memory stream for writing the png. + var memstream = new InMemoryRandomAccessStream(); + + // Write the png. + var encoder = await BitmapEncoder.CreateAsync(encoderId, memstream); + encoder.SetPixelData(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Ignore, (uint)width, (uint)height, 96, 96, pixelData); + await encoder.FlushAsync(); + + // Copy the memory stream into the real output stream. + memstream.Seek(0); + memstream.AsStreamForRead().CopyTo(stream); + + }).Wait(); + } + + public static SharpDX.Direct3D11.Texture2D CreateTex2DFromBitmap(SharpDX.WIC.BitmapSource bsource, GraphicsDevice device) + { + + SharpDX.Direct3D11.Texture2DDescription desc; + desc.Width = bsource.Size.Width; + desc.Height = bsource.Size.Height; + desc.ArraySize = 1; + desc.BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource; + desc.Usage = SharpDX.Direct3D11.ResourceUsage.Default; + desc.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None; + desc.Format = SharpDX.DXGI.Format.R8G8B8A8_UNorm; + desc.MipLevels = 1; + desc.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None; + desc.SampleDescription.Count = 1; + desc.SampleDescription.Quality = 0; + + SharpDX.Direct3D11.Texture2D dx11Texture; + + using(SharpDX.DataStream s = new SharpDX.DataStream(bsource.Size.Height * bsource.Size.Width * 4, true, true)) + { + bsource.CopyPixels(bsource.Size.Width * 4, s); + + SharpDX.DataRectangle rect = new SharpDX.DataRectangle(s.DataPointer, bsource.Size.Width * 4); + + dx11Texture = new SharpDX.Direct3D11.Texture2D(device._d3dDevice, desc, rect); + } + + return dx11Texture; + } + + static SharpDX.WIC.ImagingFactory imgfactory = null; + private static SharpDX.WIC.BitmapSource LoadBitmap(Stream stream, out SharpDX.WIC.BitmapDecoder decoder) + { + if (imgfactory == null) + { + imgfactory = new SharpDX.WIC.ImagingFactory(); + } + + SharpDX.WIC.FormatConverter fconv = null; + + decoder = new SharpDX.WIC.BitmapDecoder( + imgfactory, + stream, + SharpDX.WIC.DecodeOptions.CacheOnDemand + ); + + fconv = new SharpDX.WIC.FormatConverter(imgfactory); + + fconv.Initialize( + decoder.GetFrame(0), + SharpDX.WIC.PixelFormat.Format32bppPRGBA, + SharpDX.WIC.BitmapDitherType.None, null, + 0.0, SharpDX.WIC.BitmapPaletteType.Custom); + + return fconv; + } + + +#endif // WINRT + + // This method allows games that use Texture2D.FromStream + // to reload their textures after the GL context is lost. + internal void Reload(Stream textureStream) + { +#if OPENGL + GenerateGLTextureIfRequired(); + FillTextureFromStream(textureStream); +#endif + } + +#if OPENGL + private void GenerateGLTextureIfRequired() + { + if (this.glTexture < 0) + { +#if IOS || ANDROID + GL.GenTextures(1, ref this.glTexture); +#else + GL.GenTextures(1, out this.glTexture); +#endif + GraphicsExtensions.CheckGLError(); + + // For best compatibility and to keep the default wrap mode of XNA, only set ClampToEdge if either + // dimension is not a power of two. + var wrap = TextureWrapMode.Repeat; + if (((width & (width - 1)) != 0) || ((height & (height - 1)) != 0)) + wrap = TextureWrapMode.ClampToEdge; + + GL.BindTexture(TextureTarget.Texture2D, this.glTexture); + GraphicsExtensions.CheckGLError(); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, + (levelCount > 1) ? (int)TextureMinFilter.LinearMipmapLinear : (int)TextureMinFilter.Linear); + GraphicsExtensions.CheckGLError(); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, + (int)TextureMagFilter.Linear); + GraphicsExtensions.CheckGLError(); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)wrap); + GraphicsExtensions.CheckGLError(); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)wrap); + GraphicsExtensions.CheckGLError(); + } + } +#endif + +#if ANDROID + private byte[] GetTextureData(int ThreadPriorityLevel) + { + int framebufferId = -1; + int renderBufferID = -1; + + GL.GenFramebuffers(1, ref framebufferId); + GraphicsExtensions.CheckGLError(); + GL.BindFramebuffer(All.Framebuffer, framebufferId); + GraphicsExtensions.CheckGLError(); + //renderBufferIDs = new int[currentRenderTargets]; + GL.GenRenderbuffers(1, ref renderBufferID); + GraphicsExtensions.CheckGLError(); + + // attach the texture to FBO color attachment point + GL.FramebufferTexture2D(All.Framebuffer, All.ColorAttachment0, + All.Texture2D, this.glTexture, 0); + GraphicsExtensions.CheckGLError(); + + // create a renderbuffer object to store depth info + GL.BindRenderbuffer(All.Renderbuffer, renderBufferID); + GraphicsExtensions.CheckGLError(); + GL.RenderbufferStorage(All.Renderbuffer, All.DepthComponent24Oes, + Width, Height); + GraphicsExtensions.CheckGLError(); + + // attach the renderbuffer to depth attachment point + GL.FramebufferRenderbuffer(All.Framebuffer, All.DepthAttachment, + All.Renderbuffer, renderBufferID); + GraphicsExtensions.CheckGLError(); + + All status = GL.CheckFramebufferStatus(All.Framebuffer); + + if (status != All.FramebufferComplete) + throw new Exception("Error creating framebuffer: " + status); + byte[] imageInfo; + int sz = 0; + + switch (this.Format) + { + case SurfaceFormat.Color: //kTexture2DPixelFormat_RGBA8888 + case SurfaceFormat.Dxt3: + + sz = 4; + imageInfo = new byte[(Width * Height) * sz]; + break; + case SurfaceFormat.Bgra4444: //kTexture2DPixelFormat_RGBA4444 + sz = 2; + imageInfo = new byte[(Width * Height) * sz]; + + break; + case SurfaceFormat.Bgra5551: //kTexture2DPixelFormat_RGB5A1 + sz = 2; + imageInfo = new byte[(Width * Height) * sz]; + break; + case SurfaceFormat.Alpha8: // kTexture2DPixelFormat_A8 + sz = 1; + imageInfo = new byte[(Width * Height) * sz]; + break; + default: + throw new NotSupportedException("Texture format"); + } + + GL.ReadPixels(0,0,Width, Height, All.Rgba, All.UnsignedByte, imageInfo); + GraphicsExtensions.CheckGLError(); + GL.FramebufferRenderbuffer(All.Framebuffer, All.DepthAttachment, All.Renderbuffer, 0); + GraphicsExtensions.CheckGLError(); + GL.DeleteRenderbuffers(1, ref renderBufferID); + GraphicsExtensions.CheckGLError(); + GL.DeleteFramebuffers(1, ref framebufferId); + GraphicsExtensions.CheckGLError(); + GL.BindFramebuffer(All.Framebuffer, 0); + GraphicsExtensions.CheckGLError(); + return imageInfo; + } +#endif + } +} + From 50c1b894503004cca0d490219e1e463ab40c84c3 Mon Sep 17 00:00:00 2001 From: John Weng Date: Sat, 12 Jul 2014 12:03:51 -0700 Subject: [PATCH 21/21] Disabled tracking of EveryPsmTextureEver. --- MonoGame.Framework/Graphics/Texture2D.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MonoGame.Framework/Graphics/Texture2D.cs b/MonoGame.Framework/Graphics/Texture2D.cs index 31d3bd4a455..d38b2e23f02 100644 --- a/MonoGame.Framework/Graphics/Texture2D.cs +++ b/MonoGame.Framework/Graphics/Texture2D.cs @@ -111,7 +111,7 @@ public class Texture2D : Texture #if PSM internal PssTexture2D _texture2D; - public static System.Collections.Generic.List EveryPsmTextureEver = new System.Collections.Generic.List(); + //public static System.Collections.Generic.List EveryPsmTextureEver = new System.Collections.Generic.List(); #elif OPENGL PixelInternalFormat glInternalFormat; GLPixelFormat glFormat; @@ -194,7 +194,7 @@ internal Texture2D(GraphicsDevice graphicsDevice, int width, int height, bool mi if (renderTarget) option = PixelBufferOption.Renderable; _texture2D = new Sce.PlayStation.Core.Graphics.Texture2D(width, height, mipmap, PSSHelper.ToFormat(format),option); - EveryPsmTextureEver.Add(this); // Add to texture tracker + //EveryPsmTextureEver.Add(this); // Add to texture tracker #else this.glTarget = TextureTarget.Texture2D;