From 4c8f85b36b5b9aa6704b350698fa46afe542c74c Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 16 Jul 2010 18:22:19 +1200 Subject: [PATCH] split renderer into a file per class --- OpenRA.Gl/GraphicsDevice.cs | 242 ++---------------------------------- OpenRA.Gl/IndexBuffer.cs | 63 ++++++++++ OpenRA.Gl/OpenRA.Gl.csproj | 4 + OpenRA.Gl/Shader.cs | 96 ++++++++++++++ OpenRA.Gl/Texture.cs | 82 ++++++++++++ OpenRA.Gl/VertexBuffer.cs | 69 ++++++++++ 6 files changed, 324 insertions(+), 232 deletions(-) create mode 100644 OpenRA.Gl/IndexBuffer.cs create mode 100644 OpenRA.Gl/Shader.cs create mode 100644 OpenRA.Gl/Texture.cs create mode 100644 OpenRA.Gl/VertexBuffer.cs diff --git a/OpenRA.Gl/GraphicsDevice.cs b/OpenRA.Gl/GraphicsDevice.cs index c64f179ffd..41353b44ac 100644 --- a/OpenRA.Gl/GraphicsDevice.cs +++ b/OpenRA.Gl/GraphicsDevice.cs @@ -19,10 +19,8 @@ #endregion using System; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using System.Runtime.InteropServices; +using System.Drawing; +using System.IO; using System.Windows.Forms; using OpenRA.FileFormats.Graphics; using Tao.Cg; @@ -257,13 +255,15 @@ namespace OpenRA.GlRenderer 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)); + 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); + Gl.glDrawElements(ModeFromPrimitiveType(pt), numPrimitives * IndicesPerPrimitive(pt), + Gl.GL_UNSIGNED_SHORT, IntPtr.Zero); CheckGlError(); } @@ -289,231 +289,9 @@ namespace OpenRA.GlRenderer throw new NotImplementedException(); } - #region IGraphicsDevice Members - - public IVertexBuffer CreateVertexBuffer(int size) - { - 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) - { - Gl.glGenBuffers(1, out buffer); - GraphicsDevice.CheckGlError(); - } - - public void SetData(T[] data) - { - Bind(); - Gl.glBufferData(Gl.GL_ARRAY_BUFFER, - new IntPtr(Marshal.SizeOf(typeof(T)) * data.Length), data, Gl.GL_DYNAMIC_DRAW); - GraphicsDevice.CheckGlError(); - } - - public void Bind() - { - Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, buffer); - GraphicsDevice.CheckGlError(); - Gl.glVertexPointer(3, Gl.GL_FLOAT, Marshal.SizeOf(typeof(T)), IntPtr.Zero); - GraphicsDevice.CheckGlError(); - Gl.glTexCoordPointer(4, Gl.GL_FLOAT, Marshal.SizeOf(typeof(T)), new IntPtr(12)); - GraphicsDevice.CheckGlError(); - } - - bool disposed; - public void Dispose() - { - if (disposed) return; - GC.SuppressFinalize(this); - Gl.glDeleteBuffers(1, ref buffer); - GraphicsDevice.CheckGlError(); - disposed = true; - } - - //~VertexBuffer() { Dispose(); } - } - - public class IndexBuffer : IIndexBuffer, IDisposable - { - int buffer; - - public IndexBuffer(GraphicsDevice dev, int size) - { - Gl.glGenBuffers(1, out buffer); - GraphicsDevice.CheckGlError(); - } - - public void SetData(ushort[] data) - { - Bind(); - Gl.glBufferData(Gl.GL_ELEMENT_ARRAY_BUFFER, - new IntPtr(2 * data.Length), data, Gl.GL_DYNAMIC_DRAW); - GraphicsDevice.CheckGlError(); - } - - public void Bind() - { - Gl.glBindBuffer(Gl.GL_ELEMENT_ARRAY_BUFFER, buffer); - GraphicsDevice.CheckGlError(); - } - - bool disposed; - public void Dispose() - { - if (disposed) return; - GC.SuppressFinalize(this); - Gl.glDeleteBuffers(1, ref buffer); - GraphicsDevice.CheckGlError(); - disposed = true; - } - - //~IndexBuffer() { Dispose(); } - } - - public class Shader : IShader - { - IntPtr effect; - IntPtr technique; - GraphicsDevice dev; - - public Shader(GraphicsDevice dev, Stream s) - { - this.dev = dev; - string code; - using (var file = new StreamReader(s)) - code = file.ReadToEnd(); - effect = Cg.cgCreateEffect(dev.cgContext, code, null); - - if (effect == IntPtr.Zero) - { - var err = Cg.cgGetErrorString(Cg.cgGetError()); - var results = Cg.cgGetLastListing(dev.cgContext); - throw new InvalidOperationException( - string.Format("Cg compile failed ({0}):\n{1}", err, results)); - } - - 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 void Render(Action a) - { - CgGl.cgGLEnableProfile(dev.vertexProfile); - CgGl.cgGLEnableProfile(dev.fragmentProfile); - - var pass = Cg.cgGetFirstPass(technique); - while (pass != IntPtr.Zero) - { - Cg.cgSetPassState(pass); - a(); - Cg.cgResetPassState(pass); - pass = Cg.cgGetNextPass(pass); - } - - CgGl.cgGLDisableProfile(dev.fragmentProfile); - CgGl.cgGLDisableProfile(dev.vertexProfile); - } - - 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); - } - - public void SetValue(string name, float x, float y) - { - var param = Cg.cgGetNamedEffectParameter(effect, name); - if (param != IntPtr.Zero) - CgGl.cgGLSetParameter2f(param, x, y); - } - - public void Commit() { } - } - - public class Texture : ITexture - { - internal int texture; - - public Texture(GraphicsDevice dev, Bitmap bitmap) - { - Gl.glGenTextures(1, out texture); - GraphicsDevice.CheckGlError(); - SetData(bitmap); - } - - public void SetData(Bitmap bitmap) - { - if (!IsPowerOf2(bitmap.Width) || !IsPowerOf2(bitmap.Height)) - { - //throw new InvalidOperationException( "non-power-of-2-texture" ); - bitmap = new Bitmap(bitmap, new Size(NextPowerOf2(bitmap.Width), NextPowerOf2(bitmap.Height))); - } - - Gl.glBindTexture(Gl.GL_TEXTURE_2D, texture); - GraphicsDevice.CheckGlError(); - - var bits = bitmap.LockBits( - new Rectangle(0, 0, bitmap.Width, bitmap.Height), - ImageLockMode.ReadOnly, - PixelFormat.Format32bppArgb); - - Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_BASE_LEVEL, 0); - GraphicsDevice.CheckGlError(); - Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAX_LEVEL, 0); - GraphicsDevice.CheckGlError(); - Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA8, bits.Width, bits.Height, - 0, Gl.GL_BGRA, Gl.GL_UNSIGNED_BYTE, bits.Scan0); // todo: weird strides - GraphicsDevice.CheckGlError(); - - bitmap.UnlockBits(bits); - } - - bool IsPowerOf2(int v) - { - return (v & (v - 1)) == 0; - } - - int NextPowerOf2(int v) - { - --v; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - ++v; - return v; - } + public IVertexBuffer CreateVertexBuffer(int size) { 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); } } } diff --git a/OpenRA.Gl/IndexBuffer.cs b/OpenRA.Gl/IndexBuffer.cs new file mode 100644 index 0000000000..3391579c2d --- /dev/null +++ b/OpenRA.Gl/IndexBuffer.cs @@ -0,0 +1,63 @@ +#region Copyright & License Information +/* + * Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford. + * This file is part of OpenRA. + * + * OpenRA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OpenRA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OpenRA. If not, see . + */ +#endregion + +using System; +using OpenRA.FileFormats.Graphics; +using Tao.OpenGl; + +namespace OpenRA.GlRenderer +{ + public class IndexBuffer : IIndexBuffer, IDisposable + { + int buffer; + + public IndexBuffer(GraphicsDevice dev, int size) + { + Gl.glGenBuffers(1, out buffer); + GraphicsDevice.CheckGlError(); + } + + public void SetData(ushort[] data) + { + Bind(); + Gl.glBufferData(Gl.GL_ELEMENT_ARRAY_BUFFER, + new IntPtr(2 * data.Length), data, Gl.GL_DYNAMIC_DRAW); + GraphicsDevice.CheckGlError(); + } + + public void Bind() + { + Gl.glBindBuffer(Gl.GL_ELEMENT_ARRAY_BUFFER, buffer); + GraphicsDevice.CheckGlError(); + } + + bool disposed; + public void Dispose() + { + if (disposed) return; + GC.SuppressFinalize(this); + Gl.glDeleteBuffers(1, ref buffer); + GraphicsDevice.CheckGlError(); + disposed = true; + } + + //~IndexBuffer() { Dispose(); } + } +} diff --git a/OpenRA.Gl/OpenRA.Gl.csproj b/OpenRA.Gl/OpenRA.Gl.csproj index 695680c861..5bcd79eb0a 100644 --- a/OpenRA.Gl/OpenRA.Gl.csproj +++ b/OpenRA.Gl/OpenRA.Gl.csproj @@ -54,7 +54,11 @@ + + + + diff --git a/OpenRA.Gl/Shader.cs b/OpenRA.Gl/Shader.cs new file mode 100644 index 0000000000..ff2e460219 --- /dev/null +++ b/OpenRA.Gl/Shader.cs @@ -0,0 +1,96 @@ +#region Copyright & License Information +/* + * Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford. + * This file is part of OpenRA. + * + * OpenRA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OpenRA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OpenRA. If not, see . + */ +#endregion + +using System; +using System.IO; +using OpenRA.FileFormats.Graphics; +using Tao.Cg; + +namespace OpenRA.GlRenderer +{ + public class Shader : IShader + { + IntPtr effect; + IntPtr technique; + GraphicsDevice dev; + + public Shader(GraphicsDevice dev, Stream s) + { + this.dev = dev; + string code; + using (var file = new StreamReader(s)) + code = file.ReadToEnd(); + effect = Cg.cgCreateEffect(dev.cgContext, code, null); + + if (effect == IntPtr.Zero) + { + var err = Cg.cgGetErrorString(Cg.cgGetError()); + var results = Cg.cgGetLastListing(dev.cgContext); + throw new InvalidOperationException( + string.Format("Cg compile failed ({0}):\n{1}", err, results)); + } + + 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 void Render(Action a) + { + CgGl.cgGLEnableProfile(dev.vertexProfile); + CgGl.cgGLEnableProfile(dev.fragmentProfile); + + var pass = Cg.cgGetFirstPass(technique); + while (pass != IntPtr.Zero) + { + Cg.cgSetPassState(pass); + a(); + Cg.cgResetPassState(pass); + pass = Cg.cgGetNextPass(pass); + } + + CgGl.cgGLDisableProfile(dev.fragmentProfile); + CgGl.cgGLDisableProfile(dev.vertexProfile); + } + + 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); + } + + public void SetValue(string name, float x, float y) + { + var param = Cg.cgGetNamedEffectParameter(effect, name); + if (param != IntPtr.Zero) + CgGl.cgGLSetParameter2f(param, x, y); + } + + public void Commit() { } + } +} diff --git a/OpenRA.Gl/Texture.cs b/OpenRA.Gl/Texture.cs new file mode 100644 index 0000000000..0e6bed5186 --- /dev/null +++ b/OpenRA.Gl/Texture.cs @@ -0,0 +1,82 @@ +#region Copyright & License Information +/* + * Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford. + * This file is part of OpenRA. + * + * OpenRA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OpenRA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OpenRA. If not, see . + */ +#endregion + +using System.Drawing; +using System.Drawing.Imaging; +using OpenRA.FileFormats.Graphics; +using Tao.OpenGl; + +namespace OpenRA.GlRenderer +{ + public class Texture : ITexture + { + internal int texture; + + public Texture(GraphicsDevice dev, Bitmap bitmap) + { + Gl.glGenTextures(1, out texture); + GraphicsDevice.CheckGlError(); + SetData(bitmap); + } + + public void SetData(Bitmap bitmap) + { + if (!IsPowerOf2(bitmap.Width) || !IsPowerOf2(bitmap.Height)) + { + //throw new InvalidOperationException( "non-power-of-2-texture" ); + bitmap = new Bitmap(bitmap, new Size(NextPowerOf2(bitmap.Width), NextPowerOf2(bitmap.Height))); + } + + Gl.glBindTexture(Gl.GL_TEXTURE_2D, texture); + GraphicsDevice.CheckGlError(); + + var bits = bitmap.LockBits( + new Rectangle(0, 0, bitmap.Width, bitmap.Height), + ImageLockMode.ReadOnly, + PixelFormat.Format32bppArgb); + + Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_BASE_LEVEL, 0); + GraphicsDevice.CheckGlError(); + Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAX_LEVEL, 0); + GraphicsDevice.CheckGlError(); + Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA8, bits.Width, bits.Height, + 0, Gl.GL_BGRA, Gl.GL_UNSIGNED_BYTE, bits.Scan0); // todo: weird strides + GraphicsDevice.CheckGlError(); + + bitmap.UnlockBits(bits); + } + + bool IsPowerOf2(int v) + { + return (v & (v - 1)) == 0; + } + + int NextPowerOf2(int v) + { + --v; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + ++v; + return v; + } + } +} diff --git a/OpenRA.Gl/VertexBuffer.cs b/OpenRA.Gl/VertexBuffer.cs new file mode 100644 index 0000000000..f28dc88813 --- /dev/null +++ b/OpenRA.Gl/VertexBuffer.cs @@ -0,0 +1,69 @@ +#region Copyright & License Information +/* + * Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford. + * This file is part of OpenRA. + * + * OpenRA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OpenRA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OpenRA. If not, see . + */ +#endregion + +using System; +using System.Runtime.InteropServices; +using OpenRA.FileFormats.Graphics; +using Tao.OpenGl; + +namespace OpenRA.GlRenderer +{ + public class VertexBuffer : IVertexBuffer, IDisposable + where T : struct + { + int buffer; + + public VertexBuffer(GraphicsDevice dev, int size) + { + Gl.glGenBuffers(1, out buffer); + GraphicsDevice.CheckGlError(); + } + + public void SetData(T[] data) + { + Bind(); + Gl.glBufferData(Gl.GL_ARRAY_BUFFER, + new IntPtr(Marshal.SizeOf(typeof(T)) * data.Length), data, Gl.GL_DYNAMIC_DRAW); + GraphicsDevice.CheckGlError(); + } + + public void Bind() + { + Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, buffer); + GraphicsDevice.CheckGlError(); + Gl.glVertexPointer(3, Gl.GL_FLOAT, Marshal.SizeOf(typeof(T)), IntPtr.Zero); + GraphicsDevice.CheckGlError(); + Gl.glTexCoordPointer(4, Gl.GL_FLOAT, Marshal.SizeOf(typeof(T)), new IntPtr(12)); + GraphicsDevice.CheckGlError(); + } + + bool disposed; + public void Dispose() + { + if (disposed) return; + GC.SuppressFinalize(this); + Gl.glDeleteBuffers(1, ref buffer); + GraphicsDevice.CheckGlError(); + disposed = true; + } + + //~VertexBuffer() { Dispose(); } + } +}