mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-07-06 02:00:41 +00:00
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:
parent
52cbe0c5a8
commit
3ff2b848e2
|
@ -1,7 +1,29 @@
|
||||||
#region License
|
#region License
|
||||||
//Copyright (c) 2006 Stephen Apostolopoulos
|
/*
|
||||||
//See license.txt for license info
|
MIT License
|
||||||
#endregion
|
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;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -10,18 +32,19 @@ using System.Security;
|
||||||
using System.Security.Permissions;
|
using System.Security.Permissions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections;
|
using System.CodeDom;
|
||||||
|
|
||||||
[assembly:CLSCompliant(true), FileIOPermission(SecurityAction.RequestMinimum, Unrestricted = true)]
|
|
||||||
namespace OpenTK.OpenGL.Bind
|
namespace OpenTK.OpenGL.Bind
|
||||||
{
|
{
|
||||||
static class MainClass
|
static class MainClass
|
||||||
{
|
{
|
||||||
static void Main(string[] arguments)
|
static void Main(string[] arguments)
|
||||||
{
|
{
|
||||||
Console.WriteLine("{0} {1} by Stephen Apostolopoulos (stapostol@gmail.com)",
|
Console.WriteLine("OpenGL binding generator {0} for OpenTK.",
|
||||||
System.Reflection.Assembly.GetExecutingAssembly().GetName().Name,
|
|
||||||
System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString());
|
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
|
#region Handle Arguments
|
||||||
|
|
||||||
|
@ -72,44 +95,28 @@ namespace OpenTK.OpenGL.Bind
|
||||||
{
|
{
|
||||||
long ticks = System.DateTime.Now.Ticks;
|
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");
|
delegates = SpecReader.ReadFunctionSpecs("gl.spec");
|
||||||
Translation.CSTypes = SpecReader.ReadTypeMap("csharp.tm");
|
SpecReader.ReadEnumSpecs("enum.spec", out enums);
|
||||||
|
SpecReader.ReadEnumSpecs("enumext.spec", out enums2);
|
||||||
|
enums = SpecTranslator.Merge(enums, enums2);
|
||||||
|
enums = SpecTranslator.TranslateEnums(enums);
|
||||||
|
|
||||||
List<Function> wrappers;
|
functions = SpecTranslator.TranslateDelegates(delegates, enums);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
Translation.TranslateFunctions(functions, enums, out wrappers);
|
// Generate the code
|
||||||
Translation.TranslateEnums(enums);
|
SpecWriter.Generate(delegates, functions, 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.
|
|
||||||
|
|
||||||
ticks = System.DateTime.Now.Ticks - ticks;
|
ticks = System.DateTime.Now.Ticks - ticks;
|
||||||
|
|
||||||
Console.WriteLine("Bindings generated in {0} seconds.", ticks / (double)10000000.0);
|
Console.WriteLine("Bindings generated in {0} seconds.", ticks / (double)10000000.0);
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("Press enter to continue...");
|
||||||
|
Console.ReadLine();
|
||||||
}
|
}
|
||||||
catch (SecurityException e)
|
catch (SecurityException e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
||||||
// Build Number
|
// Build Number
|
||||||
// Revision
|
// Revision
|
||||||
//
|
//
|
||||||
[assembly: AssemblyVersion("0.7.7.0")]
|
[assembly: AssemblyVersion("0.9.0.3")]
|
||||||
[assembly: AssemblyFileVersion("0.7.7.0")]
|
[assembly: AssemblyFileVersion("0.9.0.3")]
|
||||||
|
|
|
@ -13,7 +13,12 @@ namespace OpenTK.OpenGL.Bind
|
||||||
{
|
{
|
||||||
public static string InputPath = "..\\..\\..\\Source\\OpenGL\\Specifications";
|
public static string InputPath = "..\\..\\..\\Source\\OpenGL\\Specifications";
|
||||||
public static string OutputPath = "..\\..\\..\\Source\\OpenGL\\OpenGL\\Bindings";
|
public static string OutputPath = "..\\..\\..\\Source\\OpenGL\\OpenGL\\Bindings";
|
||||||
public static string GLClass = "GL";
|
|
||||||
public static string OutputNamespace = "OpenTK.OpenGL";
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
416
Source/OpenGL/Bind/SpecReader.cs
Normal file
416
Source/OpenGL/Bind/SpecReader.cs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
877
Source/OpenGL/Bind/SpecTranslator.cs
Normal file
877
Source/OpenGL/Bind/SpecTranslator.cs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
337
Source/OpenGL/Bind/SpecWriter.cs
Normal file
337
Source/OpenGL/Bind/SpecWriter.cs
Normal 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
|
||||||
|
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue