From e6120238c7aa4cf8a7e3d671d0816c1247eb491f Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 17 Feb 2010 19:52:54 +1300 Subject: [PATCH 1/6] inverting the Engine <-> GL project dependency. --- .gitignore | 2 + .../Graphics/IGraphicsDevice.cs | 80 +++++++++++ OpenRa.FileFormats/OpenRa.FileFormats.csproj | 1 + OpenRa.Game/Graphics/LineRenderer.cs | 10 +- OpenRa.Game/Graphics/Renderer.cs | 53 +++++--- OpenRa.Game/Graphics/Sheet.cs | 8 +- OpenRa.Game/Graphics/SpriteRenderer.cs | 18 +-- OpenRa.Game/Graphics/TerrainRenderer.cs | 11 +- OpenRa.Game/Graphics/Vertex.cs | 3 - OpenRa.Game/OpenRa.Game.csproj | 4 - OpenRa.Gl/GraphicsDevice.cs | 126 ++++++++++-------- OpenRa.Gl/OpenRa.Gl.csproj | 9 ++ 12 files changed, 214 insertions(+), 111 deletions(-) create mode 100755 OpenRa.FileFormats/Graphics/IGraphicsDevice.cs diff --git a/.gitignore b/.gitignore index c96b870526..7ea2b993b6 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,5 @@ log.txt cg.dll cgGL.dll glfw.dll + +/OpenRa.Gl.dll \ No newline at end of file diff --git a/OpenRa.FileFormats/Graphics/IGraphicsDevice.cs b/OpenRa.FileFormats/Graphics/IGraphicsDevice.cs new file mode 100755 index 0000000000..4936b1947e --- /dev/null +++ b/OpenRa.FileFormats/Graphics/IGraphicsDevice.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Drawing; +using System.IO; + +namespace OpenRa.FileFormats.Graphics +{ + [AttributeUsage( AttributeTargets.Assembly )] + public class RendererAttribute : Attribute + { + public readonly Type Type; + + public RendererAttribute( Type graphicsDeviceType ) + { + if( !typeof( IGraphicsDevice ).IsAssignableFrom( graphicsDeviceType ) ) + throw new InvalidOperationException( "Incorrect type in RendererAttribute" ); + Type = graphicsDeviceType; + } + } + + public interface IGraphicsDevice + { + IVertexBuffer CreateVertexBuffer( int length ) where T : struct; + IIndexBuffer CreateIndexBuffer( int length ); + ITexture CreateTexture( Bitmap bitmap ); + + IShader CreateShader( Stream stream ); + + void Begin(); + void End(); + void Clear( Color color ); + void Present(); + + void DrawIndexedPrimitives( PrimitiveType type, Range vertexRange, Range indexRange ); + void DrawIndexedPrimitives( PrimitiveType type, int vertexPool, int numPrimitives ); + + void EnableScissor( int left, int top, int width, int height ); + void DisableScissor(); + } + + public interface IVertexBuffer + { + void Bind(); + void SetData( T[] vertices ); + } + + public interface IIndexBuffer + { + void Bind(); + void SetData( ushort[] indices ); + } + + public interface IShader + { + void SetValue( string name, float x, float y ); + void SetValue( string param, ITexture texture ); + void Commit(); + void Render( Action a ); + } + + public interface ITexture + { + void SetData( Bitmap bitmap ); + } + + public enum PrimitiveType + { + PointList, + LineList, + TriangleList, + } + + public struct Range + { + public readonly T Start, End; + public Range( T start, T end ) { Start = start; End = end; } + } +} diff --git a/OpenRa.FileFormats/OpenRa.FileFormats.csproj b/OpenRa.FileFormats/OpenRa.FileFormats.csproj index e3e81c355f..d631870623 100644 --- a/OpenRa.FileFormats/OpenRa.FileFormats.csproj +++ b/OpenRa.FileFormats/OpenRa.FileFormats.csproj @@ -59,6 +59,7 @@ + diff --git a/OpenRa.Game/Graphics/LineRenderer.cs b/OpenRa.Game/Graphics/LineRenderer.cs index fe50b4c5c1..2be4f0d9a3 100644 --- a/OpenRa.Game/Graphics/LineRenderer.cs +++ b/OpenRa.Game/Graphics/LineRenderer.cs @@ -19,15 +19,15 @@ #endregion using System.Drawing; -using OpenRa.GlRenderer; +using OpenRa.FileFormats.Graphics; namespace OpenRa.Graphics { class LineRenderer { Renderer renderer; - VertexBuffer vertexBuffer; - IndexBuffer indexBuffer; /* kindof a waste of space, but the GPU likes indexing, oh well */ + IVertexBuffer vertexBuffer; + IIndexBuffer indexBuffer; /* kindof a waste of space, but the GPU likes indexing, oh well */ const int linesPerBatch = 1024; @@ -39,8 +39,8 @@ namespace OpenRa.Graphics public LineRenderer( Renderer renderer ) { this.renderer = renderer; - vertexBuffer = new VertexBuffer( renderer.Device, vertices.Length, Vertex.Format ); - indexBuffer = new IndexBuffer( renderer.Device, indices.Length ); + vertexBuffer = renderer.Device.CreateVertexBuffer(vertices.Length ); + indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length ); } public void Flush() diff --git a/OpenRa.Game/Graphics/Renderer.cs b/OpenRa.Game/Graphics/Renderer.cs index 7968a5f927..f59f505582 100644 --- a/OpenRa.Game/Graphics/Renderer.cs +++ b/OpenRa.Game/Graphics/Renderer.cs @@ -18,12 +18,15 @@ */ #endregion +using System; using System.Drawing; using System.Drawing.Text; +using System.Reflection; using System.Windows.Forms; using OpenRa.FileFormats; -using OpenRa.GlRenderer; +using OpenRa.FileFormats.Graphics; using OpenRa.Support; +using System.IO; namespace OpenRa.Graphics { @@ -31,14 +34,14 @@ namespace OpenRa.Graphics { internal static int SheetSize; - readonly GraphicsDevice device; + readonly IGraphicsDevice device; - public Shader SpriteShader { get; private set; } /* note: shared shader params */ - public Shader LineShader { get; private set; } - public Shader RgbaSpriteShader { get; private set; } - public Shader WorldSpriteShader { get; private set; } + public IShader SpriteShader { get; private set; } /* note: shared shader params */ + public IShader LineShader { get; private set; } + public IShader RgbaSpriteShader { get; private set; } + public IShader WorldSpriteShader { get; private set; } - public Texture PaletteTexture; + public ITexture PaletteTexture; readonly Font fDebug, fTitle; @@ -49,16 +52,12 @@ namespace OpenRa.Graphics public Renderer(Control control, Size resolution, bool windowed) { control.ClientSize = resolution; - device = new GraphicsDevice(control, resolution.Width, resolution.Height, windowed, false); + device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( "OpenRa.Gl.dll" ) ), control, resolution.Width, resolution.Height, windowed, false ); - SpriteShader = new Shader(device, FileSystem.Open("world-shp.fx")); - SpriteShader.Quality = ShaderQuality.Low; - LineShader = new Shader(device, FileSystem.Open("line.fx")); - LineShader.Quality = ShaderQuality.High; - RgbaSpriteShader = new Shader(device, FileSystem.Open("chrome-rgba.fx")); - RgbaSpriteShader.Quality = ShaderQuality.High; - WorldSpriteShader = new Shader(device, FileSystem.Open("chrome-shp.fx")); - WorldSpriteShader.Quality = ShaderQuality.High; + SpriteShader = device.CreateShader(FileSystem.Open("world-shp.fx")); + LineShader = device.CreateShader(FileSystem.Open("line.fx")); + RgbaSpriteShader = device.CreateShader(FileSystem.Open("chrome-rgba.fx")); + WorldSpriteShader = device.CreateShader(FileSystem.Open("chrome-shp.fx")); fDebug = new Font("Tahoma", 10, FontStyle.Regular); fTitle = new Font("Tahoma", 10, FontStyle.Bold); @@ -67,6 +66,16 @@ namespace OpenRa.Graphics textSprite = new Sprite(textSheet, new Rectangle(0, 0, 256, 256), TextureChannel.Alpha); } + IGraphicsDevice CreateDevice( Assembly rendererDll, Control control, int width, int height, bool fullscreen, bool vsync ) + { + foreach( RendererAttribute r in rendererDll.GetCustomAttributes( typeof( RendererAttribute ), false ) ) + { + return (IGraphicsDevice)r.Type.GetConstructor( new Type[] { typeof( Control ), typeof( int ), typeof( int ), typeof( bool ), typeof( bool ) } ) + .Invoke( new object[] { control, width, height, fullscreen, vsync } ); + } + throw new NotImplementedException(); + } + Bitmap RenderTextToBitmap(string s, Font f, Color c) { Bitmap b = new Bitmap(256, 256); @@ -86,7 +95,7 @@ namespace OpenRa.Graphics return new int2(g.MeasureString(s, f).ToSize()); } - public GraphicsDevice Device { get { return device; } } + public IGraphicsDevice Device { get { return device; } } public void BeginFrame(float2 r1, float2 r2, float2 scroll) { @@ -99,7 +108,7 @@ namespace OpenRa.Graphics SetShaderParams( WorldSpriteShader, r1, r2, scroll ); } - private void SetShaderParams( Shader s, float2 r1, float2 r2, float2 scroll ) + private void SetShaderParams( IShader s, float2 r1, float2 r2, float2 scroll ) { s.SetValue( "Palette", PaletteTexture ); s.SetValue( "Scroll", scroll.X, scroll.Y ); @@ -114,8 +123,8 @@ namespace OpenRa.Graphics device.Present(); } - public void DrawBatch(VertexBuffer vertices, IndexBuffer indices, - Range vertexRange, Range indexRange, Texture texture, PrimitiveType type, Shader shader) + public void DrawBatch(IVertexBuffer vertices, IIndexBuffer indices, + Range vertexRange, Range indexRange, ITexture texture, PrimitiveType type, IShader shader) where T : struct { shader.SetValue("DiffuseTexture", texture); @@ -129,8 +138,8 @@ namespace OpenRa.Graphics PerfHistory.Increment("batches", 1); } - public void DrawBatch(VertexBuffer vertices, IndexBuffer indices, - int vertexPool, int numPrimitives, Texture texture, PrimitiveType type) + public void DrawBatch(IVertexBuffer vertices, IIndexBuffer indices, + int vertexPool, int numPrimitives, ITexture texture, PrimitiveType type) where T : struct { SpriteShader.SetValue("DiffuseTexture", texture); diff --git a/OpenRa.Game/Graphics/Sheet.cs b/OpenRa.Game/Graphics/Sheet.cs index 9f75828d21..6feb2bd0aa 100644 --- a/OpenRa.Game/Graphics/Sheet.cs +++ b/OpenRa.Game/Graphics/Sheet.cs @@ -20,7 +20,7 @@ using System.Drawing; using OpenRa.FileFormats; -using OpenRa.GlRenderer; +using OpenRa.FileFormats.Graphics; namespace OpenRa.Graphics { @@ -29,7 +29,7 @@ namespace OpenRa.Graphics readonly Renderer renderer; protected readonly Bitmap bitmap; - Texture texture; + ITexture texture; internal Sheet(Renderer renderer, Size size) { @@ -45,10 +45,10 @@ namespace OpenRa.Graphics void Resolve() { - texture = new Texture(renderer.Device, bitmap); + texture = renderer.Device.CreateTexture(bitmap); } - public Texture Texture + public ITexture Texture { get { diff --git a/OpenRa.Game/Graphics/SpriteRenderer.cs b/OpenRa.Game/Graphics/SpriteRenderer.cs index 0e74184ef3..4550f52753 100644 --- a/OpenRa.Game/Graphics/SpriteRenderer.cs +++ b/OpenRa.Game/Graphics/SpriteRenderer.cs @@ -18,16 +18,16 @@ */ #endregion -using OpenRa.GlRenderer; +using OpenRa.FileFormats.Graphics; namespace OpenRa.Graphics { class SpriteRenderer { - VertexBuffer vertexBuffer; - IndexBuffer indexBuffer; + IVertexBuffer vertexBuffer; + IIndexBuffer indexBuffer; Renderer renderer; - Shader shader; + IShader shader; const int spritesPerBatch = 1024; @@ -35,18 +35,15 @@ namespace OpenRa.Graphics ushort[] indices = new ushort[6 * spritesPerBatch]; Sheet currentSheet = null; int sprites = 0; - ShaderQuality quality; int nv = 0, ni = 0; - public SpriteRenderer(Renderer renderer, bool allowAlpha, Shader shader) + public SpriteRenderer(Renderer renderer, bool allowAlpha, IShader shader) { this.renderer = renderer; this.shader = shader; - vertexBuffer = new VertexBuffer(renderer.Device, vertices.Length, Vertex.Format); - indexBuffer = new IndexBuffer(renderer.Device, indices.Length); - - quality = allowAlpha ? ShaderQuality.High : ShaderQuality.Low; + vertexBuffer = renderer.Device.CreateVertexBuffer( vertices.Length ); + indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length ); } public SpriteRenderer(Renderer renderer, bool allowAlpha) @@ -56,7 +53,6 @@ namespace OpenRa.Graphics { if (sprites > 0) { - shader.Quality = quality; shader.SetValue( "DiffuseTexture", currentSheet.Texture ); shader.Render(() => { diff --git a/OpenRa.Game/Graphics/TerrainRenderer.cs b/OpenRa.Game/Graphics/TerrainRenderer.cs index b066214ac4..bce0114ecd 100644 --- a/OpenRa.Game/Graphics/TerrainRenderer.cs +++ b/OpenRa.Game/Graphics/TerrainRenderer.cs @@ -20,14 +20,14 @@ using System.Drawing; using OpenRa.FileFormats; -using OpenRa.GlRenderer; +using OpenRa.FileFormats.Graphics; namespace OpenRa.Graphics { class TerrainRenderer { - VertexBuffer vertexBuffer; - IndexBuffer indexBuffer; + IVertexBuffer vertexBuffer; + IIndexBuffer indexBuffer; Sheet terrainSheet; Renderer renderer; @@ -62,10 +62,10 @@ namespace OpenRa.Graphics terrainSheet = tileMapping[map.MapTiles[map.XOffset, map.YOffset]].sheet; - vertexBuffer = new VertexBuffer( renderer.Device, vertices.Length, Vertex.Format ); + vertexBuffer = renderer.Device.CreateVertexBuffer( vertices.Length ); vertexBuffer.SetData( vertices ); - indexBuffer = new IndexBuffer( renderer.Device, indices.Length ); + indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length ); indexBuffer.SetData( indices ); overlayRenderer = new OverlayRenderer( renderer, map ); @@ -97,7 +97,6 @@ namespace OpenRa.Graphics firstRow = r.Bottom - map.YOffset; } - renderer.SpriteShader.Quality = ShaderQuality.Low; renderer.SpriteShader.SetValue( "DiffuseTexture", terrainSheet.Texture ); renderer.SpriteShader.Render(() => renderer.DrawBatch(vertexBuffer, indexBuffer, diff --git a/OpenRa.Game/Graphics/Vertex.cs b/OpenRa.Game/Graphics/Vertex.cs index 8cea985bd8..e0229a8025 100644 --- a/OpenRa.Game/Graphics/Vertex.cs +++ b/OpenRa.Game/Graphics/Vertex.cs @@ -19,7 +19,6 @@ #endregion using System.Runtime.InteropServices; -using OpenRa.GlRenderer; namespace OpenRa.Graphics { @@ -35,7 +34,5 @@ namespace OpenRa.Graphics this.u = uv.X; this.v = uv.Y; this.p = pc.X; this.c = pc.Y; } - - public const VertexFormat Format = VertexFormat.Position | VertexFormat.Texture2; } } diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index da75c2cd7b..99d00154a8 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -272,10 +272,6 @@ {BDAEAB25-991E-46A7-AF1E-4F0E03358DAA} OpenRa.FileFormats - - {67CF1A10-C5F6-48FA-B1A7-FE83BE4CE2CC} - OpenRa.Gl - diff --git a/OpenRa.Gl/GraphicsDevice.cs b/OpenRa.Gl/GraphicsDevice.cs index 2f07cb967e..014a632d45 100644 --- a/OpenRa.Gl/GraphicsDevice.cs +++ b/OpenRa.Gl/GraphicsDevice.cs @@ -27,10 +27,13 @@ using System.Windows.Forms; using Tao.Cg; using Tao.OpenGl; using Tao.Platform.Windows; +using OpenRa.FileFormats.Graphics; + +[assembly: Renderer( typeof( OpenRa.GlRenderer.GraphicsDevice ))] namespace OpenRa.GlRenderer { - public class GraphicsDevice + public class GraphicsDevice : IGraphicsDevice { Size windowSize; Graphics g; @@ -39,7 +42,7 @@ namespace OpenRa.GlRenderer internal IntPtr cgContext; internal int vertexProfile, fragmentProfile; - public static void CheckGlError() + internal static void CheckGlError() { var n = Gl.glGetError(); if (n != Gl.GL_NO_ERROR) @@ -125,17 +128,28 @@ namespace OpenRa.GlRenderer CheckGlError(); } - public void DrawIndexedPrimitives(PrimitiveType pt, Range vertices, Range indices) - { - Gl.glDrawElements( (int)pt, indices.End - indices.Start, Gl.GL_UNSIGNED_SHORT, new IntPtr( indices.Start * 2 ) ); - CheckGlError(); - } - - public void DrawIndexedPrimitives(PrimitiveType pt, int numVerts, int numPrimitives) - { - Gl.glDrawElements((int)pt, numPrimitives * IndicesPerPrimitive( pt ), Gl.GL_UNSIGNED_SHORT, IntPtr.Zero); - CheckGlError(); - } + public void DrawIndexedPrimitives( PrimitiveType pt, Range vertices, Range indices ) + { + Gl.glDrawElements( ModeFromPrimitiveType( pt ), indices.End - indices.Start, Gl.GL_UNSIGNED_SHORT, new IntPtr( indices.Start * 2 ) ); + CheckGlError(); + } + + public void DrawIndexedPrimitives( PrimitiveType pt, int numVerts, int numPrimitives ) + { + Gl.glDrawElements( ModeFromPrimitiveType( pt ), numPrimitives * IndicesPerPrimitive( pt ), Gl.GL_UNSIGNED_SHORT, IntPtr.Zero ); + CheckGlError(); + } + + static int ModeFromPrimitiveType( PrimitiveType pt ) + { + switch( pt ) + { + case PrimitiveType.PointList: return Gl.GL_POINTS; + case PrimitiveType.LineList: return Gl.GL_LINES; + case PrimitiveType.TriangleList: return Gl.GL_TRIANGLES; + } + throw new NotImplementedException(); + } static int IndicesPerPrimitive( PrimitiveType pt ) { @@ -147,19 +161,39 @@ namespace OpenRa.GlRenderer } throw new NotImplementedException(); } - } - public struct Range - { - public readonly T Start, End; - public Range(T start, T end) { Start = start; End = end; } - } + #region IGraphicsDevice Members - public class VertexBuffer where T : struct + public IVertexBuffer CreateVertexBuffer( int size ) + where T : struct + { + return new VertexBuffer( this, size ); + } + + public IIndexBuffer CreateIndexBuffer( int size ) + { + return new IndexBuffer( this, size ); + } + + public ITexture CreateTexture( Bitmap bitmap ) + { + return new Texture( this, bitmap ); + } + + public IShader CreateShader( Stream stream ) + { + return new Shader( this, stream ); + } + + #endregion + } + + public class VertexBuffer : IVertexBuffer, IDisposable + where T : struct { int buffer; - public VertexBuffer(GraphicsDevice dev, int size, VertexFormat fmt) + public VertexBuffer(GraphicsDevice dev, int size) { Gl.glGenBuffers(1, out buffer); GraphicsDevice.CheckGlError(); @@ -196,7 +230,7 @@ namespace OpenRa.GlRenderer //~VertexBuffer() { Dispose(); } } - public class IndexBuffer : IDisposable + public class IndexBuffer : IIndexBuffer, IDisposable { int buffer; @@ -233,11 +267,10 @@ namespace OpenRa.GlRenderer //~IndexBuffer() { Dispose(); } } - public class Shader + public class Shader : IShader { IntPtr effect; - IntPtr highTechnique; - IntPtr lowTechnique; + IntPtr technique; GraphicsDevice dev; public Shader(GraphicsDevice dev, Stream s) @@ -256,31 +289,22 @@ namespace OpenRa.GlRenderer string.Format("Cg compile failed ({0}):\n{1}", err, results)); } - lowTechnique = Cg.cgGetNamedTechnique(effect, "low_quality"); - highTechnique = Cg.cgGetNamedTechnique(effect, "high_quality"); - - if (lowTechnique != IntPtr.Zero && 0 == Cg.cgValidateTechnique(lowTechnique)) - lowTechnique = IntPtr.Zero; - if (highTechnique != IntPtr.Zero && 0 == Cg.cgValidateTechnique(highTechnique)) - highTechnique = IntPtr.Zero; - - if (highTechnique == IntPtr.Zero && lowTechnique == IntPtr.Zero) - throw new InvalidOperationException("No valid techniques"); - - if( highTechnique == IntPtr.Zero ) - highTechnique = lowTechnique; - if( lowTechnique == IntPtr.Zero ) - lowTechnique = highTechnique; + technique = Cg.cgGetFirstTechnique( effect ); + if( technique == IntPtr.Zero ) + throw new InvalidOperationException("No techniques"); + while( Cg.cgValidateTechnique( technique ) == 0 ) + { + technique = Cg.cgGetNextTechnique( technique ); + if( technique == IntPtr.Zero ) + throw new InvalidOperationException("No valid techniques"); + } } - public ShaderQuality Quality { get; set; } - public void Render(Action a) { CgGl.cgGLEnableProfile(dev.vertexProfile); CgGl.cgGLEnableProfile(dev.fragmentProfile); - var technique = Quality == ShaderQuality.High ? highTechnique : lowTechnique; var pass = Cg.cgGetFirstPass(technique); while (pass != IntPtr.Zero) { @@ -294,8 +318,9 @@ namespace OpenRa.GlRenderer CgGl.cgGLDisableProfile(dev.vertexProfile); } - public void SetValue(string name, Texture texture) + public void SetValue(string name, ITexture t) { + var texture = (Texture)t; var param = Cg.cgGetNamedEffectParameter( effect, name ); if( param != IntPtr.Zero && texture != null ) CgGl.cgGLSetupSampler( param, texture.texture ); @@ -311,7 +336,7 @@ namespace OpenRa.GlRenderer public void Commit() { } } - public class Texture + public class Texture : ITexture { internal int texture; @@ -343,15 +368,4 @@ namespace OpenRa.GlRenderer bitmap.UnlockBits(bits); } } - - [Flags] - public enum VertexFormat { Position, Texture2 } - - public enum ShaderQuality { Low, High } - public enum PrimitiveType - { - PointList = Gl.GL_POINTS, - LineList = Gl.GL_LINES, - TriangleList = Gl.GL_TRIANGLES - } } diff --git a/OpenRa.Gl/OpenRa.Gl.csproj b/OpenRa.Gl/OpenRa.Gl.csproj index 0a299eafbc..fb3caf6559 100644 --- a/OpenRa.Gl/OpenRa.Gl.csproj +++ b/OpenRa.Gl/OpenRa.Gl.csproj @@ -59,6 +59,12 @@ + + + {BDAEAB25-991E-46A7-AF1E-4F0E03358DAA} + OpenRa.FileFormats + + + + copy "$(TargetPath)" "$(SolutionDir)" + \ No newline at end of file From 5637b0dc43cd9113edb17d89b708d5494472308c Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 17 Feb 2010 23:23:07 +1300 Subject: [PATCH 2/6] some of a glfw window --- OpenRa.Game/Game.cs | 83 ++++++++++++- OpenRa.Game/Graphics/Renderer.cs | 11 +- OpenRa.Game/MainWindow.cs | 196 +++++++++++++++---------------- OpenRa.Game/Support/Program.cs | 3 +- OpenRa.Game/Support/Settings.cs | 2 +- OpenRa.Gl/GraphicsDevice.cs | 88 +++++++------- OpenRa.Gl/OpenRa.Gl.csproj | 5 + 7 files changed, 239 insertions(+), 149 deletions(-) diff --git a/OpenRa.Game/Game.cs b/OpenRa.Game/Game.cs index a76a79e135..9c21c41716 100644 --- a/OpenRa.Game/Game.cs +++ b/OpenRa.Game/Game.cs @@ -30,6 +30,8 @@ using OpenRa.Network; using OpenRa.Support; using OpenRa.Traits; using Timer = OpenRa.Support.Timer; +using System.Runtime.InteropServices; +using System.IO; namespace OpenRa { @@ -285,7 +287,7 @@ namespace OpenRa return sp; } - internal static void DispatchMouseInput(MouseInputEvent ev, MouseEventArgs e, Keys ModifierKeys) + public static void DispatchMouseInput(MouseInputEvent ev, MouseEventArgs e, Keys ModifierKeys) { int sync = Game.world.SyncHash(); @@ -302,7 +304,7 @@ namespace OpenRa throw new InvalidOperationException( "Desync in DispatchMouseInput" ); } - internal static void HandleKeyDown( KeyEventArgs e ) + public static void HandleKeyDown( KeyEventArgs e ) { int sync = Game.world.SyncHash(); @@ -315,7 +317,7 @@ namespace OpenRa throw new InvalidOperationException( "Desync in OnKeyDown" ); } - internal static void HandleKeyPress( KeyPressEventArgs e ) + public static void HandleKeyPress( KeyPressEventArgs e ) { int sync = Game.world.SyncHash(); @@ -327,5 +329,80 @@ namespace OpenRa if( sync != Game.world.SyncHash() ) throw new InvalidOperationException( "Desync in OnKeyPress" ); } + + static Size GetResolution(Settings settings) + { + var desktopResolution = Screen.PrimaryScreen.Bounds.Size; + if (Game.Settings.Width > 0 && Game.Settings.Height > 0) + { + desktopResolution.Width = Game.Settings.Width; + desktopResolution.Height = Game.Settings.Height; + } + return new Size( + desktopResolution.Width, + desktopResolution.Height); + } + + [DllImport("user32")] + static extern int ShowCursor([MarshalAs(UnmanagedType.Bool)] bool visible); + + public static void PreInit(Settings settings) + { + while (!File.Exists("redalert.mix")) + { + var current = Directory.GetCurrentDirectory(); + if (Directory.GetDirectoryRoot(current) == current) + throw new InvalidOperationException("Unable to load MIX files."); + Directory.SetCurrentDirectory(".."); + } + + + LoadUserSettings(settings); + Game.LobbyInfo.GlobalSettings.Mods = Game.Settings.InitialMods; + + // Load the default mod to access required files + Game.LoadModPackages(new Manifest(Game.LobbyInfo.GlobalSettings.Mods)); + + UiOverlay.ShowUnitDebug = Game.Settings.UnitDebug; + WorldRenderer.ShowUnitPaths = Game.Settings.PathDebug; + Renderer.SheetSize = Game.Settings.SheetSize; + + bool windowed = !Game.Settings.Fullscreen; + var resolution = GetResolution(settings); + renderer = new Renderer(resolution, windowed); + + var controller = new Controller(() => (Modifiers)(int)0/*ModifierKeys*/); /* a bit of insane input routing */ + + Game.Initialize(Game.Settings.Map, renderer, new int2(resolution), Game.Settings.Player, controller); + + ShowCursor(false); + Game.ResetTimer(); + } + + static void LoadUserSettings(Settings settings) + { + Game.Settings = new UserSettings(); + var settingsFile = settings.GetValue("settings", "settings.ini"); + FileSystem.Mount("./"); + if (FileSystem.Exists(settingsFile)) + FieldLoader.Load(Game.Settings, + new IniFile(FileSystem.Open(settingsFile)).GetSection("Settings")); + FileSystem.UnmountAll(); + } + + static bool quit; + internal static void Run() + { + while (!quit) + { + Game.Tick(); + Application.DoEvents(); + } + } + + public static void Exit() + { + quit = true; + } } } diff --git a/OpenRa.Game/Graphics/Renderer.cs b/OpenRa.Game/Graphics/Renderer.cs index f59f505582..aa3033435b 100644 --- a/OpenRa.Game/Graphics/Renderer.cs +++ b/OpenRa.Game/Graphics/Renderer.cs @@ -49,10 +49,9 @@ namespace OpenRa.Graphics SpriteRenderer rgbaRenderer; Sprite textSprite; - public Renderer(Control control, Size resolution, bool windowed) + public Renderer(Size resolution, bool windowed) { - control.ClientSize = resolution; - device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( "OpenRa.Gl.dll" ) ), control, resolution.Width, resolution.Height, windowed, false ); + device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( "OpenRa.Gl.dll" ) ), resolution.Width, resolution.Height, windowed, false ); SpriteShader = device.CreateShader(FileSystem.Open("world-shp.fx")); LineShader = device.CreateShader(FileSystem.Open("line.fx")); @@ -66,12 +65,12 @@ namespace OpenRa.Graphics textSprite = new Sprite(textSheet, new Rectangle(0, 0, 256, 256), TextureChannel.Alpha); } - IGraphicsDevice CreateDevice( Assembly rendererDll, Control control, int width, int height, bool fullscreen, bool vsync ) + IGraphicsDevice CreateDevice( Assembly rendererDll, int width, int height, bool fullscreen, bool vsync ) { foreach( RendererAttribute r in rendererDll.GetCustomAttributes( typeof( RendererAttribute ), false ) ) { - return (IGraphicsDevice)r.Type.GetConstructor( new Type[] { typeof( Control ), typeof( int ), typeof( int ), typeof( bool ), typeof( bool ) } ) - .Invoke( new object[] { control, width, height, fullscreen, vsync } ); + return (IGraphicsDevice)r.Type.GetConstructor( new Type[] { typeof( int ), typeof( int ), typeof( bool ), typeof( bool ) } ) + .Invoke( new object[] { width, height, fullscreen, vsync } ); } throw new NotImplementedException(); } diff --git a/OpenRa.Game/MainWindow.cs b/OpenRa.Game/MainWindow.cs index 87c7340a40..05900bf949 100755 --- a/OpenRa.Game/MainWindow.cs +++ b/OpenRa.Game/MainWindow.cs @@ -29,128 +29,128 @@ using OpenRa.Graphics; namespace OpenRa { - class MainWindow : Form - { - readonly Renderer renderer; + //class MainWindow : Form + //{ + // readonly Renderer renderer; - static Size GetResolution(Settings settings) - { - var desktopResolution = Screen.PrimaryScreen.Bounds.Size; - if (Game.Settings.Width > 0 && Game.Settings.Height > 0) - { - desktopResolution.Width = Game.Settings.Width; - desktopResolution.Height = Game.Settings.Height; - } - return new Size( - desktopResolution.Width, - desktopResolution.Height); - } + // static Size GetResolution(Settings settings) + // { + // var desktopResolution = Screen.PrimaryScreen.Bounds.Size; + // if (Game.Settings.Width > 0 && Game.Settings.Height > 0) + // { + // desktopResolution.Width = Game.Settings.Width; + // desktopResolution.Height = Game.Settings.Height; + // } + // return new Size( + // desktopResolution.Width, + // desktopResolution.Height); + // } - [DllImport("user32")] - static extern int ShowCursor([MarshalAs(UnmanagedType.Bool)] bool visible); + // [DllImport("user32")] + // static extern int ShowCursor([MarshalAs(UnmanagedType.Bool)] bool visible); - public MainWindow(Settings settings) - { - Icon = Resources1.OpenRA; - FormBorderStyle = FormBorderStyle.None; - BackColor = Color.Black; - StartPosition = FormStartPosition.Manual; - Location = Point.Empty; - Visible = true; + // public MainWindow(Settings settings) + // { + // Icon = Resources1.OpenRA; + // FormBorderStyle = FormBorderStyle.None; + // BackColor = Color.Black; + // StartPosition = FormStartPosition.Manual; + // Location = Point.Empty; + // Visible = true; - while (!File.Exists("redalert.mix")) - { - var current = Directory.GetCurrentDirectory(); - if (Directory.GetDirectoryRoot(current) == current) - throw new InvalidOperationException("Unable to load MIX files."); - Directory.SetCurrentDirectory(".."); - } + // while (!File.Exists("redalert.mix")) + // { + // var current = Directory.GetCurrentDirectory(); + // if (Directory.GetDirectoryRoot(current) == current) + // throw new InvalidOperationException("Unable to load MIX files."); + // Directory.SetCurrentDirectory(".."); + // } - LoadUserSettings(settings); - Game.LobbyInfo.GlobalSettings.Mods = Game.Settings.InitialMods; + // LoadUserSettings(settings); + // Game.LobbyInfo.GlobalSettings.Mods = Game.Settings.InitialMods; - // Load the default mod to access required files - Game.LoadModPackages(new Manifest(Game.LobbyInfo.GlobalSettings.Mods)); + // // Load the default mod to access required files + // Game.LoadModPackages(new Manifest(Game.LobbyInfo.GlobalSettings.Mods)); - UiOverlay.ShowUnitDebug = Game.Settings.UnitDebug; - WorldRenderer.ShowUnitPaths = Game.Settings.PathDebug; - Renderer.SheetSize = Game.Settings.SheetSize; + // UiOverlay.ShowUnitDebug = Game.Settings.UnitDebug; + // WorldRenderer.ShowUnitPaths = Game.Settings.PathDebug; + // Renderer.SheetSize = Game.Settings.SheetSize; - bool windowed = !Game.Settings.Fullscreen; - renderer = new Renderer(this, GetResolution(settings), windowed); + // bool windowed = !Game.Settings.Fullscreen; + // renderer = new Renderer(this, GetResolution(settings), windowed); - var controller = new Controller(() => (Modifiers)(int)ModifierKeys); /* a bit of insane input routing */ + // var controller = new Controller(() => (Modifiers)(int)ModifierKeys); /* a bit of insane input routing */ - Game.Initialize(Game.Settings.Map, renderer, new int2(ClientSize), Game.Settings.Player, controller); + // Game.Initialize(Game.Settings.Map, renderer, new int2(ClientSize), Game.Settings.Player, controller); - ShowCursor(false); - Game.ResetTimer(); - } + // ShowCursor(false); + // Game.ResetTimer(); + // } - static void LoadUserSettings(Settings settings) - { - Game.Settings = new UserSettings(); - var settingsFile = settings.GetValue("settings", "settings.ini"); - FileSystem.Mount("./"); - if (FileSystem.Exists(settingsFile)) - FieldLoader.Load(Game.Settings, - new IniFile(FileSystem.Open(settingsFile)).GetSection("Settings")); - FileSystem.UnmountAll(); - } + // static void LoadUserSettings(Settings settings) + // { + // Game.Settings = new UserSettings(); + // var settingsFile = settings.GetValue("settings", "settings.ini"); + // FileSystem.Mount("./"); + // if (FileSystem.Exists(settingsFile)) + // FieldLoader.Load(Game.Settings, + // new IniFile(FileSystem.Open(settingsFile)).GetSection("Settings")); + // FileSystem.UnmountAll(); + // } - internal void Run() - { - while (Created && Visible) - { - Game.Tick(); - Application.DoEvents(); - } - } + // internal void Run() + // { + // while (Created && Visible) + // { + // Game.Tick(); + // Application.DoEvents(); + // } + // } - int2 lastPos; + // int2 lastPos; - protected override void OnMouseDown(MouseEventArgs e) - { - base.OnMouseDown(e); - lastPos = new int2(e.Location); - Game.DispatchMouseInput(MouseInputEvent.Down, e, ModifierKeys); - } + // protected override void OnMouseDown(MouseEventArgs e) + // { + // base.OnMouseDown(e); + // lastPos = new int2(e.Location); + // Game.DispatchMouseInput(MouseInputEvent.Down, e, ModifierKeys); + // } - protected override void OnMouseMove(MouseEventArgs e) - { - base.OnMouseMove(e); + // protected override void OnMouseMove(MouseEventArgs e) + // { + // base.OnMouseMove(e); - if (e.Button == MouseButtons.Middle || e.Button == (MouseButtons.Left | MouseButtons.Right)) - { - int2 p = new int2(e.Location); - Game.viewport.Scroll(lastPos - p); - lastPos = p; - } + // if (e.Button == MouseButtons.Middle || e.Button == (MouseButtons.Left | MouseButtons.Right)) + // { + // int2 p = new int2(e.Location); + // Game.viewport.Scroll(lastPos - p); + // lastPos = p; + // } - Game.DispatchMouseInput(MouseInputEvent.Move, e, ModifierKeys); - } + // Game.DispatchMouseInput(MouseInputEvent.Move, e, ModifierKeys); + // } - protected override void OnMouseUp(MouseEventArgs e) - { - base.OnMouseUp(e); - Game.DispatchMouseInput(MouseInputEvent.Up, e, ModifierKeys); - } + // protected override void OnMouseUp(MouseEventArgs e) + // { + // base.OnMouseUp(e); + // Game.DispatchMouseInput(MouseInputEvent.Up, e, ModifierKeys); + // } - protected override void OnKeyDown(KeyEventArgs e) - { - base.OnKeyDown(e); + // protected override void OnKeyDown(KeyEventArgs e) + // { + // base.OnKeyDown(e); - Game.HandleKeyDown( e ); - } + // Game.HandleKeyDown( e ); + // } - protected override void OnKeyPress(KeyPressEventArgs e) - { - base.OnKeyPress(e); + // protected override void OnKeyPress(KeyPressEventArgs e) + // { + // base.OnKeyPress(e); - Game.HandleKeyPress( e ); - } - } + // Game.HandleKeyPress( e ); + // } + //} [Flags] public enum MouseButton diff --git a/OpenRa.Game/Support/Program.cs b/OpenRa.Game/Support/Program.cs index 6d095c1386..7cd81c0f00 100644 --- a/OpenRa.Game/Support/Program.cs +++ b/OpenRa.Game/Support/Program.cs @@ -47,7 +47,8 @@ namespace OpenRa static void Run( string[] args ) { - new MainWindow( new Settings( args ) ).Run(); + Game.PreInit( new Settings( args ) ); + Game.Run(); } } } \ No newline at end of file diff --git a/OpenRa.Game/Support/Settings.cs b/OpenRa.Game/Support/Settings.cs index c9980a6788..2f47130034 100644 --- a/OpenRa.Game/Support/Settings.cs +++ b/OpenRa.Game/Support/Settings.cs @@ -23,7 +23,7 @@ using System.Text.RegularExpressions; namespace OpenRa { - class Settings + public class Settings { Dictionary settings = new Dictionary(); diff --git a/OpenRa.Gl/GraphicsDevice.cs b/OpenRa.Gl/GraphicsDevice.cs index 014a632d45..5afbb14536 100644 --- a/OpenRa.Gl/GraphicsDevice.cs +++ b/OpenRa.Gl/GraphicsDevice.cs @@ -28,6 +28,7 @@ using Tao.Cg; using Tao.OpenGl; using Tao.Platform.Windows; using OpenRa.FileFormats.Graphics; +using Tao.Glfw; [assembly: Renderer( typeof( OpenRa.GlRenderer.GraphicsDevice ))] @@ -36,56 +37,63 @@ namespace OpenRa.GlRenderer public class GraphicsDevice : IGraphicsDevice { Size windowSize; - Graphics g; - internal IntPtr dc; - internal IntPtr rc; internal IntPtr cgContext; internal int vertexProfile, fragmentProfile; + readonly Glfw.GLFWmousebuttonfun mouseButtonCallback; + readonly Glfw.GLFWmouseposfun mousePositionCallback; + readonly Glfw.GLFWwindowclosefun windowCloseCallback; + int mouseX, mouseY; + internal static void CheckGlError() { - var n = Gl.glGetError(); - if (n != Gl.GL_NO_ERROR) - throw new InvalidOperationException("GL Error"); + var n = Gl.glGetError(); + if (n != Gl.GL_NO_ERROR) + throw new InvalidOperationException("GL Error"); } - public GraphicsDevice(Control control, int width, int height, bool fullscreen, bool vsync) - { + public GraphicsDevice( int width, int height, bool fullscreen, bool vsync ) + { + Glfw.glfwInit(); + Glfw.glfwOpenWindow( width, height, 0, 0, 0, 0, 0, 0, /*fullscreen ? Glfw.GLFW_FULLSCREEN :*/ Glfw.GLFW_WINDOW ); + Glfw.glfwSetMouseButtonCallback( mouseButtonCallback = ( button, action ) => + { + var b = button == Glfw.GLFW_MOUSE_BUTTON_1 ? MouseButtons.Left + : button == Glfw.GLFW_MOUSE_BUTTON_2 ? MouseButtons.Right + : button == Glfw.GLFW_MOUSE_BUTTON_3 ? MouseButtons.Middle + : 0; + Game.DispatchMouseInput( action == Glfw.GLFW_PRESS ? MouseInputEvent.Down : MouseInputEvent.Up, + new MouseEventArgs( b, action == Glfw.GLFW_PRESS ? 1 : 0, mouseX, mouseY, 0 ), 0 ); + } ); + //Glfw.glfwSetMousePosCallback( mousePositionCallback = ( x, y ) => + // { + // mouseX = x; + // mouseY = y; + // Game.DispatchMouseInput( MouseInputEvent.Move, new MouseEventArgs( 0, 0, x, y, 0 ), 0 ); + // } ); + Glfw.glfwSetWindowCloseCallback( windowCloseCallback = () => + { + Game.Exit(); + Glfw.glfwIconifyWindow(); + return Gl.GL_FALSE; + } ); + CheckGlError(); + windowSize = new Size( width, height ); - g = control.CreateGraphics(); - dc = g.GetHdc(); - - var pfd = new Gdi.PIXELFORMATDESCRIPTOR - { - nSize = (short)Marshal.SizeOf(typeof(Gdi.PIXELFORMATDESCRIPTOR)), - nVersion = 1, - dwFlags = Gdi.PFD_SUPPORT_OPENGL | Gdi.PFD_DRAW_TO_BITMAP | Gdi.PFD_DOUBLEBUFFER, - iPixelType = Gdi.PFD_TYPE_RGBA, - cColorBits = 24, - iLayerType = Gdi.PFD_MAIN_PLANE - }; - var iFormat = Gdi.ChoosePixelFormat(dc, ref pfd); - Gdi.SetPixelFormat(dc, iFormat, ref pfd); + cgContext = Cg.cgCreateContext(); + Cg.cgSetErrorCallback( CgErrorCallback ); - rc = Wgl.wglCreateContext(dc); - if (rc == IntPtr.Zero) - throw new InvalidOperationException("can't create wglcontext"); - Wgl.wglMakeCurrent(dc, rc); + CgGl.cgGLRegisterStates( cgContext ); + CgGl.cgGLSetManageTextureParameters( cgContext, true ); + vertexProfile = CgGl.cgGLGetLatestProfile( CgGl.CG_GL_VERTEX ); + fragmentProfile = CgGl.cgGLGetLatestProfile( CgGl.CG_GL_FRAGMENT ); - cgContext = Cg.cgCreateContext(); - Cg.cgSetErrorCallback(CgErrorCallback); - - CgGl.cgGLRegisterStates(cgContext); - CgGl.cgGLSetManageTextureParameters(cgContext, true); - vertexProfile = CgGl.cgGLGetLatestProfile(CgGl.CG_GL_VERTEX); - fragmentProfile = CgGl.cgGLGetLatestProfile(CgGl.CG_GL_FRAGMENT); - - Gl.glEnableClientState(Gl.GL_VERTEX_ARRAY); - CheckGlError(); - Gl.glEnableClientState(Gl.GL_TEXTURE_COORD_ARRAY); - CheckGlError(); - } + Gl.glEnableClientState( Gl.GL_VERTEX_ARRAY ); + CheckGlError(); + Gl.glEnableClientState( Gl.GL_TEXTURE_COORD_ARRAY ); + CheckGlError(); + } static Cg.CGerrorCallbackFuncDelegate CgErrorCallback = () => { @@ -124,7 +132,7 @@ namespace OpenRa.GlRenderer public void Present() { - Wgl.wglSwapBuffers(dc); + Glfw.glfwSwapBuffers(); CheckGlError(); } diff --git a/OpenRa.Gl/OpenRa.Gl.csproj b/OpenRa.Gl/OpenRa.Gl.csproj index fb3caf6559..ed770f441f 100644 --- a/OpenRa.Gl/OpenRa.Gl.csproj +++ b/OpenRa.Gl/OpenRa.Gl.csproj @@ -48,6 +48,7 @@ False + False @@ -64,6 +65,10 @@ {BDAEAB25-991E-46A7-AF1E-4F0E03358DAA} OpenRa.FileFormats + + {0DFB103F-2962-400F-8C6D-E2C28CCBA633} + OpenRa.Game +