Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'develop3d' of http://github.com/mono/MonoGame into deve…

…lop3d
  • Loading branch information...
commit 391a157c41983118c96b5e8d6e5cd0d1e98295a3 2 parents 6795526 + 2f94187
@danzel danzel authored
View
4 MonoGame.Framework/Android/AndroidGameActivity.cs
@@ -64,10 +64,6 @@ protected override void OnResume()
return;
(deviceManager as GraphicsDeviceManager).ForceSetFullScreen();
Game.Window.RequestFocus();
- if (Game.GraphicsDevice != null)
- {
- Game.GraphicsDevice.platform = Game.Platform;
- }
}
}
View
4 MonoGame.Framework/Android/AndroidGamePlatform.cs
@@ -161,8 +161,8 @@ public override bool BeforeRun()
// Get the Accelerometer going
Accelerometer.SetupAccelerometer();
- Window.Run(1.0 / Game.TargetElapsedTime.TotalSeconds);
- //Window.Pause();
+ // Run it as fast as we can to allow for more response on threaded GPU resource creation
+ Window.Run();
return false;
}
View
31 MonoGame.Framework/Android/AndroidGameWindow.cs
@@ -81,6 +81,8 @@ public class AndroidGameWindow : AndroidGameView , Android.Views.View.IOnTouchLi
double updateFrameLast;
double renderFrameLast;
public GraphicsContext BackgroundContext;
+ // Work-around for FrameEventArgs.Time being unusable as it is being modified by a background thread constantly
+ System.Diagnostics.Stopwatch frameTime = new System.Diagnostics.Stopwatch();
public AndroidGameWindow(Context context, Game game) : base(context)
{
@@ -153,9 +155,6 @@ public override bool OnKeyUp(Keycode keyCode, KeyEvent e)
protected override void CreateFrameBuffer()
{
- // Allow threaded resource loading
- OpenTK.Graphics.GraphicsContext.ShareContexts = true;
-
#if true
try
{
@@ -174,25 +173,13 @@ protected override void CreateFrameBuffer()
if (!GraphicsContext.IsCurrent)
MakeCurrent();
-
- // Create a context for the background loading
- GraphicsContextFlags flags = GraphicsContextFlags.Default;
-#if DEBUG
- //flags |= GraphicsContextFlags.Debug;
-#endif
- GraphicsMode mode = new GraphicsMode();
- BackgroundContext = new GraphicsContext(mode, WindowInfo, 2, 0, flags);
- Threading.BackgroundContext = BackgroundContext;
- Threading.WindowInfo = WindowInfo;
}
protected override void OnLoad(EventArgs e)
{
- // FIXME: Uncomment this line when moving to Mono for Android 4.0.5
- //MakeCurrent();
-
// Make sure an Update is called before a Draw
updateFrameElapsed = _game.TargetElapsedTime.TotalSeconds;
+ frameTime.Start();
base.OnLoad(e);
}
@@ -210,10 +197,13 @@ protected override void OnRenderFrame(FrameEventArgs e)
if (!GraphicsContext.IsCurrent)
MakeCurrent();
+ Threading.Run();
+
if (_game != null)
{
double targetElapsed = _game.TargetElapsedTime.TotalSeconds;
- renderFrameElapsed += e.Time;
+ //renderFrameElapsed += e.Time;
+ renderFrameElapsed = frameTime.Elapsed.TotalSeconds;
if (renderFrameElapsed < (renderFrameLast + targetElapsed))
return;
@@ -238,10 +228,13 @@ protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
- if (_game != null )
+ Threading.Run();
+
+ if (_game != null)
{
double targetElapsed = _game.TargetElapsedTime.TotalSeconds;
- updateFrameElapsed += e.Time;
+ //updateFrameElapsed += e.Time;
+ updateFrameElapsed = frameTime.Elapsed.TotalSeconds;
if (updateFrameElapsed < (updateFrameLast + targetElapsed))
return;
View
53 MonoGame.Framework/Content/ContentManager.cs
@@ -162,37 +162,45 @@ public virtual T Load<T>(string assetName)
}
T result = default(T);
- // Serialize access to loadedAssets with a lock
- lock (ContentManagerLock)
+
+ // Check for a previously loaded asset first
+ object asset = null;
+ if (loadedAssets.TryGetValue(assetName, out asset))
{
- // Check for a previously loaded asset first
- object asset = null;
- if (loadedAssets.TryGetValue(assetName, out asset))
+ if (asset is T)
{
- if (asset is T)
- {
- return (T)asset;
- }
+ return (T)asset;
}
+ }
- // Load the asset.
- result = ReadAsset<T>(assetName, null);
+ // Load the asset.
+ result = ReadAsset<T>(assetName, null);
- // Cache the result.
- if (!loadedAssets.ContainsKey(assetName))
- {
- loadedAssets.Add(assetName, result);
- }
+ // Cache the result.
+ if (!loadedAssets.ContainsKey(assetName))
+ {
+ loadedAssets.Add(assetName, result);
}
- return result;
+
+ return result;
}
protected virtual Stream OpenStream(string assetName)
{
Stream stream;
- try {
- string assetPath = Path.Combine (_rootDirectory, assetName)+".xnb";
+ try
+ {
+ string assetPath = Path.Combine(_rootDirectory, assetName) + ".xnb";
stream = TitleContainer.OpenStream(assetPath);
+#if ANDROID
+ // Read the asset into memory in one go. This results in a ~50% reduction
+ // in load times on Android due to slow Android asset streams.
+ MemoryStream memStream = new MemoryStream();
+ stream.CopyTo(memStream);
+ memStream.Seek(0, SeekOrigin.Begin);
+ stream.Close();
+ stream = memStream;
+#endif
}
catch (FileNotFoundException fileNotFound)
{
@@ -236,11 +244,14 @@ protected T ReadAsset<T>(string assetName, Action<IDisposable> recordDisposableO
Stream stream = null;
bool loadXnb = false;
- try {
+ try
+ {
//try load it traditionally
stream = OpenStream(assetName);
loadXnb = true;
- } catch (ContentLoadException) {
+ }
+ catch (ContentLoadException)
+ {
//MonoGame try to load as a non-content file
assetName = TitleContainer.GetFilename(Path.Combine (_rootDirectory, assetName));
View
19 MonoGame.Framework/Graphics/Effect/DXShader.cs
@@ -34,11 +34,11 @@ internal class DXShader
public readonly ShaderType ShaderType;
- public readonly int ShaderHandle;
+ public int ShaderHandle;
#if DEBUG
// We only keep around the GLSL code for debugging.
- private readonly string _glslCode;
+ private string _glslCode;
#endif
private struct Attribute
@@ -151,8 +151,7 @@ internal DXShader(GraphicsDevice device, BinaryReader reader)
}
- Threading.Begin();
- try
+ Threading.BlockOnUIThread(() =>
{
ShaderHandle = GL.CreateShader(ShaderType);
#if GLES
@@ -193,16 +192,12 @@ internal DXShader(GraphicsDevice device, BinaryReader reader)
GL.DeleteShader(ShaderHandle);
throw new InvalidOperationException("Shader Compilation Failed");
}
- }
- finally
- {
- Threading.End();
- }
+ });
#endif // OPENGL
}
-#if OPENGL
+#if OPENGL
public void OnLink(int program)
{
@@ -237,7 +232,7 @@ public void OnLink(int program)
}
}
}
-
+
public void Apply( GraphicsDevice graphicsDevice,
int program,
@@ -284,7 +279,7 @@ public void OnLink(int program)
tex.Activate();
samplerStates[sampler.index].Activate(tex.glTarget, tex.LevelCount > 1);
}
- }
+ }
// Update and set the constants.
for (var c = 0; c < _cbuffers.Length; c++)
View
9 MonoGame.Framework/Graphics/Effect/EffectPass.cs
@@ -104,8 +104,7 @@ internal EffectPass(Effect effect, EffectPass cloneSource)
private void Initialize()
{
#if OPENGL
- Threading.Begin();
- try
+ Threading.BlockOnUIThread(() =>
{
// TODO: Shouldn't we be calling GL.DeleteProgram() somewhere?
@@ -136,11 +135,7 @@ private void Initialize()
#endif
throw new InvalidOperationException("Unable to link effect program");
}
- }
- finally
- {
- Threading.End();
- }
+ });
#elif DIRECTX
View
6 MonoGame.Framework/Graphics/GraphicsDevice.cs
@@ -143,10 +143,6 @@ public class GraphicsDevice : IDisposable
#endif // DIRECTX
-#if ANDROID
- internal GamePlatform platform;
-#endif
-
#if OPENGL
// OpenGL ES2.0 attribute locations
@@ -782,7 +778,7 @@ public void Present()
#elif PSS
_graphics.SwapBuffers();
#elif ANDROID
- platform.Present();
+ Game.Instance.Platform.Present();
#elif OPENGL
GL.Flush ();
#endif
View
51 MonoGame.Framework/Graphics/Texture2D.cs
@@ -142,8 +142,7 @@ public Texture2D(GraphicsDevice graphicsDevice, int width, int height, bool mipm
this.glTarget = TextureTarget.Texture2D;
- Threading.Begin();
- try
+ Threading.BlockOnUIThread(() =>
{
#if IPHONE || ANDROID
GL.GenTextures(1, ref this.glTexture);
@@ -223,11 +222,7 @@ public Texture2D(GraphicsDevice graphicsDevice, int width, int height, bool mipm
this.levelCount++;
}
}
- }
- finally
- {
- Threading.End();
- }
+ });
#endif
}
@@ -270,10 +265,8 @@ public int Height
if (data == null)
throw new ArgumentNullException("data");
-#if !DIRECTX
- // WTF is this? Document your code people!
- Threading.Begin();
- try
+#if OPENGL
+ Threading.BlockOnUIThread(() =>
{
#endif
#if !PSS
@@ -340,12 +333,8 @@ public int Height
dataHandle.Free();
#endif
-#if !DIRECTX
- }
- finally
- {
- Threading.End();
- }
+#if OPENGL
+ });
#endif
}
@@ -426,16 +415,11 @@ public static Texture2D FromStream(GraphicsDevice graphicsDevice, Stream stream)
colorSpace.Dispose();
Texture2D texture = null;
- Threading.Begin();
- try
+ Threading.BlockOnUIThread(() =>
{
texture = new Texture2D(graphicsDevice, width, height, false, SurfaceFormat.Color);
texture.SetData(data);
- }
- finally
- {
- Threading.End();
- }
+ });
return texture;
}
@@ -474,16 +458,12 @@ public static Texture2D FromStream(GraphicsDevice graphicsDevice, Stream stream)
}
Texture2D texture = null;
- Threading.Begin();
- try
+ Threading.BlockOnUIThread(() =>
{
texture = new Texture2D(graphicsDevice, width, height, false, SurfaceFormat.Color);
texture.SetData<int>(pixels);
- }
- finally
- {
- Threading.End();
- }
+ });
+
return texture;
#elif DIRECTX
@@ -505,16 +485,11 @@ public static Texture2D FromStream(GraphicsDevice graphicsDevice, Stream stream)
image.UnlockBits(bitmapData);
Texture2D texture = null;
- Threading.Begin();
- try
+ Threading.BlockOnUIThread(() =>
{
texture = new Texture2D(graphicsDevice, image.Width, image.Height);
texture.SetData(data);
- }
- finally
- {
- Threading.End();
- }
+ });
return texture;
}
View
27 MonoGame.Framework/Graphics/Vertices/IndexBuffer.cs
@@ -80,8 +80,7 @@ protected IndexBuffer(GraphicsDevice graphicsDevice, IndexElementSize indexEleme
#elif PSS
_buffer = new PssVertexBuffer(0, indexCount);
#else
- Threading.Begin();
- try
+ Threading.BlockOnUIThread(() =>
{
#if IPHONE || ANDROID
GL.GenBuffers(1, ref ibo);
@@ -91,11 +90,7 @@ protected IndexBuffer(GraphicsDevice graphicsDevice, IndexElementSize indexEleme
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo);
GL.BufferData(BufferTarget.ElementArrayBuffer,
(IntPtr)sizeInBytes, IntPtr.Zero, dynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw);
- }
- finally
- {
- Threading.End();
- }
+ });
#endif
}
@@ -125,8 +120,7 @@ protected IndexBuffer(GraphicsDevice graphicsDevice, IndexElementSize indexEleme
#elif PSS
throw new NotImplementedException();
#else
- Threading.Begin();
- try
+ Threading.BlockOnUIThread(() =>
{
GL.BindBuffer(BufferTarget.ArrayBuffer, ibo);
var elementSizeInByte = Marshal.SizeOf(typeof(T));
@@ -158,11 +152,7 @@ protected IndexBuffer(GraphicsDevice graphicsDevice, IndexElementSize indexEleme
#else
GL.UnmapBuffer(BufferTarget.ArrayBuffer);
#endif
- }
- finally
- {
- Threading.End();
- }
+ });
#endif
}
@@ -254,8 +244,7 @@ protected IndexBuffer(GraphicsDevice graphicsDevice, IndexElementSize indexEleme
_buffer.SetIndices(clone, 0, 0, elementCount);
}
#else
- Threading.Begin();
- try
+ Threading.BlockOnUIThread(() =>
{
var elementSizeInByte = Marshal.SizeOf(typeof(T));
var sizeInBytes = elementSizeInByte * elementCount;
@@ -266,11 +255,7 @@ protected IndexBuffer(GraphicsDevice graphicsDevice, IndexElementSize indexEleme
GL.BufferSubData(BufferTarget.ElementArrayBuffer, (IntPtr)offsetInBytes, (IntPtr)sizeInBytes, dataPtr);
dataHandle.Free();
- }
- finally
- {
- Threading.End();
- }
+ });
#endif
}
View
27 MonoGame.Framework/Graphics/Vertices/VertexBuffer.cs
@@ -80,8 +80,7 @@ protected VertexBuffer(GraphicsDevice graphicsDevice, VertexDeclaration vertexDe
VertexFormat[] vertexFormat = vertexDeclaration.GetVertexFormat();
_buffer = new PssVertexBuffer(vertexCount, vertexFormat);
#else
- Threading.Begin();
- try
+ Threading.BlockOnUIThread(() =>
{
//GLExt.Oes.GenVertexArrays(1, out this.vao);
//GLExt.Oes.BindVertexArray(this.vao);
@@ -94,11 +93,7 @@ protected VertexBuffer(GraphicsDevice graphicsDevice, VertexDeclaration vertexDe
GL.BufferData(BufferTarget.ArrayBuffer,
new IntPtr(vertexDeclaration.VertexStride * vertexCount), IntPtr.Zero,
dynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw);
- }
- finally
- {
- Threading.End();
- }
+ });
#endif
}
@@ -128,8 +123,7 @@ protected VertexBuffer(GraphicsDevice graphicsDevice, VertexDeclaration vertexDe
#elif PSS
throw new NotImplementedException();
#else
- Threading.Begin();
- try
+ Threading.BlockOnUIThread(() =>
{
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
var elementSizeInByte = Marshal.SizeOf(typeof(T));
@@ -163,11 +157,7 @@ protected VertexBuffer(GraphicsDevice graphicsDevice, VertexDeclaration vertexDe
#else
GL.UnmapBuffer(BufferTarget.ArrayBuffer);
#endif
- }
- finally
- {
- Threading.End();
- }
+ });
#endif
}
@@ -255,17 +245,12 @@ protected VertexBuffer(GraphicsDevice graphicsDevice, VertexDeclaration vertexDe
#elif PSS
_buffer.SetVertices(data, offsetInBytes, startIndex, elementCount);
#else
- Threading.Begin();
- try
+ Threading.BlockOnUIThread(() =>
{
var sizeInBytes = elementSizeInBytes * elementCount;
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
GL.BufferSubData<T>(BufferTarget.ArrayBuffer, new IntPtr(offsetInBytes), new IntPtr(sizeInBytes), data);
- }
- finally
- {
- Threading.End();
- }
+ });
#endif
}
View
93 MonoGame.Framework/Threading.cs
@@ -41,62 +41,101 @@ 1. Definitions
using System;
using System.Collections.Generic;
using System.Threading;
-#if ANDROID
-using OpenTK.Graphics;
-using OpenTK.Platform;
-#endif
#if IPHONE
using MonoTouch.Foundation;
using MonoTouch.OpenGLES;
+#if ES11
+using OpenTK.Graphics.ES11;
+#else
using OpenTK.Graphics.ES20;
#endif
+#endif
namespace Microsoft.Xna.Framework
{
internal class Threading
{
static int mainThreadId;
-#if IPHONE
- public static EAGLContext BackgroundContext;
-#elif ANDROID
- public static GraphicsContext BackgroundContext;
- public static IWindowInfo WindowInfo;
+#if ANDROID || LINUX || WINDOWS
+ static List<Action> actions = new List<Action>();
+ static Mutex actionsMutex = new Mutex();
+#elif IPHONE
+ public static EAGLContext BackgroundContext;
#endif
- static Mutex contextMutex = new Mutex();
-
static Threading()
{
mainThreadId = Thread.CurrentThread.ManagedThreadId;
}
/// <summary>
- /// To be called prior to any GL calls that may happen on a secondary thread. If called on a A shared context
+ /// Runs the given action on the UI thread and blocks the current thread while the action is running.
+ /// If the current thread is the UI thread, the action will run immediately.
/// </summary>
- internal static void Begin()
+ /// <param name="action">The action to be run on the UI thread</param>
+ internal static void BlockOnUIThread(Action action)
{
- if (mainThreadId != Thread.CurrentThread.ManagedThreadId)
+ if (action == null)
+ throw new ArgumentNullException("action cannot be null");
+
+#if DIRECTX
+ action();
+#else
+ // If we are already on the UI thread, just call the action and be done with it
+ if (mainThreadId == Thread.CurrentThread.ManagedThreadId)
{
- contextMutex.WaitOne();
+ action();
+ return;
+ }
+
#if IPHONE
- if (EAGLContext.CurrentContext != BackgroundContext)
- EAGLContext.SetCurrentContext(BackgroundContext);
-#elif ANDROID
- // FIXME: To be implemented
- throw new NotImplementedException("Threaded creation of GPU resources is not currently supported on Android");
+ lock (BackgroundContext)
+ {
+ if (EAGLContext.CurrentContext != BackgroundContext)
+ EAGLContext.SetCurrentContext(BackgroundContext);
+ action();
+ }
#else
- // FIXME: To be implemented
- throw new NotImplementedException("Threaded creation of GPU resources is not currently supported on this platform");
+ System.Threading.ManualResetEventSlim resetEvent = new System.Threading.ManualResetEventSlim(false);
+#if MONOMAC
+ MonoMac.AppKit.NSApplication.SharedApplication.BeginInvokeOnMainThread(() =>
+#else
+ Add(() =>
+#endif
+ {
+ if (!Game.Instance.Window.GraphicsContext.IsCurrent)
+ Game.Instance.Window.MakeCurrent();
+ action();
+ resetEvent.Set();
+ });
+ resetEvent.Wait();
#endif
+#endif
+ }
+
+#if ANDROID || LINUX || WINDOWS
+ static void Add(Action action)
+ {
+ lock (actions)
+ {
+ actions.Add(action);
}
}
/// <summary>
- /// To be called after the GL calls that may happen on a secondary thread.
+ /// Runs all pending actions. Must be called from the UI thread.
/// </summary>
- internal static void End()
+ internal static void Run()
{
- if (mainThreadId != Thread.CurrentThread.ManagedThreadId)
- contextMutex.ReleaseMutex();
+ System.Diagnostics.Debug.Assert(mainThreadId == Thread.CurrentThread.ManagedThreadId, "Threading.Run must be called from the UI thread");
+ lock (actions)
+ {
+ foreach (Action action in actions)
+ {
+ action();
+ }
+ actions.Clear();
+ }
}
+#endif
}
-}
+}
Please sign in to comment.
Something went wrong with that request. Please try again.