Synced with latest Tao.GlBindGen source. OpenTK.OpenGL.Bind now uses CodeDOM internally for code generation. Many bugfixes. Supports newest specs.

This commit is contained in:
the_fiddler 2007-04-20 19:03:11 +00:00
parent 52cbe0c5a8
commit 3ff2b848e2
8 changed files with 1683 additions and 994 deletions

View file

@ -1,7 +1,29 @@
#region License
//Copyright (c) 2006 Stephen Apostolopoulos
//See license.txt for license info
#endregion
/*
MIT License
Copyright ©2003-2006 Tao Framework Team
http://www.taoframework.com
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
using System.Text;
@ -10,18 +32,19 @@ using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Collections.Generic;
using System.Collections;
using System.CodeDom;
[assembly:CLSCompliant(true), FileIOPermission(SecurityAction.RequestMinimum, Unrestricted = true)]
namespace OpenTK.OpenGL.Bind
{
static class MainClass
{
static void Main(string[] arguments)
{
Console.WriteLine("{0} {1} by Stephen Apostolopoulos (stapostol@gmail.com)",
System.Reflection.Assembly.GetExecutingAssembly().GetName().Name,
Console.WriteLine("OpenGL binding generator {0} for OpenTK.",
System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString());
Console.WriteLine("For comments, bugs and suggestions visit http://opentk.sourceforge.net");
//Console.WriteLine(" - the OpenTK team ;-)");
Console.WriteLine();
#region Handle Arguments
@ -72,44 +95,28 @@ namespace OpenTK.OpenGL.Bind
{
long ticks = System.DateTime.Now.Ticks;
// GL binding generation.
List<CodeMemberMethod> functions;
List<CodeTypeDelegate> delegates;
CodeTypeDeclarationCollection enums;
CodeTypeDeclarationCollection enums2;
Translation.GLTypes = SpecReader.ReadTypeMap("gl.tm");
Translation.CSTypes = SpecReader.ReadTypeMap("csharp.tm");
delegates = SpecReader.ReadFunctionSpecs("gl.spec");
SpecReader.ReadEnumSpecs("enum.spec", out enums);
SpecReader.ReadEnumSpecs("enumext.spec", out enums2);
enums = SpecTranslator.Merge(enums, enums2);
enums = SpecTranslator.TranslateEnums(enums);
List<Function> wrappers;
List<Function> functions = SpecReader.ReadFunctionSpecs("gl.spec");
Hashtable enums = SpecReader.ReadEnumSpecs("enum.spec");
Hashtable enums2 = SpecReader.ReadEnumSpecs("enumext.spec");
foreach (Enum e in enums2.Values)
if (!enums.ContainsKey(e.Name))
enums.Add(e.Name, e);
else
{
foreach (Constant c in e.ConstantCollection.Values)
if (!((Enum)enums[e.Name]).ConstantCollection.ContainsKey(c.Name))
((Enum)enums[e.Name]).ConstantCollection.Add(c.Name, c);
}
functions = SpecTranslator.TranslateDelegates(delegates, enums);
Translation.TranslateFunctions(functions, enums, out wrappers);
Translation.TranslateEnums(enums);
SpecWriter.WriteSpecs(Settings.OutputPath, Settings.GLClass, functions, wrappers, enums);
//ContextWriter.WriteMainContext(Settings.OutputPath, "GLContext", Settings.GLClass, functions);
//ContextWriter.WriteDerivedContext(Settings.OutputPath, "WindowsContext", Settings.GLClass, functions, "1.0", "1.1");
//ContextWriter.WriteDerivedContext(Settings.OutputPath, "WindowsVistaContext", Settings.GLClass, functions, "1.0", "1.1", "1.2", "1.3", "1.4");
//ContextWriter.WriteDerivedContext(Settings.OutputPath, "X11Context", Settings.GLClass, functions, "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "2.0");
// GLX binding generation.
//Translation.GLXTypes = SpecReader.ReadTypeMap("glx.tm"); // Works semi-ok.
//List<Function> functions = SpecReader.ReadFunctionSpecs("glx.spec"); // Works ok!
//Hashtable enums = SpecReader.ReadEnumSpecs("glxenum.spec"); // Works ok!
//SpecWriter.WriteSpecs(Settings.OutputPath, "Glx", functions, null, enums); // Needs updating.
// Generate the code
SpecWriter.Generate(delegates, functions, enums);
ticks = System.DateTime.Now.Ticks - ticks;
Console.WriteLine("Bindings generated in {0} seconds.", ticks / (double)10000000.0);
Console.WriteLine();
Console.WriteLine("Press enter to continue...");
Console.ReadLine();
}
catch (SecurityException e)
{

View file

@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
// Build Number
// Revision
//
[assembly: AssemblyVersion("0.7.7.0")]
[assembly: AssemblyFileVersion("0.7.7.0")]
[assembly: AssemblyVersion("0.9.0.3")]
[assembly: AssemblyFileVersion("0.9.0.3")]

View file

@ -13,7 +13,12 @@ namespace OpenTK.OpenGL.Bind
{
public static string InputPath = "..\\..\\..\\Source\\OpenGL\\Specifications";
public static string OutputPath = "..\\..\\..\\Source\\OpenGL\\OpenGL\\Bindings";
public static string GLClass = "GL";
public static string OutputNamespace = "OpenTK.OpenGL";
public static string GLClass = "GL";
public static string WglClass = "Wgl";
public static string GlxClass = "Glx";
public static string GluClass = "Glu";
public static string GLFunctionPrepend = String.Empty;
}
}

View file

@ -0,0 +1,416 @@
#region License
/*
MIT License
Copyright ©2003-2006 Tao Framework Team
http://www.taoframework.com
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.CodeDom;
namespace OpenTK.OpenGL.Bind
{
static class SpecReader
{
#region internal static string FilePath
internal static string FilePath
{
get
{
string filePath = Path.Combine("..", "..");
string fileDirectory = Settings.InputPath;
string fileName = "gl.spec";
if (File.Exists(fileName))
{
filePath = "";
fileDirectory = "";
}
else if (File.Exists(Path.Combine(fileDirectory, fileName)))
{
filePath = "";
}
return Path.Combine(filePath, fileDirectory);
}
}
#endregion
#region private static StreamReader OpenSpecFile(string file)
private static StreamReader OpenSpecFile(string file)
{
string path = Path.Combine(FilePath, file);
StreamReader sr;
try
{
sr = new StreamReader(path);
}
catch (Exception e)
{
Console.WriteLine("Error opening spec file: {0}", path);
Console.WriteLine("Error: {0}", e.Message);
throw e;
}
return sr;
}
#endregion
#region private static bool IsExtension(string function_name)
private static bool IsExtension(string function_name)
{
return (function_name.EndsWith("ARB") ||
function_name.EndsWith("EXT") ||
function_name.EndsWith("ATI") ||
function_name.EndsWith("NV") ||
function_name.EndsWith("SUN") ||
function_name.EndsWith("SUNX") ||
function_name.EndsWith("SGI") ||
function_name.EndsWith("SGIS") ||
function_name.EndsWith("SGIX") ||
function_name.EndsWith("MESA") ||
function_name.EndsWith("3DFX") ||
function_name.EndsWith("IBM") ||
function_name.EndsWith("GREMEDY") ||
function_name.EndsWith("HP") ||
function_name.EndsWith("INTEL") ||
function_name.EndsWith("PGI") ||
function_name.EndsWith("INGR") ||
function_name.EndsWith("APPLE"));
}
#endregion
#region private static string NextValidLine(StreamReader sr)
private static string NextValidLine(StreamReader sr)
{
string line;
do
{
if (sr.EndOfStream)
return null;
line = sr.ReadLine().Trim();
if (String.IsNullOrEmpty(line) ||
line.StartsWith("#") || // Disregard comments.
line.StartsWith("passthru") || // Disregard passthru statements.
line.StartsWith("required-props:") ||
line.StartsWith("param:") ||
line.StartsWith("dlflags:") ||
line.StartsWith("glxflags:") ||
line.StartsWith("vectorequiv:") ||
//line.StartsWith("category:") ||
line.StartsWith("version:") ||
line.StartsWith("glxsingle:") ||
line.StartsWith("glxropcode:") ||
line.StartsWith("glxvendorpriv:") ||
line.StartsWith("glsflags:") ||
line.StartsWith("glsopcode:") ||
line.StartsWith("glsalias:") ||
line.StartsWith("wglflags:") ||
line.StartsWith("extension:") ||
line.StartsWith("alias:") ||
line.StartsWith("offset:"))
continue;
return line;
}
while (true);
}
#endregion
#region public static void ReadFunctionSpecs(string file, out List<CodeTypeDelegate> delegates, out List<CodeMemberMethod> functions)
public static List<CodeTypeDelegate> ReadFunctionSpecs(string file)
{
StreamReader sr = OpenSpecFile(file);
Console.WriteLine("Reading function specs from file: {0}", file);
List<CodeTypeDelegate> delegates = new List<CodeTypeDelegate>();
do
{
string line = NextValidLine(sr);
if (String.IsNullOrEmpty(line))
break;
// Get next OpenGL function
while (line.Contains("(") && !sr.EndOfStream)
{
CodeTypeDelegate d = new CodeTypeDelegate();
d.Attributes = MemberAttributes.Static;
d.CustomAttributes.Add(new CodeAttributeDeclaration("System.Security.SuppressUnmanagedCodeSecurity"));
// Get function name:
d.Name = line.Split(SpecTranslator.Separators, StringSplitOptions.RemoveEmptyEntries)[0];
if (IsExtension(d.Name))
{
d.UserData.Add("Extension", true);
}
else
{
d.UserData.Add("Extension", false);
}
//d.StartDirectives.Add(new CodeRegionDirective(CodeRegionMode.Start, d.Name));
//d.EndDirectives.Add(new CodeRegionDirective(CodeRegionMode.End, d.Name));
// Get function parameters and return value:
do
{
line = sr.ReadLine();
List<string> words = new List<string>(
line.Replace('\t', ' ').Split(SpecTranslator.Separators, StringSplitOptions.RemoveEmptyEntries));
if (words.Count == 0)
break;
// Identify line:
switch (words[0])
{
case "return": // Line denotes return value
CodeTypeReference tr = new CodeTypeReference(
words[1]
);
//if (tr.BaseType == "GLvoid")
// tr.BaseType = "System.Void";
d.ReturnType = tr;
break;
case "param": // Line denotes parameter
CodeParameterDeclarationExpression p =
new CodeParameterDeclarationExpression();
p.Name = words[1];
p.Type = new CodeTypeReference(words[2]);
p.Direction = words[3] == "in" ? FieldDirection.In : FieldDirection.Out;
if (words[3] != "in")
p.CustomAttributes.Add(new CodeAttributeDeclaration("In, Out"));
p.Type.ArrayRank = words[4] == "array" ? 1 : 0;
d.Parameters.Add(p);
break;
/* version directive is not used. GetTexParameterIivEXT and GetTexParameterIuivEXT define two(!) versions (why?)
case "version": // Line denotes function version (i.e. 1.0, 1.2, 1.5)
d.UserData.Add("version", words[1]);
break;
*/
case "category":
d.UserData.Add("Category", words[1]);
break;
}
}
while (!sr.EndOfStream);
delegates.Add(d);
}
}
while (!sr.EndOfStream);
return delegates;
}
#endregion
#region public static void ReadEnumSpecs(string file, out List<CodeMemberField> enums)
public static void ReadEnumSpecs(string file, out CodeTypeDeclarationCollection enums)
{
enums = new CodeTypeDeclarationCollection();
StreamReader sr = OpenSpecFile(file);
Console.WriteLine("Reading constant specs from file: {0}", file);
do
{
string line = NextValidLine(sr);
if (String.IsNullOrEmpty(line))
break;
line = line.Replace('\t', ' ');
// We just encountered the start of a new enumerant:
while (!String.IsNullOrEmpty(line) && line.Contains("enum"))
{
string[] words = line.Split(SpecTranslator.Separators, StringSplitOptions.RemoveEmptyEntries);
if (words.Length == 0)
continue;
// Declare a new enumerant
CodeTypeDeclaration e = new CodeTypeDeclaration();
e.IsEnum = true;
e.Name = SpecTranslator.GetTranslatedEnum(words[0]);
//d.Attributes = MemberAttributes.Const | MemberAttributes.Public;
// And fill in the values for this enumerant
do
{
line = NextValidLine(sr);
if (String.IsNullOrEmpty(line) || line.StartsWith("#"))
continue;
if (line.Contains("enum:") || sr.EndOfStream)
break;
line = line.Replace('\t', ' ');
words = line.Split(SpecTranslator.Separators, StringSplitOptions.RemoveEmptyEntries);
if (words.Length == 0)
continue;
// If we reach this point, we have found a new value for the current enumerant
CodeMemberField c = new CodeMemberField();
if (line.Contains("="))
{
c.Name = SpecTranslator.GetTranslatedEnum(words[0]);
uint number;
if (UInt32.TryParse(words[2].Replace("0x", String.Empty), System.Globalization.NumberStyles.AllowHexSpecifier, null, out number))
{
if (number > 0x7FFFFFFF)
{
words[2] = "unchecked((Int32)" + words[2] + ")";
}
}
else if (words[2].StartsWith("GL_"))
{
words[2] = words[2].Substring(3);
}
//c.InitExpression = new CodeFieldReferenceExpression(null, words[2]);
//c.UserData.Add("InitExpression", " = " + words[2]);
c.UserData.Add("ObjectReference", null);
c.UserData.Add("FieldReference", words[2]);
}
else if (words[0] == "use")
{
c.Name = SpecTranslator.GetTranslatedEnum(words[2]);
//c.InitExpression = new CodeFieldReferenceExpression(new CodeSnippetExpression(words[1]), SpecTranslator.GetTranslatedEnum(words[2]));
//c.UserData.Add("InitExpression", " = " + words[1] + "." + SpecTranslator.GetTranslatedEnum(words[2]));
c.UserData.Add("ObjectReference", words[1]);
c.UserData.Add("FieldReference", words[2]);
}
//if (!String.IsNullOrEmpty(c.Name) && !e.Members.Contains.Contains(c))
SpecTranslator.Merge(e.Members, c);
}
while (!sr.EndOfStream);
// At this point, the complete value list for the current enumerant has been read, so add this
// enumerant to the list.
e.StartDirectives.Add(new CodeRegionDirective(CodeRegionMode.Start, "public enum " + e.Name));
e.EndDirectives.Add(new CodeRegionDirective(CodeRegionMode.End, "public enum " + e.Name));
// Hack - discard Boolean enum, it fsucks up the fragile translation code ahead.
//if (!e.Name.Contains("Bool"))
SpecTranslator.Merge(enums, e);
}
}
while (!sr.EndOfStream);
}
#endregion
#region public static bool ListContainsConstant(List<CodeMemberField> enums, CodeMemberField c)
public static bool ListContainsConstant(List<CodeMemberField> constants, CodeMemberField c)
{
foreach (CodeMemberField d in constants)
if (d.Name == c.Name)
return true;
return false;
}
#endregion
#region public static Dictionary<string, CodeTypeReference> ReadTypeMap(string file)
public static Dictionary<string, CodeTypeReference> ReadTypeMap(string file)
{
Dictionary<string, CodeTypeReference> map =
new Dictionary<string, CodeTypeReference>();
string path = Path.Combine(FilePath, file);
StreamReader sr;
try
{
sr = new StreamReader(path);
}
catch (Exception)
{
Console.WriteLine("Error opening typemap file: {0}", path);
return null;
}
Console.WriteLine("Reading typemaps from file: {0}", file);
do
{
string line = sr.ReadLine();
if (String.IsNullOrEmpty(line) || line.StartsWith("#"))
continue;
string[] words = line.Split(new char[] { ' ', ',', '*', '\t' }, StringSplitOptions.RemoveEmptyEntries);
if (words[0] == "void")
{
// Special case for "void" -> ""
map.Add(words[0], new CodeTypeReference(String.Empty));
}
else if (words[0] == "VoidPointer")
{ // Special case for "VoidPointer" -> "GLvoid*"
map.Add(words[0], new CodeTypeReference("System.Object"));
}
else if (words[0] == "CharPointer" || words[0] == "charPointerARB")
{
map.Add(words[0], new CodeTypeReference("System.String"));
}
else if (words[0].Contains("Pointer"))
{
map.Add(words[0], new CodeTypeReference(words[1], 1));
}
//else if (words[1].Contains("Boolean"))
//{
// // Do not add this to the typemap!
//}
/*else if (words[1] == "GLenum")
{
// Do not throw away the type to generic GLenum. We want type checking!
}*/
else
{
map.Add(words[0], new CodeTypeReference(words[1]));
}
}
while (!sr.EndOfStream);
return map;
}
#endregion
}
}

View file

@ -0,0 +1,877 @@
#region License
/*
MIT License
Copyright ©2003-2006 Tao Framework Team
http://www.taoframework.com
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.CodeDom;
namespace OpenTK.OpenGL.Bind
{
#region WrapperTypes enum
public enum WrapperTypes
{
/// <summary>
/// No wrapper needed.
/// </summary>
None,
/// <summary>
/// Function takes bool parameter - C uses Int for bools, so we have to marshal.
/// </summary>
BoolParameter,
/// <summary>
/// Function takes generic parameters - add ref/out generic and generic overloads.
/// </summary>
GenericParameter,
/// <summary>
/// Function takes arrays as parameters - add ref/out and ([Out]) array overloads.
/// </summary>
ArrayParameter,
/// <summary>
/// Function with bitmask parameters. Bitmask parameters map to UInt, but since we can only use signed
/// types (for CLS compliance), we must add the unchecked keyword.
/// Usually found in bitmasks
/// </summary>
UncheckedParameter,
/// <summary>
/// Function returns string - needs manual marshalling through IntPtr to prevent the managed GC
/// from freeing memory allocated on the unmanaged side (e.g. glGetString).
/// </summary>
StringReturnValue,
/// <summary>
/// Function returns a void pointer - maps to IntPtr, and the user has to manually marshal the type.
/// </summary>
GenericReturnValue,
/// <summary>
/// Function returns a typed pointer - we have to copy the data to an array to protect it from the GC.
/// </summary>
ArrayReturnValue
}
#endregion
static class SpecTranslator
{
#region static SpecTranslator()
// Do not remove! - forces BeforeFieldInit to false.
static SpecTranslator()
{
}
#endregion
#region Fields and Properties
public static char[] Separators = { ' ', '\n', ',', '(', ')', ';', '#' };
#region GL types dictionary
private static Dictionary<string, CodeTypeReference> _gl_types = SpecReader.ReadTypeMap("gl.tm");
public static Dictionary<string, CodeTypeReference> GLTypes
{
get { return SpecTranslator._gl_types; }
set { SpecTranslator._gl_types = value; }
}
#endregion
#region CS types dictionary
private static Dictionary<string, CodeTypeReference> _cs_types = SpecReader.ReadTypeMap("csharp.tm");
public static Dictionary<string, CodeTypeReference> CSTypes
{
get { return SpecTranslator._cs_types; }
set { SpecTranslator._cs_types = value; }
}
#endregion
#region GLX types dictionary
private static Dictionary<string, string> _glx_types;
public static Dictionary<string, string> GLXTypes
{
get { return _glx_types; }
set { _glx_types = value; }
}
#endregion
#region WGL types dictionary
private static Dictionary<string, string> _wgl_types;
public static Dictionary<string, string> WGLTypes
{
get { return _wgl_types; }
set { _wgl_types = value; }
}
#endregion
#endregion
#region public static List<CodeMemberMethod> TranslateDelegates(List<CodeTypeDelegate> delegates, CodeTypeDeclarationCollection enums)
public static List<CodeMemberMethod> TranslateDelegates(List<CodeTypeDelegate> delegates, CodeTypeDeclarationCollection enums)
{
List<CodeMemberMethod> functions = new List<CodeMemberMethod>();
foreach (CodeTypeDelegate d in delegates)
{
TranslateReturnValue(d);
TranslateParameters(d, enums);
functions.AddRange(CreateWrappers(d));
}
return functions;
}
#endregion
#region private static void TranslateReturnValue(CodeTypeDelegate d)
private static void TranslateReturnValue(CodeTypeDelegate d)
{
CodeTypeReference s;
if (d.ReturnType.BaseType == "void")
d.ReturnType.BaseType = "System.Void";
if (GLTypes.TryGetValue(d.ReturnType.BaseType, out s))
d.ReturnType = s;
if (d.ReturnType.BaseType == "GLstring")
{
d.ReturnType = new CodeTypeReference("IntPtr");
d.ReturnType.UserData.Add("Wrapper", WrapperTypes.StringReturnValue);
}
if (d.ReturnType.BaseType.ToLower().Contains("object"))
{
d.ReturnType.BaseType = "IntPtr";
d.ReturnType.UserData.Add("Wrapper", WrapperTypes.GenericReturnValue);
d.ReturnType.ArrayRank = 0;
}
if (d.ReturnType.UserData.Contains("Wrapper"))
{
d.UserData.Add("Wrapper", null);
}
}
#endregion
#region private static void TranslateParameters(CodeTypeDelegate d)
private static void TranslateParameters(CodeTypeDelegate d, CodeTypeDeclarationCollection enums)
{
CodeTypeReference s;
if (d.Name == "BufferDataARB")
{
}
// Translate each parameter of the function while checking for needed wrappers:
foreach (CodeParameterDeclarationExpression p in d.Parameters)
{
// Translate parameter type
if (Search(enums, p.Type.BaseType))
{
p.Type.BaseType = "Enums." + p.Type.BaseType;
}
else if (GLTypes.TryGetValue(p.Type.BaseType, out s))
{
if (s.BaseType == "GLenum" && d.UserData.Contains("Category"))
{
bool found = false;
// There is no enumerant with the needed name. Try to see if any of the generic enumerants
// (category: VERSION_1_1 etc) match the needed name.
foreach (CodeTypeDeclaration enumerant in enums)
{
if (enumerant.Name == (string)d.UserData["Category"])
{
p.Type.BaseType = "Enums." + (string)d.UserData["Category"];
found = true;
break;
}
}
if (!found || p.Type.BaseType.ToLower().Contains("bool"))
{
p.Type.BaseType = s.BaseType;
}
}
else
{
p.Type.BaseType = s.BaseType;
}
}
if (p.Type.ArrayRank == 0 && p.Type.BaseType.ToLower().Contains("enums."))
{
// Do nothing
}
else if (p.Type.ArrayRank > 0 && p.Type.BaseType.Contains("char") ||
p.Type.ArrayRank == 0 && p.Type.BaseType.ToLower().Contains("string"))
{
// GLchar[] parameters should become (in) string or (out) StringBuilder
if (p.Direction == FieldDirection.Out || p.Direction == FieldDirection.Ref)
p.Type = new CodeTypeReference("System.Text.StringBuilder");
else
p.Type = new CodeTypeReference("System.String");
}
else if (p.Type.ArrayRank > 0 && p.Type.BaseType.ToLower().Contains("string"))
{
// string parameters do not need special wrappers. We add this here
// to simplify the next if-statements.
// p.Type.ArrayRank = 0;
}
else if (p.Type.ArrayRank > 0)
{
// All other array parameters need wrappers (around IntPtr).
if (p.Type.BaseType.Contains("void") || p.Type.BaseType.Contains("Void"))
{
p.UserData.Add("Wrapper", WrapperTypes.GenericParameter);
}
else
{
p.UserData.Add("Wrapper", WrapperTypes.ArrayParameter);
p.UserData.Add("OriginalType", new string(p.Type.BaseType.ToCharArray()));
}
// We do not want an array of IntPtrs (IntPtr[]) - it is the IntPtr that points to the array.
p.Type = new CodeTypeReference();
p.Type.BaseType = "System.IntPtr";
p.Type.ArrayRank = 0;
// The same wrapper works for either in or out parameters.
//p.CustomAttributes.Add(new CodeAttributeDeclaration("In, Out"));
}
else if (p.Type.BaseType.Contains("ushort") && d.Name.Contains("LineStipple"))
{
// glLineStipple needs wrapper to allow large unsigned mask values.
p.UserData.Add("Wrapper", WrapperTypes.UncheckedParameter);
}
if (p.Type.BaseType.ToLower().Contains("boolean"))
{
p.Type.BaseType = "System.Boolean";
//p.UserData.Add("Wrapper", WrapperTypes.BoolParameter);
p.CustomAttributes.Add(
new CodeAttributeDeclaration(
"MarshalAs",
new CodeAttributeArgument(new CodeSnippetExpression("UnmanagedType.Bool"))
)
);
}
if (p.UserData.Contains("Wrapper") && !d.UserData.Contains("Wrapper"))
{
// If there is at least 1 parameter that needs wrappers, mark the funcction for wrapping.
d.UserData.Add("Wrapper", null);
}
p.Direction = FieldDirection.In;
}
}
#endregion
private static bool Search(CodeTypeDeclarationCollection enums, string name)
{
foreach (CodeTypeDeclaration enumerant in enums)
{
if (enumerant.Name == name)
{
return true;
}
}
return false;
}
#region private static List<CodeMemberMethod> CreateWrappers(CodeTypeDelegate d)
private static List<CodeMemberMethod> CreateWrappers(CodeTypeDelegate d)
{
List<CodeMemberMethod> wrappers = new List<CodeMemberMethod>();
CodeMemberMethod f = new CodeMemberMethod();
// Check if a wrapper is needed:
if (!d.UserData.Contains("Wrapper"))
{
// If not, add just add a function that calls the delegate.
f = CreatePrototype(d);
if (!f.ReturnType.BaseType.Contains("Void"))
f.Statements.Add(new CodeMethodReturnStatement(GenerateInvokeExpression(f)));
else
f.Statements.Add(GenerateInvokeExpression(f));
wrappers.Add(f);
}
else
{
// We have to add wrappers for all possible WrapperTypes.
// First, check if the return type needs wrapping:
if (d.ReturnType.UserData.Contains("Wrapper"))
{
switch ((WrapperTypes)d.ReturnType.UserData["Wrapper"])
{
// If the function returns a string (glGetString) we must manually marshal it
// using Marshal.PtrToStringXXX. Otherwise, the GC will try to free the memory
// used by the string, resulting in corruption (the memory belongs to the
// unmanaged boundary).
case WrapperTypes.StringReturnValue:
f = CreatePrototype(d);
f.ReturnType = new CodeTypeReference("System.String");
f.Statements.Add(
new CodeMethodReturnStatement(
new CodeMethodInvokeExpression(
new CodeTypeReferenceExpression("Marshal"),
"PtrToStringAnsi",
new CodeExpression[] { GenerateInvokeExpression(f) }
)
)
);
wrappers.Add(f);
break;
// If the function returns a void* (GenericReturnValue), we'll have to return an IntPtr.
// The user will unfortunately need to marshal this IntPtr to a data type manually.
case WrapperTypes.GenericReturnValue:
f = CreatePrototype(d);
if (!f.ReturnType.BaseType.Contains("Void"))
f.Statements.Add(new CodeMethodReturnStatement(GenerateInvokeExpression(f)));
else
f.Statements.Add(GenerateInvokeExpression(f));
wrappers.Add(f);
break;
}
}
if (d.Name.Contains("LineStipple"))
{
// glLineStipple accepts a GLushort bitfield. Since GLushort is mapped to Int16, not UInt16
// (for CLS compliance), we'll have to add the unchecked keyword.
f = CreatePrototype(d);
CodeSnippetExpression e =
new CodeSnippetExpression("Delegates.glLineStipple(factor, unchecked((GLushort)pattern))");
f.Statements.Add(e);
wrappers.Add(f);
}
WrapPointersMonsterFunctionMK2(String.IsNullOrEmpty(f.Name) ? CreatePrototype(d) : f, wrappers);
}
return wrappers;
}
#endregion
#region private static void WrapPointersMonsterFunctionMK2(CodeTypeDelegate d, List<CodeMemberMethod> wrappers)
// This function needs some heavy refactoring. I'm ashamed I ever wrote it, but it works...
// What it does is this: it adds to the wrapper list all possible wrapper permutations
// for functions that have more than one IntPtr parameter. Example:
// "void Delegates.f(IntPtr p, IntPtr q)" where p and q are pointers to void arrays needs the following wrappers:
// "void f(IntPtr p, IntPtr q)"
// "void f(IntPtr p, object q)"
// "void f(object p, IntPtr q)"
// "void f(object p, object q)"
private static int count = 0;
private static void WrapPointersMonsterFunctionMK2(CodeMemberMethod f, List<CodeMemberMethod> wrappers)
{
if (count == 0)
{
bool functionContainsIntPtrParameters = false;
// Check if there are any IntPtr parameters (we may have come here from a ReturnType wrapper
// such as glGetString, which contains no IntPtr parameters)
foreach (CodeParameterDeclarationExpression p in f.Parameters)
{
if (p.Type.BaseType.Contains("IntPtr"))
{
functionContainsIntPtrParameters = true;
break;
}
}
if (functionContainsIntPtrParameters)
{
wrappers.Add(IntPtrToIntPtr(f));
}
else
{
return;
}
}
if (count >= 0 && count < f.Parameters.Count)
{
if (f.Parameters[count].UserData.Contains("Wrapper"))
{
//++count;
//WrapPointersMonsterFunctionMK2(d, wrappers);
//--count;
if ((WrapperTypes)f.Parameters[count].UserData["Wrapper"] == WrapperTypes.ArrayParameter)
{
++count;
WrapPointersMonsterFunctionMK2(f, wrappers);
--count;
CodeMemberMethod w = IntPtrToArray(f, count);
wrappers.Add(w);
++count;
WrapPointersMonsterFunctionMK2(w, wrappers);
--count;
/*w = IntPtrToReference(f, count);
wrappers.Add(w);
++count;
WrapPointersMonsterFunctionMK2(w, wrappers);
--count;*/
}
else if ((WrapperTypes)f.Parameters[count].UserData["Wrapper"] == WrapperTypes.GenericParameter)
{
++count;
WrapPointersMonsterFunctionMK2(f, wrappers);
--count;
CodeMemberMethod w = IntPtrToObject(f, count);
wrappers.Add(w);
++count;
WrapPointersMonsterFunctionMK2(w, wrappers);
--count;
}
}
else
{
++count;
WrapPointersMonsterFunctionMK2(f, wrappers);
--count;
}
}
}
#endregion
#region private static CodeMemberMethod IntPtrToIntPtr(CodeMemberMethod f)
private static CodeMemberMethod IntPtrToIntPtr(CodeMemberMethod f)
{
CodeMemberMethod w = CreatePrototype(f);
if (!w.ReturnType.BaseType.Contains("Void"))
{
w.Statements.Add(new CodeMethodReturnStatement(GenerateInvokeExpression(w)));
}
else
{
w.Statements.Add(GenerateInvokeExpression(w));
}
return w;
}
#endregion
#region private static CodeMemberMethod IntPtrToObject(CodeMemberMethod f, int index)
private static CodeMemberMethod IntPtrToObject(CodeMemberMethod f, int index)
{
CodeMemberMethod w = CreatePrototype(f);
CodeParameterDeclarationExpression newp = new CodeParameterDeclarationExpression();
newp.Name = f.Parameters[index].Name;
newp.Type = new CodeTypeReference("System.Object");
//if (newp.Flow == Parameter.FlowDirection.Out)
// newp.Flow = Parameter.FlowDirection.Undefined;
w.Parameters[index] = newp;
// In the function body we should pin all objects in memory before calling the
// low-level function.
w.Statements.AddRange(GenerateInvokeExpressionWithPins(w));
return w;
}
#endregion
#region private static CodeMemberMethod IntPtrToArray(CodeMemberMethod f, int index)
// IntPtr -> GL[...] wrapper.
private static CodeMemberMethod IntPtrToArray(CodeMemberMethod f, int index)
{
CodeMemberMethod w = CreatePrototype(f);
// Search and replace IntPtr parameters with the known parameter types:
CodeParameterDeclarationExpression newp = new CodeParameterDeclarationExpression();
newp.Name = f.Parameters[index].Name;
newp.Type.BaseType = (string)f.Parameters[index].UserData["OriginalType"];
newp.Type.ArrayRank = 1;
w.Parameters[index] = newp;
// In the function body we should pin all objects in memory before calling the
// low-level function.
w.Statements.AddRange(GenerateInvokeExpressionWithPins(w));
return w;
}
#endregion
#region private static CodeMemberMethod IntPtrToReference(CodeMemberMethod f, int index)
/// <summary>
/// This function is not working yet! How can we obtain a pinned IntPtr from a ref
/// without resorting to unsafe code?
/// </summary>
/// <param name="f"></param>
/// <param name="index"></param>
/// <returns></returns>
private static CodeMemberMethod IntPtrToReference(CodeMemberMethod f, int index)
{
CodeMemberMethod w = CreatePrototype(f);
// Search and replace IntPtr parameters with the known parameter types:
CodeParameterDeclarationExpression newp = new CodeParameterDeclarationExpression();
newp.Name = f.Parameters[index].Name;
newp.Type.BaseType = (string)f.Parameters[index].UserData["OriginalType"];
newp.Direction = FieldDirection.Ref;
w.Parameters[index] = newp;
// In the function body we should pin all objects in memory before calling the
// low-level function.
w.Statements.AddRange(GenerateInvokeExpressionWithPins(w));
return w;
}
#endregion
#region private static CodeMemberMethod CreatePrototype(CodeTypeDelegate d)
private static CodeMemberMethod CreatePrototype(CodeTypeDelegate d)
{
CodeMemberMethod f = new CodeMemberMethod();
f.Name = Settings.GLFunctionPrepend + d.Name;
f.Parameters.AddRange(d.Parameters);
f.ReturnType = d.ReturnType;
f.Attributes = MemberAttributes.Static | MemberAttributes.Public;
//f.StartDirectives.Add(new CodeRegionDirective(CodeRegionMode.Start, f.Name));
//f.EndDirectives.Add(new CodeRegionDirective(CodeRegionMode.End, f.Name));
/*f.Comments.Add(new CodeCommentStatement("<summary>", true));
f.Comments.Add(new CodeCommentStatement(" ", true));
f.Comments.Add(new CodeCommentStatement("</summary>", true));*/
return f;
}
#endregion
#region private static CodeMemberMethod CreatePrototype(CodeMemberMethod d)
private static CodeMemberMethod CreatePrototype(CodeMemberMethod d)
{
CodeMemberMethod f = new CodeMemberMethod();
f.Name = d.Name;
f.Parameters.AddRange(d.Parameters);
f.ReturnType = d.ReturnType;
f.Attributes = MemberAttributes.Static | MemberAttributes.Public;
//f.StartDirectives.Add(new CodeRegionDirective(CodeRegionMode.Start, f.Name));
//f.EndDirectives.Add(new CodeRegionDirective(CodeRegionMode.End, f.Name));
foreach (object key in d.UserData.Keys)
{
f.UserData.Add(key, d.UserData[key]);
}
/*f.Comments.Add(new CodeCommentStatement("<summary>", true));
f.Comments.Add(new CodeCommentStatement(" ", true));
f.Comments.Add(new CodeCommentStatement("</summary>", true));*/
return f;
}
#endregion
#region private static CodeExpression GenerateInvokeExpression(CodeMemberMethod f)
private static CodeExpression GenerateInvokeExpression(CodeMemberMethod f)
{
CodeVariableReferenceExpression[] parameters = new CodeVariableReferenceExpression[f.Parameters.Count];
int i = 0;
foreach (CodeParameterDeclarationExpression p in f.Parameters)
{
parameters[i++] = new CodeVariableReferenceExpression(p.Name);
}
return new CodeMethodInvokeExpression(
new CodeTypeReferenceExpression("Delegates"),
"gl" + f.Name,
parameters
);
}
#endregion
#region private static CodeStatementCollection GenerateInvokeExpressionWithPins(CodeMemberMethod f)
private static CodeStatementCollection GenerateInvokeExpressionWithPins(CodeMemberMethod f)
{
CodeVariableReferenceExpression[] parameters = new CodeVariableReferenceExpression[f.Parameters.Count];
CodeTryCatchFinallyStatement m = new CodeTryCatchFinallyStatement();
CodeStatementCollection statements = new CodeStatementCollection();
int h = 0;
int i = 0;
foreach (CodeParameterDeclarationExpression p in f.Parameters)
{
// Do manual marshalling for objects and arrays, but not strings.
if (p.Type.BaseType.ToLower().Contains("object") && !p.Type.BaseType.ToLower().Contains("enums.") ||
(p.Type.ArrayRank > 0 && !p.Type.BaseType.ToLower().Contains("string")))
{
// Pin the object and store the resulting GCHandle to h0, h1, ...
CodeVariableDeclarationStatement s = new CodeVariableDeclarationStatement();
s.Type = new CodeTypeReference("GCHandle");
s.Name = "h" + h;
s.InitExpression =
new CodeMethodInvokeExpression(
new CodeTypeReferenceExpression("GCHandle"),
"Alloc",
new CodeTypeReferenceExpression[] {
new CodeTypeReferenceExpression(p.Name),
new CodeTypeReferenceExpression("GCHandleType.Pinned")
}
);
statements.Add(s);
// Free the object using the h0, h1, ... variables
m.FinallyStatements.Add(
new CodeMethodInvokeExpression(
new CodeTypeReferenceExpression("h" + h),
"Free"
)
);
// Add the h(n) variable to the list of parameters
parameters[i] = new CodeVariableReferenceExpression("h" + h + ".AddrOfPinnedObject()");
h++;
}
else
{
// Add the normal paramater to the parameter list
parameters[i] = new CodeVariableReferenceExpression(p.Name);
}
i++;
}
if (!f.ReturnType.BaseType.Contains("Void"))
{
m.TryStatements.Add(
new CodeMethodReturnStatement(
new CodeMethodInvokeExpression(
new CodeTypeReferenceExpression("Delegates"),
"gl" + f.Name,
parameters
)
)
);
}
else
{
m.TryStatements.Add(
new CodeMethodInvokeExpression(
new CodeTypeReferenceExpression("Delegates"),
"gl" + f.Name,
parameters
)
);
}
statements.Add(m);
return statements;
}
#endregion
#region public static CodeTypeDeclarationCollection Merge(CodeTypeDeclarationCollection list1, CodeTypeDeclarationCollection list2)
public static CodeTypeDeclarationCollection Merge(CodeTypeDeclarationCollection list1, CodeTypeDeclarationCollection list2)
{
foreach (CodeTypeDeclaration d in list2)
{
Merge(list1, d);
}
return list1;
}
#endregion
#region public static CodeTypeDeclarationCollection Merge(CodeTypeDeclarationCollection list, CodeTypeDeclaration item)
public static CodeTypeDeclarationCollection Merge(CodeTypeDeclarationCollection list, CodeTypeDeclaration item)
{
bool t_exists = false;
foreach (CodeTypeDeclaration d in list)
{
if (d.Name == item.Name)
{
t_exists = true;
foreach (CodeTypeMember m in item.Members)
{
Merge(d.Members, m);
}
}
}
if (!t_exists)
{
list.Add(item);
}
return list;
}
#endregion
#region public static CodeTypeMemberCollection Merge(CodeTypeMemberCollection list, CodeTypeMember item)
public static CodeTypeMemberCollection Merge(CodeTypeMemberCollection list, CodeTypeMember item)
{
bool t_exists = false;
foreach (CodeTypeMember d in list)
{
if (d.Name == item.Name)
{
t_exists = true;
}
}
if (!t_exists)
{
list.Add(item);
}
return list;
}
#endregion
#region public static CodeTypeDeclarationCollection TranslateEnums(CodeTypeDeclarationCollection enums)
public static CodeTypeDeclarationCollection TranslateEnums(CodeTypeDeclarationCollection enums)
{
// Add missing enums.
{
CodeTypeDeclaration e = new CodeTypeDeclaration("SGIX_icc_texture");
e.IsEnum = true;
CodeMemberField c;
c = new CodeMemberField(); c.Name = "RGB_ICC_SGIX"; c.InitExpression = new CodeFieldReferenceExpression(null, "0x8460"); e.Members.Add(c);
c = new CodeMemberField(); c.Name = "RGBA_ICC_SGIX"; c.InitExpression = new CodeFieldReferenceExpression(null, "0x8461"); e.Members.Add(c);
c = new CodeMemberField(); c.Name = "ALPHA_ICC_SGIX"; c.InitExpression = new CodeFieldReferenceExpression(null, "0x8462"); e.Members.Add(c);
c = new CodeMemberField(); c.Name = "LUMINANCE_ICC_SGIX"; c.InitExpression = new CodeFieldReferenceExpression(null, "0x8463"); e.Members.Add(c);
c = new CodeMemberField(); c.Name = "INTENSITY_ICC_SGIX"; c.InitExpression = new CodeFieldReferenceExpression(null, "0x8464"); e.Members.Add(c);
c = new CodeMemberField(); c.Name = "LUMINANCE_ALPHA_ICC_SGIX"; c.InitExpression = new CodeFieldReferenceExpression(null, "0x8465"); e.Members.Add(c);
c = new CodeMemberField(); c.Name = "R5_G6_B5_ICC_SGIX"; c.InitExpression = new CodeFieldReferenceExpression(null, "0x8466"); e.Members.Add(c);
c = new CodeMemberField(); c.Name = "R5_G6_B5_A8_ICC_SGIX"; c.InitExpression = new CodeFieldReferenceExpression(null, "0x8467"); e.Members.Add(c);
c = new CodeMemberField(); c.Name = "ALPHA16_ICC_SGIX"; c.InitExpression = new CodeFieldReferenceExpression(null, "0x8468"); e.Members.Add(c);
c = new CodeMemberField(); c.Name = "LUMINANCE16_ICC_SGIX"; c.InitExpression = new CodeFieldReferenceExpression(null, "0x8469"); e.Members.Add(c);
c = new CodeMemberField(); c.Name = "INTENSITY16_ICC_SGIX"; c.InitExpression = new CodeFieldReferenceExpression(null, "0x846A"); e.Members.Add(c);
c = new CodeMemberField(); c.Name = "LUMINANCE16_ALPHA8_ICC_SGIX"; c.InitExpression = new CodeFieldReferenceExpression(null, "0x846B"); e.Members.Add(c);
enums.Add(e);
}
// Translate enums.
foreach (CodeTypeDeclaration e in enums)
{
if (Char.IsDigit(e.Name[0]))
e.Name = e.Name.Insert(0, "_");
if (e.Name == "Boolean")
continue;
foreach (CodeMemberField c in e.Members)
{
// Prepend an '_' if the first letter is a number (e.g. 4_BYTES -> _4_BYTES)
if (Char.IsDigit(c.Name[0]))
c.Name = c.Name.Insert(0, "_");
if (c.UserData["FieldReference"] == null)
continue;
c.UserData["ObjectReference"] = GetTranslatedEnum((string)c.UserData["ObjectReference"]);
c.UserData["FieldReference"] = GetTranslatedEnum((string)c.UserData["FieldReference"]);
// There are cases when a value is not a number but an aliased constant, with no enum specified.
// In this case try searching all enums for the correct constant to alias (stupid opengl specs).
if (c.UserData["ObjectReference"] == null &&
!((string)c.UserData["FieldReference"]).StartsWith("0x") &&
!Char.IsDigit(((string)c.UserData["FieldReference"])[0]))
{
if (((string)c.UserData["FieldReference"]).StartsWith("GL_"))
c.UserData["FieldReference"] = ((string)c.UserData["FieldReference"]).Substring(3);
foreach (CodeTypeDeclaration enumerant in enums)
{
foreach (CodeTypeMember member in enumerant.Members)
{
if (member.Name == (string)c.UserData["FieldReference"] ||
member.Name == ((string)c.UserData["FieldReference"]).TrimStart('_'))
{
c.UserData["ObjectReference"] = enumerant.Name;
}
}
}
}
c.InitExpression =
new CodeFieldReferenceExpression(
c.UserData["ObjectReference"] == null ? null : new CodeSnippetExpression((string)c.UserData["ObjectReference"]),
(string)c.UserData["FieldReference"]
);
}
}
return enums;
}
#endregion
#region public static string GetTranslatedEnum(string name)
public static string GetTranslatedEnum(string name)
{
int useless;
if (String.IsNullOrEmpty(name))
return null;
// Check if the name starts with a number, and prepend a "_" if yes.
if (!name.StartsWith("0x") &&
!Int32.TryParse(name, out useless) &&
Char.IsDigit(name[0]))
{
return name.Insert(0, "_");
}
if (name == "LightProperty")
{
return "LightParameter";
}
return name;
}
#endregion
}
}

View file

@ -0,0 +1,337 @@
#region License
/*
MIT License
Copyright ©2003-2006 Tao Framework Team
http://www.taoframework.com
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#endregion License
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using System.CodeDom;
namespace OpenTK.OpenGL.Bind
{
static class SpecWriter
{
#region internal class CodeTypeNameComparer<T> : Comparer<T> where T : CodeTypeMember
internal class CodeTypeNameComparer<T> : Comparer<T> where T : CodeTypeMember
{
public override int Compare(T x, T y)
{
return x.Name.CompareTo(y.Name);
}
}
#endregion
#region Generate
public static void Generate(
List<CodeTypeDelegate> delegates,
List<CodeMemberMethod> functions,
CodeTypeDeclarationCollection enums
)
{
if (!Directory.Exists(Settings.OutputPath))
Directory.CreateDirectory(Settings.OutputPath);
CodeNamespace ns = new CodeNamespace(Settings.OutputNamespace);
ns.Imports.Add(new CodeNamespaceImport("System"));
ns.Imports.Add(new CodeNamespaceImport("System.Runtime.InteropServices"));
ns.Imports.Add(new CodeNamespaceImport("System.Text"));
//ns.Imports.Add(new CodeNamespaceImport(Settings.OutputNamespace + ".Enums"));
foreach (string key in SpecTranslator.CSTypes.Keys)
{
ns.Imports.Add(new CodeNamespaceImport(key + " = System." + SpecTranslator.CSTypes[key].BaseType));
}
functions.Sort(new CodeTypeNameComparer<CodeMemberMethod>());
delegates.Sort(new CodeTypeNameComparer<CodeTypeDelegate>());
ns.Types.Add(GenerateGLClass(functions));
ns.Types.Add(GenerateDelegatesClass(delegates));
ns.Types.Add(GenerateImportsClass(delegates));
CodeCompileUnit cu = new CodeCompileUnit();
cu.StartDirectives.Add(new CodeDirective());
cu.Namespaces.Add(ns);
using (StreamWriter sw = new StreamWriter(Path.Combine(Settings.OutputPath, Settings.GLClass + ".cs"), false))
{
Console.WriteLine("Writing {0} class", Settings.OutputNamespace + "." + Settings.GLClass);
Microsoft.CSharp.CSharpCodeProvider cs = new Microsoft.CSharp.CSharpCodeProvider();
System.CodeDom.Compiler.CodeGeneratorOptions options = new System.CodeDom.Compiler.CodeGeneratorOptions();
options.BracingStyle = "C";
options.BlankLinesBetweenMembers = false;
options.VerbatimOrder = true;
cs.GenerateCodeFromCompileUnit(cu, sw, options);
sw.Flush();
}
ns.Name = Settings.OutputNamespace + ".Enums";
ns.Imports.Clear();
ns.Imports.Add(new CodeNamespaceImport("System"));
ns.Types.Clear();
//enums.Sort(new CodeTypeNameComparer<CodeTypeDeclaration>());
//CodeTypeDeclaration d = new CodeTypeDeclaration("Enums");
//d.IsStruct = true;
//d.Members.AddRange(enums);
//ns.Types.Add(d);
ns.Types.AddRange(enums);
using (StreamWriter sw = new StreamWriter(Path.Combine(Settings.OutputPath, Settings.GLClass + "enums.cs"), false))
{
Console.WriteLine("Writing {0} enums", Settings.OutputNamespace + "." + Settings.GLClass);
Microsoft.CSharp.CSharpCodeProvider cs = new Microsoft.CSharp.CSharpCodeProvider();
System.CodeDom.Compiler.CodeGeneratorOptions options = new System.CodeDom.Compiler.CodeGeneratorOptions();
options.BracingStyle = "C";
options.BlankLinesBetweenMembers = false;
options.VerbatimOrder = true;
cs.GenerateCodeFromCompileUnit(cu, sw, options);
sw.Flush();
}
}
#endregion
#region private static CodeTypeDeclaration GenerateGLClass(List<CodeMemberMethod> functions, List<CodeMemberField> enums)
private static CodeTypeDeclaration GenerateGLClass(List<CodeMemberMethod> functions)
{
CodeTypeDeclaration gl_class = new CodeTypeDeclaration(Settings.GLClass);
gl_class.IsClass = true;
gl_class.IsPartial = true;
gl_class.TypeAttributes = System.Reflection.TypeAttributes.Public;
gl_class.StartDirectives.Add(new CodeRegionDirective(CodeRegionMode.Start, "GL class"));
gl_class.EndDirectives.Add(new CodeRegionDirective(CodeRegionMode.End, "GL class"));
gl_class.Members.Add(new CodeSnippetTypeMember(" #pragma warning disable 1591"));
gl_class.Members.Add(new CodeSnippetTypeMember(
@"
#region Private Constants
#region string GL_NATIVE_LIBRARY
/// <summary>
/// Specifies OpenGl's native library archive.
/// </summary>
/// <remarks>
/// Specifies opengl32.dll everywhere; will be mapped via .config for mono.
/// </remarks>
internal const string GL_NATIVE_LIBRARY = ""opengl32.dll"";
#endregion string GL_NATIVE_LIBRARY
#endregion Private Constants
"));
/*
if (constants.Count > 0)
{
constants[0].StartDirectives.Add(new CodeRegionDirective(CodeRegionMode.Start, "OpenGL constants"));
constants[constants.Count - 1].EndDirectives.Add(new CodeRegionDirective(CodeRegionMode.End, "OpenGL constants"));
}
gl_class.Members.AddRange(constants.ToArray());
*/
if (functions.Count > 0)
{
functions[0].StartDirectives.Add(new CodeRegionDirective(CodeRegionMode.Start, "OpenGL functions"));
functions[functions.Count - 1].EndDirectives.Add(new CodeRegionDirective(CodeRegionMode.End, "OpenGL functions"));
}
gl_class.Members.AddRange(functions.ToArray());
return gl_class;
}
#endregion
#region private static CodeTypeDeclaration GenerateDelegatesClass(List<CodeTypeDelegate> delegates)
private static CodeTypeDeclaration GenerateDelegatesClass(List<CodeTypeDelegate> delegates)
{
CodeTypeDeclaration delegate_class = new CodeTypeDeclaration("Delegates");
delegate_class.TypeAttributes = System.Reflection.TypeAttributes.NotPublic;
CodeStatementCollection statements = new CodeStatementCollection();
foreach (CodeTypeDelegate d in delegates)
{
delegate_class.Members.Add(d);
CodeMemberField m = new CodeMemberField();
m.Name = "gl" + d.Name;
m.Type = new CodeTypeReference(d.Name);
m.Attributes = MemberAttributes.Public | MemberAttributes.Static;
//m.InitExpression =
//new CodeCastExpression(
// "Delegates." + d.Name,
// new CodeMethodInvokeExpression(
// new CodeMethodReferenceExpression(
// new CodeTypeReferenceExpression(Properties.Bind.Default.OutputClass),
// "GetDelegateForExtensionMethod"
// ),
// new CodeExpression[] {
// new CodeSnippetExpression("\"gl" + d.Name + "\""),
// new CodeTypeOfExpression("Delegates." + d.Name)
// }
// )
//);
// Hack - generate inline initialisers in the form:
// public static Accum glAccum = GetDelegate[...] ?? new Accum(Imports.Accum);
CodeSnippetExpression expr = new CodeSnippetExpression();
//expr.Value = "public static " + d.Name + " gl" + d.Name + " = ";
expr.Value +=
"((" + d.Name + ")(" + Settings.GLClass +".GetDelegateForExtensionMethod(\"" + "gl" + d.Name + "\", typeof(" + d.Name + "))))";
if (d.UserData.Contains("Extension") && !(bool)d.UserData["Extension"])
{
expr.Value += " ?? ";
expr.Value += "new " + d.Name + "(Imports." + d.Name + ")";
}
m.InitExpression = expr;
delegate_class.Members.Add(m);
/*
if (!(bool)d.UserData["Extension"])
{
statements.Add(
new CodeSnippetExpression(
"Delegates.gl" + d.Name + " = Delegates.gl" + d.Name + " ?? new Delegates." + d.Name + "(Imports." + d.Name + ")"
)
);
}
*/
}
// Disable BeforeFieldInit attribute and initialize OpenGL core.
CodeTypeConstructor con = new CodeTypeConstructor();
//con.Statements.AddRange(statements);
delegate_class.Members.Add(con);
delegate_class.StartDirectives.Add(new CodeRegionDirective(CodeRegionMode.Start, delegate_class.Name));
delegate_class.EndDirectives.Add(new CodeRegionDirective(CodeRegionMode.End, delegate_class.Name));
return delegate_class;
}
#endregion
#region private static CodeTypeDeclaration GenerateImportsClass(List<CodeTypeDelegate> delegates)
private static CodeTypeDeclaration GenerateImportsClass(List<CodeTypeDelegate> delegates)
{
CodeTypeDeclaration import_class = new CodeTypeDeclaration("Imports");
import_class.TypeAttributes = System.Reflection.TypeAttributes.NotPublic;
import_class.Members.Add(new CodeTypeConstructor());
foreach (CodeTypeDelegate d in delegates)
{
if (!(bool)d.UserData["Extension"])
{
CodeMemberMethodImport m = new CodeMemberMethodImport();
m.Name = d.Name;
m.CustomAttributes.Add(new CodeAttributeDeclaration("System.Security.SuppressUnmanagedCodeSecurity()"));
m.CustomAttributes.Add(
new CodeAttributeDeclaration(
"DllImport(" + Settings.GLClass + ".GL_NATIVE_LIBRARY, EntryPoint = \"" + "gl" + m.Name + "\", ExactSpelling = true)"
)
);
m.Parameters.AddRange(d.Parameters);
m.ReturnType = d.ReturnType;
import_class.Members.Add(new CodeSnippetTypeMember(m.Text));
}
}
import_class.StartDirectives.Add(new CodeRegionDirective(CodeRegionMode.Start, import_class.Name));
import_class.EndDirectives.Add(new CodeRegionDirective(CodeRegionMode.End, import_class.Name));
return import_class;
}
#endregion
}
#region class CodeMemberMethodImport : CodeMemberMethod
/// <summary>
/// A hack to create the C# code for a DllImported function;
/// CodeDom does not directly support static extern methods.
/// </summary>
class CodeMemberMethodImport : CodeMemberMethod
{
public string Text
{
get
{
string s;
//m.Attributes = MemberAttributes.Static | MemberAttributes.Public;
s = " #region " + this.Name + Environment.NewLine;
s += " [System.Security.SuppressUnmanagedCodeSecurity()]" + Environment.NewLine;
s += " [DllImport(" + Settings.GLClass + ".GL_NATIVE_LIBRARY, EntryPoint = \"" + "gl" + this.Name + "\", ExactSpelling = true)]" + Environment.NewLine;
s += " public extern static ";
if (this.ReturnType.BaseType == "System.Void")
{
s += "void";
}
else
{
s += this.ReturnType.BaseType;
}
s += " " + this.Name + "(";
foreach (CodeParameterDeclarationExpression p in this.Parameters)
{
s += p.Type.BaseType;
if (p.Type.ArrayRank > 0)
s += "[]";
s += " ";
if (p.Name == "base")
s += "@base";
else if (p.Name == "params")
s += "@params";
else if (p.Name == "string")
s += "@string";
else if (p.Name == "ref")
s += "@ref";
else
s += p.Name;
s += ", ";
}
s = s.TrimEnd(',', ' ') + ");" + Environment.NewLine;
s += " #endregion" + Environment.NewLine;
return s;
}
}
}
#endregion
}

View file

@ -1,496 +0,0 @@
#region License
//Copyright (c) 2006 Stephen Apostolopoulos
//See license.txt for license info
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace OpenTK.OpenGL.Bind
{
#region WrapperTypes enum
public enum WrapperTypes
{
None,
VoidArray,
Array,
UncheckedParameter,
ReturnsString,
ReturnsVoidPointer,
}
#endregion
static class Translation
{
public static char[] Separators = { ' ', '\n', ',', '(', ')', ';', '#' };
#region Dictionaries
static Dictionary<string, string> parameter_names = new Dictionary<string, string>();
#region GL types dictionary
private static Dictionary<string, string> _gl_types;
public static Dictionary<string, string> GLTypes
{
get { return Translation._gl_types; }
set { Translation._gl_types = value; }
}
#endregion
#region CS types dictionary
private static Dictionary<string, string> _cs_types;
public static Dictionary<string, string> CSTypes
{
get { return Translation._cs_types; }
set { Translation._cs_types = value; }
}
#endregion
#region GLX types dictionary
private static Dictionary<string, string> _glx_types;
public static Dictionary<string, string> GLXTypes
{
get { return _glx_types; }
set { _glx_types = value; }
}
#endregion
#region WGL types dictionary
private static Dictionary<string, string> _wgl_types;
public static Dictionary<string, string> WGLTypes
{
get { return _wgl_types; }
set { _wgl_types = value; }
}
#endregion
#endregion
#region Constructor
static Translation()
{
// Names
parameter_names.Add("base", "@base");
parameter_names.Add("object", "@object");
parameter_names.Add("string", "@string");
parameter_names.Add("ref", "reference");
parameter_names.Add("params", "parameters");
parameter_names.Add("in", "@in");
parameter_names.Add("class", "@class");
}
#endregion
#region Translate enums
public static void TranslateEnums(System.Collections.Hashtable enums)
{
// Add missing enums.
{
Enum e = new Enum();
Constant c;
e.Name = "SGIX_icc_texture";
c = new Constant("RGB_ICC_SGIX", "0x8460"); e.ConstantCollection.Add(c.Name, c);
c = new Constant("RGBA_ICC_SGIX", "0x8461"); e.ConstantCollection.Add(c.Name, c);
c = new Constant("ALPHA_ICC_SGIX", "0x8462"); e.ConstantCollection.Add(c.Name, c);
c = new Constant("LUMINANCE_ICC_SGIX", "0x8463"); e.ConstantCollection.Add(c.Name, c);
c = new Constant("INTENSITY_ICC_SGIX", "0x8464"); e.ConstantCollection.Add(c.Name, c);
c = new Constant("LUMINANCE_ALPHA_ICC_SGIX", "0x8465"); e.ConstantCollection.Add(c.Name, c);
c = new Constant("R5_G6_B5_ICC_SGIX", "0x8466"); e.ConstantCollection.Add(c.Name, c);
c = new Constant("R5_G6_B5_A8_ICC_SGIX", "0x8467"); e.ConstantCollection.Add(c.Name, c);
c = new Constant("ALPHA16_ICC_SGIX", "0x8468"); e.ConstantCollection.Add(c.Name, c);
c = new Constant("LUMINANCE16_ICC_SGIX", "0x8469"); e.ConstantCollection.Add(c.Name, c);
c = new Constant("INTENSITY16_ICC_SGIX", "0x846A"); e.ConstantCollection.Add(c.Name, c);
c = new Constant("LUMINANCE16_ALPHA8_ICC_SGIX", "0x846B"); e.ConstantCollection.Add(c.Name, c);
enums.Add(e.Name, e);
}
// Translate enums.
foreach (Enum e in enums.Values)
{
if (Char.IsDigit(e.Name[0]))
e.Name = e.Name.Insert(0, "_");
if (e.Name == "Boolean")
continue;
foreach (Constant c in e.ConstantCollection.Values)
{
// Prepend an '_' if the first letter is a number (e.g. 4_BYTES -> _4_BYTES)
if (Char.IsDigit(c.Name[0]))
c.Name = c.Name.Insert(0, "_");
// Prepend an '_' to the aliased value, if it starts with a number (e.g. DataType.4_BYTES -> DataType._4_BYTES)
if (c.Value.Contains(".") && Char.IsDigit(c.Value[c.Value.IndexOf('.') + 1]))
c.Value = c.Value.Insert(c.Value.IndexOf('.') + 1, "_");
// There are cases when a value is not a number but an aliased constant, with no enum specified.
// In this case try searching all enums for the correct constant to alias (stupid opengl group).
if (!c.Value.Contains(".") && !c.Value.StartsWith("0x") && !Char.IsDigit(c.Value[0]))
{
if (c.Value.StartsWith("GL_"))
c.Value = c.Value.TrimStart('G', 'L', '_');
if (Char.IsDigit(c.Value[0]))
c.Value = c.Value.Insert(0, "_");
foreach (Enum search_enum in enums.Values)
foreach (Constant search_constant in search_enum.ConstantCollection.Values)
if (search_constant.Name == c.Value || search_constant.Name == c.Value.TrimStart('_'))
c.Value = c.Value.Insert(0, search_enum.Name + ".");
}
// Handle enum.spec bugs:
if (c.Value.Contains("LightProperty"))
c.Value = c.Value.Replace("LightProperty", "LightParameter");
}
}
}
#endregion
#region Translate functions
public static void TranslateFunctions(List<Function> functions, Hashtable enums, out List<Function> wrappers)
{
foreach (Function f in functions)
{
TranslateReturnValue(f, enums);
TranslateParameters(f, enums);
if (f.NeedsWrapper)
f.Name = f.Name + "_";
}
wrappers = GenerateWrappers(functions);
}
#region Translate return value
private static void TranslateReturnValue(Function f, Hashtable enums)
{
string s;
if (f.ReturnValue == "void")
return;
if (GLTypes.TryGetValue(f.ReturnValue, out s))
f.ReturnValue = s;
if (f.ReturnValue == "void[]")
{
f.NeedsWrapper = true;
f.WrapperType = WrapperTypes.ReturnsVoidPointer;
f.ReturnValue = "IntPtr";
}
if (f.ReturnValue == "GLstring")
{
f.NeedsWrapper = true;
f.WrapperType = WrapperTypes.ReturnsString;
f.ReturnValue = "IntPtr";
}
}
#endregion
#region Translate parameters
private static void TranslateParameters(Function f, Hashtable enums)
{
string s;
foreach (Parameter p in f.Parameters) // Translate each parameter of the function, and check for needed wrappers.
{
#region Translate parameter name
if (parameter_names.TryGetValue(p.Name, out s))
p.Name = s;
#endregion
#region Translate parameter type
//if (p.Type.Contains("Boolean"))
//{
// p.Type = "GLboolean";
//}
if (enums.ContainsKey(p.Type))
{
p.Type = "Enums." + p.Type;
}
else if (p.Type == "GLenum")
{
if (enums.ContainsKey(f.Category))
p.Type = "Enums." + f.Category;
}
else if (GLTypes.TryGetValue(p.Type, out s))
p.Type = s;
#endregion
#region Check for needed wrappers
if (p.Type.Contains("ushort") && f.Name.Contains("LineStipple")) // glLineStipple needs wrapper to allow for unchecked mask values.
{
p.NeedsWrapper = true;
p.WrapperType = WrapperTypes.UncheckedParameter;
p.Unchecked = true;
}
else if (p.Array && p.Type.Contains("string")) // string parameters do not need special wrappers.
{
p.NeedsWrapper = false;
p.WrapperType = WrapperTypes.None;
}
else if (p.Array && p.Type.Contains("char")) // GLchar[] parameters should become (in) string or (out) StringBuilder
{
if (p.Flow == Parameter.FlowDirection.Out)
p.Type = "StringBuilder";
else
p.Type = "string";
p.Array = false;
}
else if (p.Array) // All other array parameters need wrappers (around IntPtr).
{
p.NeedsWrapper = true;
if (p.Type.Contains("void"))
p.WrapperType = WrapperTypes.VoidArray;
else
p.WrapperType = WrapperTypes.Array;
p.Type = "IntPtr";
p.Array = false; // We do not want an array of IntPtrs (IntPtr[]) - it is the IntPtr that points to the array.
p.Flow = Parameter.FlowDirection.Undefined; // The same wrapper works for either in or out parameters.
}
if (p.NeedsWrapper) // If there is at least 1 parameter that needs wrappers, mark the funcction for wrapping.
{
f.NeedsWrapper = true;
f.WrapperType = p.WrapperType;
}
#endregion
}
}
#endregion
#region Generate wrappers
private static List<Function> GenerateWrappers(List<Function> functions)
{
List<Function> wrappers = new List<Function>();
Function w;
foreach (Function f in functions)
{
if (f.NeedsWrapper)
{
if (f.WrapperType == WrapperTypes.UncheckedParameter)
{
w = new Function(f);
w.Name = w.Name.TrimEnd('_');
// Search and replace ushort parameters with ints.
Predicate<Parameter> is_ushort_parameter = new Predicate<Parameter>(delegate(Parameter p) { return p.Type == "GLushort"; });
Parameter oldp = w.Parameters.Find(is_ushort_parameter);
Parameter newp = new Parameter(oldp);
newp.Type = "GLint";
w.Parameters = w.Parameters.ReplaceAll(oldp, newp);
// Call the low-level function wrapping (all parameters marked with Unchecked will automatically
// be decorated with the unchecked keyword).
w.Body.Add((f.ReturnValue.Contains("void") ? "" : "return ") + f.CallString() + ";");
// Add the wrapper.
wrappers.Add(w);
continue;
}
if (f.WrapperType == WrapperTypes.ReturnsString)
{
w = new Function(f);
w.Name = w.Name.TrimEnd('_');
// Replace the IntPtr return value with string.
w.ReturnValue = "string";
// Wrap the call to the low-level function (marshal the IntPtr to string).
w.Body.Add("return Marshal.PtrToStringAnsi(" + f.CallString() + ");");
// Add the wrapper.
wrappers.Add(w);
continue;
}
//if (
WrapPointers(f, wrappers);
count = 0;
}
}
return wrappers;
}
static int count = 0;
private static void WrapPointers(Function f, List<Function> wrappers)
{
if (count == 0)
{
wrappers.Add(IntPtrToIntPtr(f));
}
if (count >= 0 && count < f.Parameters.Count)
{
if (f.Parameters[count].NeedsWrapper)
{
++count;
WrapPointers(f, wrappers);
--count;
Function w = IntPtrToObject(f, count);
wrappers.Add(w);
++count;
WrapPointers(w, wrappers);
--count;
if (f.Parameters[count].WrapperType == WrapperTypes.Array)
{
w = IntPtrToArray(f, count);
wrappers.Add(w);
++count;
WrapPointers(w, wrappers);
--count;
}
}
else
{
++count;
WrapPointers(f, wrappers);
--count;
}
}
}
// IntPtr -> IntPtr wrapper.
private static Function IntPtrToIntPtr(Function f)
{
Function w = new Function(f);
w.Name = w.Name.TrimEnd('_');
w.Body.Add((f.ReturnValue.Contains("void") ? "" : "return ") + f.CallString() + ";");
return w;
}
// IntPtr -> object wrapper.
private static Function IntPtrToObject(Function f, int index)
{
Function w = new Function(f);
w.Name = w.Name.TrimEnd('_');
Parameter newp = new Parameter(f.Parameters[index]);
newp.Type = "object";
if (newp.Flow == Parameter.FlowDirection.Out)
newp.Flow = Parameter.FlowDirection.Undefined;
w.Parameters = w.Parameters.Replace(f.Parameters[index], newp);
// In the function body we should pin all objects in memory before calling the
// low-level function.
w.Body = GenerateBodyForPins(w);
return w;
}
// IntPtr -> GL[...] wrapper.
private static Function IntPtrToArray(Function f, int index)
{
Function w = new Function(f);
w.Name = w.Name.TrimEnd('_');
// Search and replace IntPtr parameters with the know parameter types:
Parameter newp = new Parameter(f.Parameters[index]);
newp.Type = f.Parameters[index].PreviousType;
newp.Array = true;
w.Parameters = w.Parameters.Replace(f.Parameters[index], newp);
// In the function body we should pin all objects in memory before calling the
// low-level function.
w.Body = GenerateBodyForPins(w);
return w;
}
private static FunctionBody GenerateBodyForPins(Function w)
{
FunctionBody body = new FunctionBody();
int i = 0;
StringBuilder sb = new StringBuilder();
sb.Append("(");
foreach (Parameter p in w.Parameters)
{
if (p.Type == "object" || p.Array && !p.Type.Contains("string")) // we should allow the default marshalling behavior for strings.
{
body.Add("GCHandle h" + i + " = GCHandle.Alloc(" + p.Name + ", GCHandleType.Pinned);");
sb.Append("h" + i + ".AddrOfPinnedObject()" + ", ");
i++;
}
else
{
sb.Append(p.Name + ", ");
}
}
sb.Replace(", ", ")", sb.Length - 2, 2);
body.Add("try");
body.Add("{");
body.Add(
" " +
(w.ReturnValue.Contains("void") ? "" : "return ") +
w.Name + "_" +
sb.ToString() +
";");
body.Add("}");
body.Add("finally");
body.Add("{");
while (i > 0)
{
body.Add(" h" + --i + ".Free();");
}
body.Add("}");
return body;
}
#endregion
#endregion
}
}

View file

@ -1,457 +0,0 @@
#region License
//Copyright (c) 2006 Stephen Apostolopoulos
//See license.txt for license info
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using System.Collections;
namespace OpenTK.OpenGL.Bind
{
static partial class SpecWriter
{
#region Write specs
public static void WriteSpecs(string output_path, string class_name, List<Function> functions, List<Function> wrappers, Hashtable enums)
{
WriteEnumSpecs(output_path, class_name, enums);
WriteCoreFunctionSpecs(output_path, class_name, functions, wrappers);
WriteExtensionFunctionSpecs(output_path, class_name, functions, wrappers);
}
#endregion
#region Write extension function specs
private static void WriteExtensionFunctionSpecs(string output_path, string class_name, List<Function> functions, List<Function> wrappers)
{
//string filename = Path.Combine(output_path, class_name + "Extensions.cs");
//if (!Directory.Exists(output_path))
// Directory.CreateDirectory(output_path);
//StreamWriter sw = new StreamWriter(filename, false);
//Console.WriteLine("Writing {0} class to {1}", class_name, filename);
//WriteLicense(sw);
//WriteUsingDirectives(sw);
//sw.WriteLine("namespace {0}", Settings.OutputNamespace);
//sw.WriteLine("{");
//WriteTypes(sw);
//sw.WriteLine(" static public partial class {0}", class_name);
//sw.WriteLine(" {");
//sw.WriteLine(" static public class Extensions");
//sw.WriteLine(" {");
//WriteExtensionFunctionSignatures(sw, functions);
//WriteExtensionFunctions(sw, functions);
//WriteExtensionWrappers(sw, wrappers);
//sw.WriteLine(" }");
//sw.WriteLine(" }");
//sw.WriteLine("}");
//sw.WriteLine();
//sw.Flush();
//sw.Close();
}
#endregion
#region Write core function specs
private static void WriteCoreFunctionSpecs(string output_path, string class_name, List<Function> functions, List<Function> wrappers)
{
string filename = Path.Combine(output_path, class_name + ".cs");
if (!Directory.Exists(output_path))
Directory.CreateDirectory(output_path);
StreamWriter sw = new StreamWriter(filename, false);
Console.WriteLine("Writing {0} class to {1}", class_name, filename);
WriteLicense(sw);
WriteUsingDirectives(sw);
WriteTypes(sw);
sw.WriteLine("namespace {0}", Settings.OutputNamespace);
sw.WriteLine("{");
sw.WriteLine(" static public partial class {0}", class_name);
sw.WriteLine(" {");
WriteCoreFunctionSignatures(sw, functions);
WriteDllImports(sw, functions);
WriteCoreFunctions(sw, functions);
WriteCoreWrappers(sw, wrappers);
WriteCoreConstructor(sw, class_name, functions);
sw.WriteLine(" }");
sw.WriteLine("}");
sw.WriteLine();
sw.Flush();
sw.Close();
}
#endregion
#region Write enum specs
private static void WriteEnumSpecs(string output_path, string class_name, Hashtable enums)
{
string filename = Path.Combine(output_path, class_name + "Enums.cs");
if (!Directory.Exists(output_path))
Directory.CreateDirectory(output_path);
StreamWriter sw = new StreamWriter(filename, false);
Console.WriteLine("Writing {0} class to {1}", class_name, filename);
WriteLicense(sw);
WriteUsingDirectives(sw);
sw.WriteLine("namespace {0}", Settings.OutputNamespace);
sw.WriteLine("{");
WriteTypes(sw);
WriteEnums(sw, enums);
sw.WriteLine("}");
sw.WriteLine();
sw.Flush();
sw.Close();
}
#endregion
#region Write license
public static void WriteLicense(StreamWriter sw)
{
sw.WriteLine("#region License");
sw.WriteLine("//THIS FILE IS AUTOMATICALLY GENERATED");
sw.WriteLine("//DO NOT EDIT BY HAND!!");
sw.WriteLine("//See license.txt for license info");
sw.WriteLine("#endregion");
sw.WriteLine();
}
#endregion
#region Write using directivers
private static void WriteUsingDirectives(StreamWriter sw)
{
sw.WriteLine("using System;");
sw.WriteLine("using System.Runtime.InteropServices;");
sw.WriteLine("using System.Text;");
sw.WriteLine();
}
#endregion
#region Write types
private static void WriteTypes(StreamWriter sw)
{
sw.WriteLine(" #region Types");
//foreach ( c in constants)
foreach (string key in Translation.CSTypes.Keys)
{
sw.WriteLine(" using {0} = System.{1};", key, Translation.CSTypes[key]);
//sw.WriteLine(" public const {0};", c.ToString());
}
sw.WriteLine(" #endregion");
sw.WriteLine();
}
#endregion
#region Write enums
private static void WriteEnums(StreamWriter sw, Hashtable enums)
{
sw.WriteLine(" #region Enums");
sw.WriteLine(" public struct Enums");
sw.WriteLine(" {");
foreach (Enum e in enums.Values)
{
sw.WriteLine(e.ToString());
}
sw.WriteLine(" }");
sw.WriteLine(" #endregion");
sw.WriteLine();
}
#endregion
#region Write core function signatures
private static void WriteCoreFunctionSignatures(StreamWriter sw, List<Function> functions)
{
sw.WriteLine(" #region Function signatures");
sw.WriteLine();
sw.WriteLine(" public static class Delegates");
sw.WriteLine(" {");
foreach (Function f in functions)
{
if (f.Extension)
continue;
sw.WriteLine(" public delegate {0};", f.ToString());
}
sw.WriteLine(" }");
sw.WriteLine(" #endregion");
sw.WriteLine();
}
#endregion
#region Write core dll imports
private static void WriteDllImports(StreamWriter sw, List<Function> functions)
{
sw.WriteLine(" #region Imports");
sw.WriteLine();
sw.WriteLine(" internal class Imports");
sw.WriteLine(" {");
foreach (Function f in functions)
{
if (!f.Extension)
{
sw.WriteLine(" [DllImport(\"opengl32.dll\", EntryPoint = \"gl{0}\")]", f.Name.TrimEnd('_'));
sw.WriteLine(" public static extern {0};", f.ToString());
}
}
sw.WriteLine(" }");
sw.WriteLine(" #endregion");
sw.WriteLine();
}
#endregion
#region Write core functions
private static void WriteCoreFunctions(StreamWriter sw, List<Function> functions)
{
sw.WriteLine(" #region Static Functions (and static initialisation)");
sw.WriteLine();
foreach (Function f in functions)
{
if (f.Extension)
continue;
sw.WriteLine(" public static Delegates.{0} {0} = new Delegates.{0}(Imports.{0});", f.Name);
}
sw.WriteLine();
sw.WriteLine(" #endregion");
sw.WriteLine();
}
#endregion
#region Write core wrappers
public static void WriteCoreWrappers(StreamWriter sw, List<Function> wrappers)
{
sw.WriteLine(" #region Wrappers");
sw.WriteLine();
if (wrappers != null)
{
foreach (Function f in wrappers)
{
if (f.Extension)
continue;
sw.WriteLine(" #region {0}{1}", f.Name, f.Parameters.ToString());
sw.WriteLine();
sw.WriteLine(" public static");
sw.WriteLine(f.ToString(" "));
sw.WriteLine(" #endregion");
sw.WriteLine();
}
}
sw.WriteLine(" #endregion");
sw.WriteLine();
}
#endregion
#region Write core constructor
private static void WriteCoreConstructor(StreamWriter sw, string class_name, List<Function> functions)
{
sw.WriteLine(" #region static Constructor");
sw.WriteLine();
sw.WriteLine(" static {0}()", class_name);
sw.WriteLine(" {");
List<String> import_list = new List<string>();
#region Older Windows Core
// Load core for older windows versions.
sw.WriteLine(" if (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major < 6 || Environment.OSVersion.Platform == PlatformID.Win32Windows)");
sw.WriteLine(" {");
sw.WriteLine(" #region Older Windows Core");
import_list.Add("1.2");
import_list.Add("1.3");
import_list.Add("1.4");
import_list.Add("1.5");
import_list.Add("2.0");
import_list.Add("2.1");
foreach (Function f in functions)
{
if (!f.Extension)
if (import_list.Contains(f.Version))
sw.WriteLine(" {0} = (Delegates.{0})WindowsGetAddress(\"{1}\", typeof(Delegates.{0}));", f.Name, "gl"+ f.Name.TrimEnd('_'));
}
sw.WriteLine(" #endregion Older Windows Core");
sw.WriteLine(" }");
#endregion
#region Windows Vista Core
// Load core for windows vista.
sw.WriteLine(" else if (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= 6)");
sw.WriteLine(" {");
sw.WriteLine(" #region Windows Vista Core");
import_list.Remove("1.2");
import_list.Remove("1.3");
import_list.Remove("1.4");
foreach (Function f in functions)
{
if (!f.Extension)
if (import_list.Contains(f.Version))
sw.WriteLine(" {0} = (Delegates.{0})WindowsGetAddress(\"{1}\", typeof(Delegates.{0}));", f.Name, "gl" + f.Name.TrimEnd('_'));
}
sw.WriteLine(" #endregion Windows Vista Core");
sw.WriteLine(" }");
#endregion
#region X11 Core
// Load core for windows X11.
sw.WriteLine(" else if (Environment.OSVersion.Platform == PlatformID.Unix)");
sw.WriteLine(" {");
sw.WriteLine(" #region X11 Core");
import_list.Remove("1.5");
import_list.Remove("1.6");
import_list.Remove("2.0");
import_list.Remove("2.1");
foreach (Function f in functions)
{
if (!f.Extension)
if (import_list.Contains(f.Version))
sw.WriteLine(" {0} = (Delegates.{0})WindowsGetAddress(\"{1}\", typeof(Delegates.{0}));", f.Name, "gl" + f.Name.TrimEnd('_'));
}
sw.WriteLine(" #endregion X11 Core");
sw.WriteLine(" }");
#endregion
sw.WriteLine(" }");
sw.WriteLine(" #endregion static Constructor");
}
#endregion
#region Write extension function signatures
private static void WriteExtensionFunctionSignatures(StreamWriter sw, List<Function> functions)
{
sw.WriteLine(" #region Function signatures");
sw.WriteLine();
sw.WriteLine(" public static class Delegates");
sw.WriteLine(" {");
foreach (Function f in functions)
{
if (f.Extension)
sw.WriteLine(" public delegate {0};", f.ToString());
}
sw.WriteLine(" }");
sw.WriteLine(" #endregion");
sw.WriteLine();
}
#endregion
#region Write extension functions
private static void WriteExtensionFunctions(StreamWriter sw, List<Function> functions)
{
sw.WriteLine(" #region Static Functions (and static initialisation)");
sw.WriteLine();
foreach (Function f in functions)
{
if (f.Extension)
sw.WriteLine(" public static Delegates.{0} {0} = new Delegates.{0}(Imports.{0});", f.Name);
}
sw.WriteLine();
sw.WriteLine(" #endregion");
sw.WriteLine();
}
#endregion
#region Write extension wrappers
public static void WriteExtensionWrappers(StreamWriter sw, List<Function> wrappers)
{
sw.WriteLine(" #region Wrappers");
sw.WriteLine();
if (wrappers != null)
{
foreach (Function w in wrappers)
{
if (!w.Extension)
continue;
sw.WriteLine(" #region {0}{1}", w.Name, w.Parameters.ToString());
sw.WriteLine();
sw.WriteLine(" public static");
sw.WriteLine(w.ToString(" "));
sw.WriteLine(" #endregion");
sw.WriteLine();
}
}
sw.WriteLine(" #endregion");
}
#endregion
}
}