Added thread-affinity checks to SDL2 renderer.
If a call is made into a graphics resource that has thread-affinity, from a thread other than the one that created the graphics device, an exception will now be thrown to make debugging easier.
This commit is contained in:
@@ -14,7 +14,7 @@ using OpenTK.Graphics.OpenGL;
|
|||||||
|
|
||||||
namespace OpenRA.Platforms.Default
|
namespace OpenRA.Platforms.Default
|
||||||
{
|
{
|
||||||
public static class ErrorHandler
|
static class ErrorHandler
|
||||||
{
|
{
|
||||||
public static void CheckGlVersion()
|
public static void CheckGlVersion()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ using OpenTK.Graphics.OpenGL;
|
|||||||
|
|
||||||
namespace OpenRA.Platforms.Default
|
namespace OpenRA.Platforms.Default
|
||||||
{
|
{
|
||||||
public sealed class FrameBuffer : IFrameBuffer
|
sealed class FrameBuffer : ThreadAffine, IFrameBuffer
|
||||||
{
|
{
|
||||||
Texture texture;
|
readonly Texture texture;
|
||||||
Size size;
|
readonly Size size;
|
||||||
int framebuffer, depth;
|
int framebuffer, depth;
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
@@ -83,6 +83,8 @@ namespace OpenRA.Platforms.Default
|
|||||||
int[] cv = new int[4];
|
int[] cv = new int[4];
|
||||||
public void Bind()
|
public void Bind()
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
|
|
||||||
// Cache viewport rect to restore when unbinding
|
// Cache viewport rect to restore when unbinding
|
||||||
cv = ViewportRectangle();
|
cv = ViewportRectangle();
|
||||||
|
|
||||||
@@ -100,6 +102,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void Unbind()
|
public void Unbind()
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
GL.Flush();
|
GL.Flush();
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);
|
GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);
|
||||||
@@ -108,7 +111,14 @@ namespace OpenRA.Platforms.Default
|
|||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ITexture Texture { get { return texture; } }
|
public ITexture Texture
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
~FrameBuffer()
|
~FrameBuffer()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ using OpenRA.Primitives;
|
|||||||
|
|
||||||
namespace OpenRA.Platforms.Default
|
namespace OpenRA.Platforms.Default
|
||||||
{
|
{
|
||||||
public static class MultiTapDetection
|
static class MultiTapDetection
|
||||||
{
|
{
|
||||||
static Cache<Keycode, TapHistory> keyHistoryCache =
|
static Cache<Keycode, TapHistory> keyHistoryCache =
|
||||||
new Cache<Keycode, TapHistory>(_ => new TapHistory(DateTime.Now - TimeSpan.FromSeconds(1)));
|
new Cache<Keycode, TapHistory>(_ => new TapHistory(DateTime.Now - TimeSpan.FromSeconds(1)));
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
<Compile Include="FrameBuffer.cs" />
|
<Compile Include="FrameBuffer.cs" />
|
||||||
<Compile Include="MultiTapDetection.cs" />
|
<Compile Include="MultiTapDetection.cs" />
|
||||||
<Compile Include="Texture.cs" />
|
<Compile Include="Texture.cs" />
|
||||||
|
<Compile Include="ThreadAffine.cs" />
|
||||||
<Compile Include="VertexBuffer.cs" />
|
<Compile Include="VertexBuffer.cs" />
|
||||||
<Compile Include="OpenAlSoundEngine.cs" />
|
<Compile Include="OpenAlSoundEngine.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ using System;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
using OpenRA;
|
using OpenRA;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
@@ -20,20 +21,18 @@ using SDL2;
|
|||||||
|
|
||||||
namespace OpenRA.Platforms.Default
|
namespace OpenRA.Platforms.Default
|
||||||
{
|
{
|
||||||
public sealed class Sdl2GraphicsDevice : IGraphicsDevice
|
sealed class Sdl2GraphicsDevice : ThreadAffine, IGraphicsDevice
|
||||||
{
|
{
|
||||||
Size size;
|
readonly Sdl2Input input;
|
||||||
Sdl2Input input;
|
|
||||||
IntPtr context, window;
|
IntPtr context, window;
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public Size WindowSize { get { return size; } }
|
public Size WindowSize { get; private set; }
|
||||||
|
|
||||||
public Sdl2GraphicsDevice(Size windowSize, WindowMode windowMode)
|
public Sdl2GraphicsDevice(Size windowSize, WindowMode windowMode)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Using SDL 2 with OpenGL renderer");
|
Console.WriteLine("Using SDL 2 with OpenGL renderer");
|
||||||
|
WindowSize = windowSize;
|
||||||
size = windowSize;
|
|
||||||
|
|
||||||
SDL.SDL_Init(SDL.SDL_INIT_NOPARACHUTE | SDL.SDL_INIT_VIDEO);
|
SDL.SDL_Init(SDL.SDL_INIT_NOPARACHUTE | SDL.SDL_INIT_VIDEO);
|
||||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_DOUBLEBUFFER, 1);
|
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_DOUBLEBUFFER, 1);
|
||||||
@@ -46,15 +45,16 @@ namespace OpenRA.Platforms.Default
|
|||||||
SDL.SDL_GetCurrentDisplayMode(0, out display);
|
SDL.SDL_GetCurrentDisplayMode(0, out display);
|
||||||
|
|
||||||
Console.WriteLine("Desktop resolution: {0}x{1}", display.w, display.h);
|
Console.WriteLine("Desktop resolution: {0}x{1}", display.w, display.h);
|
||||||
if (size.Width == 0 && size.Height == 0)
|
if (WindowSize.Width == 0 && WindowSize.Height == 0)
|
||||||
{
|
{
|
||||||
Console.WriteLine("No custom resolution provided, using desktop resolution");
|
Console.WriteLine("No custom resolution provided, using desktop resolution");
|
||||||
size = new Size(display.w, display.h);
|
WindowSize = new Size(display.w, display.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine("Using resolution: {0}x{1}", size.Width, size.Height);
|
Console.WriteLine("Using resolution: {0}x{1}", WindowSize.Width, WindowSize.Height);
|
||||||
|
|
||||||
window = SDL.SDL_CreateWindow("OpenRA", SDL.SDL_WINDOWPOS_CENTERED, SDL.SDL_WINDOWPOS_CENTERED, size.Width, size.Height, SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL);
|
window = SDL.SDL_CreateWindow("OpenRA", SDL.SDL_WINDOWPOS_CENTERED, SDL.SDL_WINDOWPOS_CENTERED,
|
||||||
|
WindowSize.Width, WindowSize.Height, SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL);
|
||||||
|
|
||||||
if (Game.Settings.Game.LockMouseWindow)
|
if (Game.Settings.Game.LockMouseWindow)
|
||||||
GrabWindowMouseFocus();
|
GrabWindowMouseFocus();
|
||||||
@@ -100,6 +100,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public IHardwareCursor CreateHardwareCursor(string name, Size size, byte[] data, int2 hotspot)
|
public IHardwareCursor CreateHardwareCursor(string name, Size size, byte[] data, int2 hotspot)
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new SDL2HardwareCursor(size, data, hotspot);
|
return new SDL2HardwareCursor(size, data, hotspot);
|
||||||
@@ -112,6 +113,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void SetHardwareCursor(IHardwareCursor cursor)
|
public void SetHardwareCursor(IHardwareCursor cursor)
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
var c = cursor as SDL2HardwareCursor;
|
var c = cursor as SDL2HardwareCursor;
|
||||||
if (c == null)
|
if (c == null)
|
||||||
SDL.SDL_ShowCursor((int)SDL.SDL_bool.SDL_FALSE);
|
SDL.SDL_ShowCursor((int)SDL.SDL_bool.SDL_FALSE);
|
||||||
@@ -214,12 +216,14 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void DrawPrimitives(PrimitiveType pt, int firstVertex, int numVertices)
|
public void DrawPrimitives(PrimitiveType pt, int firstVertex, int numVertices)
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
GL.DrawArrays(ModeFromPrimitiveType(pt), firstVertex, numVertices);
|
GL.DrawArrays(ModeFromPrimitiveType(pt), firstVertex, numVertices);
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
GL.ClearColor(0, 0, 0, 1);
|
GL.ClearColor(0, 0, 0, 1);
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
GL.Clear(ClearBufferMask.ColorBufferBit);
|
GL.Clear(ClearBufferMask.ColorBufferBit);
|
||||||
@@ -228,6 +232,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void EnableDepthBuffer()
|
public void EnableDepthBuffer()
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
GL.Clear(ClearBufferMask.DepthBufferBit);
|
GL.Clear(ClearBufferMask.DepthBufferBit);
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
GL.Enable(EnableCap.DepthTest);
|
GL.Enable(EnableCap.DepthTest);
|
||||||
@@ -236,12 +241,14 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void DisableDepthBuffer()
|
public void DisableDepthBuffer()
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
GL.Disable(EnableCap.DepthTest);
|
GL.Disable(EnableCap.DepthTest);
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBlendMode(BlendMode mode)
|
public void SetBlendMode(BlendMode mode)
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
GL.BlendEquation(BlendEquationMode.FuncAdd);
|
GL.BlendEquation(BlendEquationMode.FuncAdd);
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
|
|
||||||
@@ -290,23 +297,27 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void GrabWindowMouseFocus()
|
public void GrabWindowMouseFocus()
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
SDL.SDL_SetWindowGrab(window, SDL.SDL_bool.SDL_TRUE);
|
SDL.SDL_SetWindowGrab(window, SDL.SDL_bool.SDL_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReleaseWindowMouseFocus()
|
public void ReleaseWindowMouseFocus()
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
SDL.SDL_SetWindowGrab(window, SDL.SDL_bool.SDL_FALSE);
|
SDL.SDL_SetWindowGrab(window, SDL.SDL_bool.SDL_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnableScissor(int left, int top, int width, int height)
|
public void EnableScissor(int left, int top, int width, int height)
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
|
|
||||||
if (width < 0)
|
if (width < 0)
|
||||||
width = 0;
|
width = 0;
|
||||||
|
|
||||||
if (height < 0)
|
if (height < 0)
|
||||||
height = 0;
|
height = 0;
|
||||||
|
|
||||||
GL.Scissor(left, size.Height - (top + height), width, height);
|
GL.Scissor(left, WindowSize.Height - (top + height), width, height);
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
GL.Enable(EnableCap.ScissorTest);
|
GL.Enable(EnableCap.ScissorTest);
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
@@ -314,19 +325,21 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void DisableScissor()
|
public void DisableScissor()
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
GL.Disable(EnableCap.ScissorTest);
|
GL.Disable(EnableCap.ScissorTest);
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetLineWidth(float width)
|
public void SetLineWidth(float width)
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
GL.LineWidth(width);
|
GL.LineWidth(width);
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bitmap TakeScreenshot()
|
public Bitmap TakeScreenshot()
|
||||||
{
|
{
|
||||||
var rect = new Rectangle(Point.Empty, size);
|
var rect = new Rectangle(Point.Empty, WindowSize);
|
||||||
var bitmap = new Bitmap(rect.Width, rect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
var bitmap = new Bitmap(rect.Width, rect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||||
var data = bitmap.LockBits(rect,
|
var data = bitmap.LockBits(rect,
|
||||||
System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||||
@@ -349,13 +362,52 @@ namespace OpenRA.Platforms.Default
|
|||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Present() { SDL.SDL_GL_SwapWindow(window); }
|
public void Present()
|
||||||
public void PumpInput(IInputHandler inputHandler) { input.PumpInput(inputHandler); }
|
{
|
||||||
public string GetClipboardText() { return input.GetClipboardText(); }
|
VerifyThreadAffinity();
|
||||||
public IVertexBuffer<Vertex> CreateVertexBuffer(int size) { return new VertexBuffer<Vertex>(size); }
|
SDL.SDL_GL_SwapWindow(window);
|
||||||
public ITexture CreateTexture() { return new Texture(); }
|
}
|
||||||
public ITexture CreateTexture(Bitmap bitmap) { return new Texture(bitmap); }
|
|
||||||
public IFrameBuffer CreateFrameBuffer(Size s) { return new FrameBuffer(s); }
|
public void PumpInput(IInputHandler inputHandler)
|
||||||
public IShader CreateShader(string name) { return new Shader(name); }
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
|
input.PumpInput(inputHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetClipboardText()
|
||||||
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
|
return input.GetClipboardText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IVertexBuffer<Vertex> CreateVertexBuffer(int size)
|
||||||
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
|
return new VertexBuffer<Vertex>(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITexture CreateTexture()
|
||||||
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
|
return new Texture();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITexture CreateTexture(Bitmap bitmap)
|
||||||
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
|
return new Texture(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IFrameBuffer CreateFrameBuffer(Size s)
|
||||||
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
|
return new FrameBuffer(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IShader CreateShader(string name)
|
||||||
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
|
return new Shader(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ using SDL2;
|
|||||||
|
|
||||||
namespace OpenRA.Platforms.Default
|
namespace OpenRA.Platforms.Default
|
||||||
{
|
{
|
||||||
public class Sdl2Input
|
class Sdl2Input
|
||||||
{
|
{
|
||||||
MouseButton lastButtonBits = (MouseButton)0;
|
MouseButton lastButtonBits = (MouseButton)0;
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ using OpenTK.Graphics.OpenGL;
|
|||||||
|
|
||||||
namespace OpenRA.Platforms.Default
|
namespace OpenRA.Platforms.Default
|
||||||
{
|
{
|
||||||
public class Shader : IShader
|
class Shader : ThreadAffine, IShader
|
||||||
{
|
{
|
||||||
readonly Dictionary<string, int> samplers = new Dictionary<string, int>();
|
readonly Dictionary<string, int> samplers = new Dictionary<string, int>();
|
||||||
readonly Dictionary<int, ITexture> textures = new Dictionary<int, ITexture>();
|
readonly Dictionary<int, ITexture> textures = new Dictionary<int, ITexture>();
|
||||||
int program;
|
readonly int program;
|
||||||
|
|
||||||
protected int CompileShaderObject(ShaderType type, string name)
|
protected int CompileShaderObject(ShaderType type, string name)
|
||||||
{
|
{
|
||||||
@@ -122,6 +122,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void Render(Action a)
|
public void Render(Action a)
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
GL.UseProgram(program);
|
GL.UseProgram(program);
|
||||||
|
|
||||||
// bind the textures
|
// bind the textures
|
||||||
@@ -138,6 +139,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void SetTexture(string name, ITexture t)
|
public void SetTexture(string name, ITexture t)
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
if (t == null)
|
if (t == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -148,6 +150,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void SetVec(string name, float x)
|
public void SetVec(string name, float x)
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
GL.UseProgram(program);
|
GL.UseProgram(program);
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
var param = GL.GetUniformLocation(program, name);
|
var param = GL.GetUniformLocation(program, name);
|
||||||
@@ -158,6 +161,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void SetVec(string name, float x, float y)
|
public void SetVec(string name, float x, float y)
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
GL.UseProgram(program);
|
GL.UseProgram(program);
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
var param = GL.GetUniformLocation(program, name);
|
var param = GL.GetUniformLocation(program, name);
|
||||||
@@ -168,6 +172,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void SetVec(string name, float[] vec, int length)
|
public void SetVec(string name, float[] vec, int length)
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
var param = GL.GetUniformLocation(program, name);
|
var param = GL.GetUniformLocation(program, name);
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
switch (length)
|
switch (length)
|
||||||
@@ -184,6 +189,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void SetMatrix(string name, float[] mtx)
|
public void SetMatrix(string name, float[] mtx)
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
if (mtx.Length != 16)
|
if (mtx.Length != 16)
|
||||||
throw new InvalidDataException("Invalid 4x4 matrix");
|
throw new InvalidDataException("Invalid 4x4 matrix");
|
||||||
|
|
||||||
|
|||||||
@@ -16,15 +16,13 @@ using OpenTK.Graphics.OpenGL;
|
|||||||
|
|
||||||
namespace OpenRA.Platforms.Default
|
namespace OpenRA.Platforms.Default
|
||||||
{
|
{
|
||||||
public sealed class Texture : ITexture
|
sealed class Texture : ThreadAffine, ITexture
|
||||||
{
|
{
|
||||||
int texture;
|
int texture;
|
||||||
TextureScaleFilter scaleFilter;
|
TextureScaleFilter scaleFilter;
|
||||||
Size size;
|
|
||||||
|
|
||||||
public int ID { get { return texture; } }
|
public int ID { get { return texture; } }
|
||||||
|
public Size Size { get; private set; }
|
||||||
public Size Size { get { return size; } }
|
|
||||||
|
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
@@ -37,6 +35,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
if (scaleFilter == value)
|
if (scaleFilter == value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -83,10 +82,11 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void SetData(byte[] colors, int width, int height)
|
public void SetData(byte[] colors, int width, int height)
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
if (!Exts.IsPowerOf2(width) || !Exts.IsPowerOf2(height))
|
if (!Exts.IsPowerOf2(width) || !Exts.IsPowerOf2(height))
|
||||||
throw new InvalidDataException("Non-power-of-two array {0}x{1}".F(width, height));
|
throw new InvalidDataException("Non-power-of-two array {0}x{1}".F(width, height));
|
||||||
|
|
||||||
size = new Size(width, height);
|
Size = new Size(width, height);
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
fixed (byte* ptr = &colors[0])
|
fixed (byte* ptr = &colors[0])
|
||||||
@@ -103,13 +103,14 @@ namespace OpenRA.Platforms.Default
|
|||||||
// An array of RGBA
|
// An array of RGBA
|
||||||
public void SetData(uint[,] colors)
|
public void SetData(uint[,] colors)
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
var width = colors.GetUpperBound(1) + 1;
|
var width = colors.GetUpperBound(1) + 1;
|
||||||
var height = colors.GetUpperBound(0) + 1;
|
var height = colors.GetUpperBound(0) + 1;
|
||||||
|
|
||||||
if (!Exts.IsPowerOf2(width) || !Exts.IsPowerOf2(height))
|
if (!Exts.IsPowerOf2(width) || !Exts.IsPowerOf2(height))
|
||||||
throw new InvalidDataException("Non-power-of-two array {0}x{1}".F(width, height));
|
throw new InvalidDataException("Non-power-of-two array {0}x{1}".F(width, height));
|
||||||
|
|
||||||
size = new Size(width, height);
|
Size = new Size(width, height);
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
fixed (uint* ptr = &colors[0, 0])
|
fixed (uint* ptr = &colors[0, 0])
|
||||||
@@ -125,6 +126,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void SetData(Bitmap bitmap)
|
public void SetData(Bitmap bitmap)
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
var allocatedBitmap = false;
|
var allocatedBitmap = false;
|
||||||
if (!Exts.IsPowerOf2(bitmap.Width) || !Exts.IsPowerOf2(bitmap.Height))
|
if (!Exts.IsPowerOf2(bitmap.Width) || !Exts.IsPowerOf2(bitmap.Height))
|
||||||
{
|
{
|
||||||
@@ -134,7 +136,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
size = new Size(bitmap.Width, bitmap.Height);
|
Size = new Size(bitmap.Width, bitmap.Height);
|
||||||
var bits = bitmap.LockBits(bitmap.Bounds(),
|
var bits = bitmap.LockBits(bitmap.Bounds(),
|
||||||
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||||
|
|
||||||
@@ -153,7 +155,8 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public byte[] GetData()
|
public byte[] GetData()
|
||||||
{
|
{
|
||||||
var data = new byte[4 * size.Width * size.Height];
|
VerifyThreadAffinity();
|
||||||
|
var data = new byte[4 * Size.Width * Size.Height];
|
||||||
|
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
GL.BindTexture(TextureTarget.Texture2D, texture);
|
GL.BindTexture(TextureTarget.Texture2D, texture);
|
||||||
@@ -172,10 +175,11 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void SetEmpty(int width, int height)
|
public void SetEmpty(int width, int height)
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
if (!Exts.IsPowerOf2(width) || !Exts.IsPowerOf2(height))
|
if (!Exts.IsPowerOf2(width) || !Exts.IsPowerOf2(height))
|
||||||
throw new InvalidDataException("Non-power-of-two array {0}x{1}".F(width, height));
|
throw new InvalidDataException("Non-power-of-two array {0}x{1}".F(width, height));
|
||||||
|
|
||||||
size = new Size(width, height);
|
Size = new Size(width, height);
|
||||||
PrepareTexture();
|
PrepareTexture();
|
||||||
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, width, height,
|
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, width, height,
|
||||||
0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
|
0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
|
||||||
|
|||||||
31
OpenRA.Platforms.Default/ThreadAffine.cs
Normal file
31
OpenRA.Platforms.Default/ThreadAffine.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace OpenRA.Platforms.Default
|
||||||
|
{
|
||||||
|
abstract class ThreadAffine
|
||||||
|
{
|
||||||
|
readonly int managedThreadId;
|
||||||
|
|
||||||
|
protected ThreadAffine()
|
||||||
|
{
|
||||||
|
managedThreadId = Thread.CurrentThread.ManagedThreadId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void VerifyThreadAffinity()
|
||||||
|
{
|
||||||
|
if (managedThreadId != Thread.CurrentThread.ManagedThreadId)
|
||||||
|
throw new InvalidOperationException("Cross-thread operation not valid: This method must be called from the same thread that created this object.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ using OpenTK.Graphics.OpenGL;
|
|||||||
|
|
||||||
namespace OpenRA.Platforms.Default
|
namespace OpenRA.Platforms.Default
|
||||||
{
|
{
|
||||||
public sealed class VertexBuffer<T> : IVertexBuffer<T>
|
sealed class VertexBuffer<T> : ThreadAffine, IVertexBuffer<T>
|
||||||
where T : struct
|
where T : struct
|
||||||
{
|
{
|
||||||
static readonly int VertexSize = Marshal.SizeOf(typeof(T));
|
static readonly int VertexSize = Marshal.SizeOf(typeof(T));
|
||||||
@@ -60,6 +60,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public void Bind()
|
public void Bind()
|
||||||
{
|
{
|
||||||
|
VerifyThreadAffinity();
|
||||||
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
|
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
GL.VertexPointer(3, VertexPointerType.Float, VertexSize, IntPtr.Zero);
|
GL.VertexPointer(3, VertexPointerType.Float, VertexSize, IntPtr.Zero);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace OpenRA.Platforms.Null
|
|||||||
{
|
{
|
||||||
public sealed class NullGraphicsDevice : IGraphicsDevice
|
public sealed class NullGraphicsDevice : IGraphicsDevice
|
||||||
{
|
{
|
||||||
public Size WindowSize { get; internal set; }
|
public Size WindowSize { get; private set; }
|
||||||
|
|
||||||
public NullGraphicsDevice(Size size, WindowMode window)
|
public NullGraphicsDevice(Size size, WindowMode window)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user