Remove legacy renderers.
This commit is contained in:
62
OpenRA.Renderer.Sdl2/ErrorHandler.cs
Normal file
62
OpenRA.Renderer.Sdl2/ErrorHandler.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 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.Diagnostics;
|
||||
using Tao.OpenGl;
|
||||
|
||||
namespace OpenRA.Renderer.Sdl2
|
||||
{
|
||||
public static class ErrorHandler
|
||||
{
|
||||
public enum GlError
|
||||
{
|
||||
GL_NO_ERROR = Gl.GL_NO_ERROR,
|
||||
GL_INVALID_ENUM = Gl.GL_INVALID_ENUM,
|
||||
GL_INVALID_VALUE = Gl.GL_INVALID_VALUE,
|
||||
GL_STACK_OVERFLOW = Gl.GL_STACK_OVERFLOW,
|
||||
GL_STACK_UNDERFLOW = Gl.GL_STACK_UNDERFLOW,
|
||||
GL_OUT_OF_MEMORY = Gl.GL_OUT_OF_MEMORY,
|
||||
GL_TABLE_TOO_LARGE = Gl.GL_TABLE_TOO_LARGE,
|
||||
GL_INVALID_OPERATION = Gl.GL_INVALID_OPERATION,
|
||||
|
||||
// Framebuffer errors
|
||||
GL_FRAMEBUFFER_COMPLETE_EXT = Gl.GL_FRAMEBUFFER_COMPLETE_EXT,
|
||||
GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT = Gl.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT,
|
||||
GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT = Gl.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT,
|
||||
GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT = Gl.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT,
|
||||
GL_FRAMEBUFFER_UNSUPPORTED_EXT = Gl.GL_FRAMEBUFFER_UNSUPPORTED_EXT,
|
||||
}
|
||||
|
||||
public static void CheckGlError()
|
||||
{
|
||||
var n = Gl.glGetError();
|
||||
if (n != Gl.GL_NO_ERROR)
|
||||
{
|
||||
var error = "GL Error: {0}\n{1}".F((GlError)n, new StackTrace());
|
||||
WriteGraphicsLog(error);
|
||||
throw new InvalidOperationException("OpenGL Error: See graphics.log for details.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteGraphicsLog(string message)
|
||||
{
|
||||
Log.Write("graphics", message);
|
||||
Log.Write("graphics", "");
|
||||
Log.Write("graphics", "OpenGL Information:");
|
||||
Log.Write("graphics", "Vendor: {0}", Gl.glGetString(Gl.GL_VENDOR));
|
||||
Log.Write("graphics", "Renderer: {0}", Gl.glGetString(Gl.GL_RENDERER));
|
||||
Log.Write("graphics", "GL Version: {0}", Gl.glGetString(Gl.GL_VERSION));
|
||||
Log.Write("graphics", "Shader Version: {0}", Gl.glGetString(Gl.GL_SHADING_LANGUAGE_VERSION));
|
||||
Log.Write("graphics", "Available extensions:");
|
||||
Log.Write("graphics", Gl.glGetString(Gl.GL_EXTENSIONS));
|
||||
}
|
||||
}
|
||||
}
|
||||
126
OpenRA.Renderer.Sdl2/FrameBuffer.cs
Normal file
126
OpenRA.Renderer.Sdl2/FrameBuffer.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 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.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using OpenRA.Graphics;
|
||||
using Tao.OpenGl;
|
||||
|
||||
namespace OpenRA.Renderer.Sdl2
|
||||
{
|
||||
public class FrameBuffer : IFrameBuffer
|
||||
{
|
||||
Texture texture;
|
||||
Size size;
|
||||
int framebuffer, depth;
|
||||
|
||||
public FrameBuffer(Size size)
|
||||
{
|
||||
this.size = size;
|
||||
if (!Exts.IsPowerOf2(size.Width) || !Exts.IsPowerOf2(size.Height))
|
||||
throw new InvalidDataException("Frame buffer size ({0}x{1}) must be a power of two".F(size.Width, size.Height));
|
||||
|
||||
Gl.glGenFramebuffersEXT(1, out framebuffer);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, framebuffer);
|
||||
ErrorHandler.CheckGlError();
|
||||
|
||||
// Color
|
||||
texture = new Texture();
|
||||
texture.SetEmpty(size.Width, size.Height);
|
||||
Gl.glFramebufferTexture2DEXT(Gl.GL_FRAMEBUFFER_EXT, Gl.GL_COLOR_ATTACHMENT0_EXT, Gl.GL_TEXTURE_2D, texture.ID, 0);
|
||||
ErrorHandler.CheckGlError();
|
||||
|
||||
// Depth
|
||||
Gl.glGenRenderbuffersEXT(1, out depth);
|
||||
ErrorHandler.CheckGlError();
|
||||
|
||||
Gl.glBindRenderbufferEXT(Gl.GL_RENDERBUFFER_EXT, depth);
|
||||
ErrorHandler.CheckGlError();
|
||||
|
||||
Gl.glRenderbufferStorageEXT(Gl.GL_RENDERBUFFER_EXT, Gl.GL_DEPTH_COMPONENT, size.Width, size.Height);
|
||||
ErrorHandler.CheckGlError();
|
||||
|
||||
Gl.glFramebufferRenderbufferEXT(Gl.GL_FRAMEBUFFER_EXT, Gl.GL_DEPTH_ATTACHMENT_EXT, Gl.GL_RENDERBUFFER_EXT, depth);
|
||||
ErrorHandler.CheckGlError();
|
||||
|
||||
// Test for completeness
|
||||
var status = Gl.glCheckFramebufferStatusEXT(Gl.GL_FRAMEBUFFER_EXT);
|
||||
if (status != Gl.GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
{
|
||||
var error = "Error creating framebuffer: {0}\n{1}".F((ErrorHandler.GlError)status, new StackTrace());
|
||||
ErrorHandler.WriteGraphicsLog(error);
|
||||
throw new InvalidOperationException("OpenGL Error: See graphics.log for details.");
|
||||
}
|
||||
|
||||
// Restore default buffer
|
||||
Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, 0);
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
|
||||
static int[] ViewportRectangle()
|
||||
{
|
||||
var v = new int[4];
|
||||
unsafe
|
||||
{
|
||||
fixed (int* ptr = &v[0])
|
||||
{
|
||||
IntPtr intPtr = new IntPtr((void*)ptr);
|
||||
Gl.glGetIntegerv(Gl.GL_VIEWPORT, intPtr);
|
||||
}
|
||||
}
|
||||
|
||||
ErrorHandler.CheckGlError();
|
||||
return v;
|
||||
}
|
||||
|
||||
void FinalizeInner()
|
||||
{
|
||||
Gl.glDeleteFramebuffersEXT(1, ref framebuffer);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glDeleteRenderbuffersEXT(1, ref depth);
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
|
||||
~FrameBuffer() { Game.RunAfterTick(FinalizeInner); }
|
||||
|
||||
int[] cv = new int[4];
|
||||
public void Bind()
|
||||
{
|
||||
// Cache viewport rect to restore when unbinding
|
||||
cv = ViewportRectangle();
|
||||
|
||||
Gl.glFlush();
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, framebuffer);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glViewport(0, 0, size.Width, size.Height);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glClearColor(0, 0, 0, 0);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
|
||||
public void Unbind()
|
||||
{
|
||||
Gl.glFlush();
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, 0);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glViewport(cv[0], cv[1], cv[2], cv[3]);
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
|
||||
public ITexture Texture { get { return texture; } }
|
||||
}
|
||||
}
|
||||
84
OpenRA.Renderer.Sdl2/MultiTapDetection.cs
Normal file
84
OpenRA.Renderer.Sdl2/MultiTapDetection.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 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 OpenRA;
|
||||
using OpenRA.Primitives;
|
||||
|
||||
namespace OpenRA.Renderer.Sdl2
|
||||
{
|
||||
public static class MultiTapDetection
|
||||
{
|
||||
static Cache<Keycode, TapHistory> keyHistoryCache =
|
||||
new Cache<Keycode, TapHistory>(_ => new TapHistory(DateTime.Now - TimeSpan.FromSeconds(1)));
|
||||
static Cache<byte, TapHistory> clickHistoryCache =
|
||||
new Cache<byte, TapHistory>(_ => new TapHistory(DateTime.Now - TimeSpan.FromSeconds(1)));
|
||||
|
||||
public static int DetectFromMouse(byte button, int2 xy)
|
||||
{
|
||||
return clickHistoryCache[button].GetTapCount(xy);
|
||||
}
|
||||
|
||||
public static int InfoFromMouse(byte button)
|
||||
{
|
||||
return clickHistoryCache[button].LastTapCount();
|
||||
}
|
||||
|
||||
public static int DetectFromKeyboard(Keycode key)
|
||||
{
|
||||
return keyHistoryCache[key].GetTapCount(int2.Zero);
|
||||
}
|
||||
|
||||
public static int InfoFromKeyboard(Keycode key)
|
||||
{
|
||||
return keyHistoryCache[key].LastTapCount();
|
||||
}
|
||||
}
|
||||
|
||||
class TapHistory
|
||||
{
|
||||
public Pair<DateTime, int2> FirstRelease, SecondRelease, ThirdRelease;
|
||||
|
||||
public TapHistory(DateTime now)
|
||||
{
|
||||
FirstRelease = SecondRelease = ThirdRelease = Pair.New(now, int2.Zero);
|
||||
}
|
||||
|
||||
static bool CloseEnough(Pair<DateTime, int2> a, Pair<DateTime, int2> b)
|
||||
{
|
||||
return a.First - b.First < TimeSpan.FromMilliseconds(250)
|
||||
&& (a.Second - b.Second).Length < 4;
|
||||
}
|
||||
|
||||
public int GetTapCount(int2 xy)
|
||||
{
|
||||
FirstRelease = SecondRelease;
|
||||
SecondRelease = ThirdRelease;
|
||||
ThirdRelease = Pair.New(DateTime.Now, xy);
|
||||
|
||||
if (!CloseEnough(ThirdRelease, SecondRelease))
|
||||
return 1;
|
||||
if (!CloseEnough(SecondRelease, FirstRelease))
|
||||
return 2;
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
public int LastTapCount()
|
||||
{
|
||||
if (!CloseEnough(ThirdRelease, SecondRelease))
|
||||
return 1;
|
||||
if (!CloseEnough(SecondRelease, FirstRelease))
|
||||
return 2;
|
||||
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,12 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Sdl2Input.cs" />
|
||||
<Compile Include="Sdl2GraphicsDevice.cs" />
|
||||
<Compile Include="Shader.cs" />
|
||||
<Compile Include="ErrorHandler.cs" />
|
||||
<Compile Include="FrameBuffer.cs" />
|
||||
<Compile Include="MultiTapDetection.cs" />
|
||||
<Compile Include="Texture.cs" />
|
||||
<Compile Include="VertexBuffer.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
@@ -51,13 +57,5 @@
|
||||
<Project>{0DFB103F-2962-400F-8C6D-E2C28CCBA633}</Project>
|
||||
<Name>OpenRA.Game</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\OpenRA.Renderer.SdlCommon\OpenRA.Renderer.SdlCommon.csproj">
|
||||
<Project>{52FD9F0B-B209-4ED7-8A32-AC8033363263}</Project>
|
||||
<Name>OpenRA.Renderer.SdlCommon</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\OpenRA.Renderer.Gl\OpenRA.Renderer.Gl.csproj">
|
||||
<Project>{E9C01A96-C3E2-4772-825B-A740AC513D31}</Project>
|
||||
<Name>OpenRA.Renderer.Gl</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -13,8 +13,6 @@ using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Renderer.Glsl;
|
||||
using OpenRA.Renderer.SdlCommon;
|
||||
using SDL2;
|
||||
using Tao.OpenGl;
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#endregion
|
||||
|
||||
using System.Text;
|
||||
using OpenRA.Renderer.SdlCommon;
|
||||
using SDL2;
|
||||
|
||||
namespace OpenRA.Renderer.Sdl2
|
||||
@@ -117,7 +116,7 @@ namespace OpenRA.Renderer.Sdl2
|
||||
case SDL.SDL_EventType.SDL_MOUSEWHEEL:
|
||||
{
|
||||
// Retain compatibility with existing bogus behavior
|
||||
// TODO: Implement real scroll behavior after we drop SDL 1.2 support
|
||||
// TODO: Implement real scroll behavior. We've dropped SDL 1.2 support!
|
||||
if (e.wheel.y == 0)
|
||||
break;
|
||||
|
||||
|
||||
186
OpenRA.Renderer.Sdl2/Shader.cs
Normal file
186
OpenRA.Renderer.Sdl2/Shader.cs
Normal file
@@ -0,0 +1,186 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 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.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using OpenRA.FileSystem;
|
||||
using OpenRA.Graphics;
|
||||
using Tao.OpenGl;
|
||||
|
||||
namespace OpenRA.Renderer.Sdl2
|
||||
{
|
||||
public class Shader : IShader
|
||||
{
|
||||
readonly Dictionary<string, int> samplers = new Dictionary<string, int>();
|
||||
readonly Dictionary<int, ITexture> textures = new Dictionary<int, ITexture>();
|
||||
int program;
|
||||
|
||||
public Shader(string name)
|
||||
{
|
||||
// Vertex shader
|
||||
string vertexCode;
|
||||
using (var file = new StreamReader(GlobalFileSystem.Open("glsl{0}{1}.vert".F(Path.DirectorySeparatorChar, name))))
|
||||
vertexCode = file.ReadToEnd();
|
||||
|
||||
var v = Gl.glCreateShaderObjectARB(Gl.GL_VERTEX_SHADER_ARB);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glShaderSourceARB(v, 1, new string[] { vertexCode }, null);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glCompileShaderARB(v);
|
||||
ErrorHandler.CheckGlError();
|
||||
|
||||
int success;
|
||||
Gl.glGetObjectParameterivARB(v, Gl.GL_OBJECT_COMPILE_STATUS_ARB, out success);
|
||||
ErrorHandler.CheckGlError();
|
||||
if (success == 0)
|
||||
throw new InvalidProgramException("Compile error in {0}{1}.vert".F(Path.DirectorySeparatorChar, name));
|
||||
|
||||
// Fragment shader
|
||||
string fragmentCode;
|
||||
using (var file = new StreamReader(GlobalFileSystem.Open("glsl{0}{1}.frag".F(Path.DirectorySeparatorChar, name))))
|
||||
fragmentCode = file.ReadToEnd();
|
||||
|
||||
var f = Gl.glCreateShaderObjectARB(Gl.GL_FRAGMENT_SHADER_ARB);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glShaderSourceARB(f, 1, new string[] { fragmentCode }, null);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glCompileShaderARB(f);
|
||||
ErrorHandler.CheckGlError();
|
||||
|
||||
Gl.glGetObjectParameterivARB(f, Gl.GL_OBJECT_COMPILE_STATUS_ARB, out success);
|
||||
ErrorHandler.CheckGlError();
|
||||
if (success == 0)
|
||||
throw new InvalidProgramException("Compile error in glsl{0}{1}.frag".F(Path.DirectorySeparatorChar, name));
|
||||
|
||||
// Assemble program
|
||||
program = Gl.glCreateProgramObjectARB();
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glAttachObjectARB(program, v);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glAttachObjectARB(program, f);
|
||||
ErrorHandler.CheckGlError();
|
||||
|
||||
Gl.glLinkProgramARB(program);
|
||||
ErrorHandler.CheckGlError();
|
||||
|
||||
Gl.glGetObjectParameterivARB(program, Gl.GL_OBJECT_LINK_STATUS_ARB, out success);
|
||||
ErrorHandler.CheckGlError();
|
||||
if (success == 0)
|
||||
throw new InvalidProgramException("Linking error in {0} shader".F(name));
|
||||
|
||||
Gl.glUseProgramObjectARB(program);
|
||||
ErrorHandler.CheckGlError();
|
||||
|
||||
int numUniforms;
|
||||
Gl.glGetObjectParameterivARB(program, Gl.GL_ACTIVE_UNIFORMS, out numUniforms);
|
||||
ErrorHandler.CheckGlError();
|
||||
|
||||
int nextTexUnit = 0;
|
||||
for (var i = 0; i < numUniforms; i++)
|
||||
{
|
||||
int length, size, type;
|
||||
var sb = new StringBuilder(128);
|
||||
|
||||
Gl.glGetActiveUniformARB(program, i, 128, out length, out size, out type, sb);
|
||||
var sampler = sb.ToString();
|
||||
ErrorHandler.CheckGlError();
|
||||
|
||||
if (type == Gl.GL_SAMPLER_2D_ARB)
|
||||
{
|
||||
samplers.Add(sampler, nextTexUnit);
|
||||
|
||||
var loc = Gl.glGetUniformLocationARB(program, sampler);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glUniform1iARB(loc, nextTexUnit);
|
||||
ErrorHandler.CheckGlError();
|
||||
|
||||
nextTexUnit++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Render(Action a)
|
||||
{
|
||||
Gl.glUseProgramObjectARB(program);
|
||||
|
||||
// bind the textures
|
||||
foreach (var kv in textures)
|
||||
{
|
||||
Gl.glActiveTextureARB(Gl.GL_TEXTURE0_ARB + kv.Key);
|
||||
Gl.glBindTexture(Gl.GL_TEXTURE_2D, ((Texture)kv.Value).ID);
|
||||
}
|
||||
|
||||
ErrorHandler.CheckGlError();
|
||||
a();
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
|
||||
public void SetTexture(string name, ITexture t)
|
||||
{
|
||||
if (t == null)
|
||||
return;
|
||||
|
||||
int texUnit;
|
||||
if (samplers.TryGetValue(name, out texUnit))
|
||||
textures[texUnit] = t;
|
||||
}
|
||||
|
||||
public void SetVec(string name, float x)
|
||||
{
|
||||
Gl.glUseProgramObjectARB(program);
|
||||
ErrorHandler.CheckGlError();
|
||||
var param = Gl.glGetUniformLocationARB(program, name);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glUniform1fARB(param, x);
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
|
||||
public void SetVec(string name, float x, float y)
|
||||
{
|
||||
Gl.glUseProgramObjectARB(program);
|
||||
ErrorHandler.CheckGlError();
|
||||
var param = Gl.glGetUniformLocationARB(program, name);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glUniform2fARB(param, x, y);
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
|
||||
public void SetVec(string name, float[] vec, int length)
|
||||
{
|
||||
var param = Gl.glGetUniformLocationARB(program, name);
|
||||
ErrorHandler.CheckGlError();
|
||||
switch (length)
|
||||
{
|
||||
case 1: Gl.glUniform1fv(param, 1, vec); break;
|
||||
case 2: Gl.glUniform2fv(param, 1, vec); break;
|
||||
case 3: Gl.glUniform3fv(param, 1, vec); break;
|
||||
case 4: Gl.glUniform4fv(param, 1, vec); break;
|
||||
default: throw new InvalidDataException("Invalid vector length");
|
||||
}
|
||||
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
|
||||
public void SetMatrix(string name, float[] mtx)
|
||||
{
|
||||
if (mtx.Length != 16)
|
||||
throw new InvalidDataException("Invalid 4x4 matrix");
|
||||
|
||||
Gl.glUseProgramObjectARB(program);
|
||||
ErrorHandler.CheckGlError();
|
||||
var param = Gl.glGetUniformLocationARB(program, name);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glUniformMatrix4fv(param, 1, Gl.GL_FALSE, mtx);
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
}
|
||||
}
|
||||
154
OpenRA.Renderer.Sdl2/Texture.cs
Normal file
154
OpenRA.Renderer.Sdl2/Texture.cs
Normal file
@@ -0,0 +1,154 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 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.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using OpenRA.Graphics;
|
||||
using Tao.OpenGl;
|
||||
|
||||
namespace OpenRA.Renderer.Sdl2
|
||||
{
|
||||
public class Texture : ITexture
|
||||
{
|
||||
int texture;
|
||||
public int ID { get { return texture; } }
|
||||
|
||||
Size size;
|
||||
public Size Size { get { return size; } }
|
||||
|
||||
public Texture()
|
||||
{
|
||||
Gl.glGenTextures(1, out texture);
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
|
||||
public Texture(Bitmap bitmap)
|
||||
{
|
||||
Gl.glGenTextures(1, out texture);
|
||||
ErrorHandler.CheckGlError();
|
||||
SetData(bitmap);
|
||||
}
|
||||
|
||||
void FinalizeInner() { Gl.glDeleteTextures(1, ref texture); }
|
||||
~Texture() { Game.RunAfterTick(FinalizeInner); }
|
||||
|
||||
void PrepareTexture()
|
||||
{
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glBindTexture(Gl.GL_TEXTURE_2D, texture);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_NEAREST);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_NEAREST);
|
||||
ErrorHandler.CheckGlError();
|
||||
|
||||
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_S, Gl.GL_CLAMP_TO_EDGE);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_T, Gl.GL_CLAMP_TO_EDGE);
|
||||
ErrorHandler.CheckGlError();
|
||||
|
||||
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_BASE_LEVEL, 0);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAX_LEVEL, 0);
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
|
||||
public void SetData(byte[] colors, int width, int height)
|
||||
{
|
||||
if (!Exts.IsPowerOf2(width) || !Exts.IsPowerOf2(height))
|
||||
throw new InvalidDataException("Non-power-of-two array {0}x{1}".F(width, height));
|
||||
|
||||
size = new Size(width, height);
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* ptr = &colors[0])
|
||||
{
|
||||
IntPtr intPtr = new IntPtr((void*)ptr);
|
||||
PrepareTexture();
|
||||
Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA8, width, height,
|
||||
0, Gl.GL_BGRA, Gl.GL_UNSIGNED_BYTE, intPtr);
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// An array of RGBA
|
||||
public void SetData(uint[,] colors)
|
||||
{
|
||||
int width = colors.GetUpperBound(1) + 1;
|
||||
int height = colors.GetUpperBound(0) + 1;
|
||||
|
||||
if (!Exts.IsPowerOf2(width) || !Exts.IsPowerOf2(height))
|
||||
throw new InvalidDataException("Non-power-of-two array {0}x{1}".F(width, height));
|
||||
|
||||
size = new Size(width, height);
|
||||
unsafe
|
||||
{
|
||||
fixed (uint* ptr = &colors[0, 0])
|
||||
{
|
||||
IntPtr intPtr = new IntPtr((void*)ptr);
|
||||
PrepareTexture();
|
||||
Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA8, width, height,
|
||||
0, Gl.GL_BGRA, Gl.GL_UNSIGNED_BYTE, intPtr);
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetData(Bitmap bitmap)
|
||||
{
|
||||
if (!Exts.IsPowerOf2(bitmap.Width) || !Exts.IsPowerOf2(bitmap.Height))
|
||||
bitmap = new Bitmap(bitmap, bitmap.Size.NextPowerOf2());
|
||||
|
||||
size = new Size(bitmap.Width, bitmap.Height);
|
||||
var bits = bitmap.LockBits(bitmap.Bounds(),
|
||||
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
PrepareTexture();
|
||||
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
|
||||
ErrorHandler.CheckGlError();
|
||||
bitmap.UnlockBits(bits);
|
||||
}
|
||||
|
||||
public byte[] GetData()
|
||||
{
|
||||
var data = new byte[4 * size.Width * size.Height];
|
||||
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glBindTexture(Gl.GL_TEXTURE_2D, texture);
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* ptr = &data[0])
|
||||
{
|
||||
IntPtr intPtr = new IntPtr((void*)ptr);
|
||||
Gl.glGetTexImage(Gl.GL_TEXTURE_2D, 0, Gl.GL_BGRA, Gl.GL_UNSIGNED_BYTE, intPtr);
|
||||
}
|
||||
}
|
||||
|
||||
ErrorHandler.CheckGlError();
|
||||
return data;
|
||||
}
|
||||
|
||||
public void SetEmpty(int width, int height)
|
||||
{
|
||||
if (!Exts.IsPowerOf2(width) || !Exts.IsPowerOf2(height))
|
||||
throw new InvalidDataException("Non-power-of-two array {0}x{1}".F(width, height));
|
||||
|
||||
size = new Size(width, height);
|
||||
PrepareTexture();
|
||||
Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA8, width, height,
|
||||
0, Gl.GL_BGRA, Gl.GL_UNSIGNED_BYTE, null);
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
}
|
||||
}
|
||||
59
OpenRA.Renderer.Sdl2/VertexBuffer.cs
Normal file
59
OpenRA.Renderer.Sdl2/VertexBuffer.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 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.Runtime.InteropServices;
|
||||
using OpenRA.Graphics;
|
||||
using Tao.OpenGl;
|
||||
|
||||
namespace OpenRA.Renderer.Sdl2
|
||||
{
|
||||
public class VertexBuffer<T> : IVertexBuffer<T>
|
||||
where T : struct
|
||||
{
|
||||
static readonly int VertexSize = Marshal.SizeOf(typeof(T));
|
||||
int buffer;
|
||||
|
||||
public VertexBuffer(int size)
|
||||
{
|
||||
Gl.glGenBuffersARB(1, out buffer);
|
||||
ErrorHandler.CheckGlError();
|
||||
Bind();
|
||||
Gl.glBufferDataARB(Gl.GL_ARRAY_BUFFER_ARB,
|
||||
new IntPtr(VertexSize * size),
|
||||
new T[size],
|
||||
Gl.GL_DYNAMIC_DRAW_ARB);
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
|
||||
public void SetData(T[] data, int length)
|
||||
{
|
||||
Bind();
|
||||
Gl.glBufferSubDataARB(Gl.GL_ARRAY_BUFFER_ARB,
|
||||
IntPtr.Zero,
|
||||
new IntPtr(VertexSize * length),
|
||||
data);
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
|
||||
public void Bind()
|
||||
{
|
||||
Gl.glBindBufferARB(Gl.GL_ARRAY_BUFFER_ARB, buffer);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glVertexPointer(3, Gl.GL_FLOAT, VertexSize, IntPtr.Zero);
|
||||
ErrorHandler.CheckGlError();
|
||||
Gl.glTexCoordPointer(4, Gl.GL_FLOAT, VertexSize, new IntPtr(12));
|
||||
ErrorHandler.CheckGlError();
|
||||
}
|
||||
|
||||
void FinalizeInner() { Gl.glDeleteBuffersARB(1, ref buffer); }
|
||||
~VertexBuffer() { Game.RunAfterTick(FinalizeInner); }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user