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