diff --git a/Source/Bind/CppSpecWriter.cs b/Source/Bind/CppSpecWriter.cs index 676d428a..631734ad 100644 --- a/Source/Bind/CppSpecWriter.cs +++ b/Source/Bind/CppSpecWriter.cs @@ -44,16 +44,224 @@ namespace Bind readonly char[] numbers = "0123456789".ToCharArray(); const string AllowDeprecated = "ALLOW_DEPRECATED_GL"; const string DigitPrefix = "T"; // Prefix for identifiers that start with a digit - const string OutputFileCpp = "glcore++.cpp"; - const string OutputFileHeader = "glcore++.h"; - const string OutputFileHeaderCompat = "glcompat++.h"; - const string OutputFileHeaderEnums = "glenums++.h"; + const string OutputFileHeader = "gl++.h"; + + #region Verbatim parts of output file + + const string GetAddressDefinition = @" + + namespace Internals + { + #if defined(_WIN32) + extern ""C"" + { + typedef int (*PROC)(); + extern void* __stdcall wglGetCurrentContext(); + extern PROC __stdcall wglGetProcAddress(const char *procname); + } + #elif !defined(__APPLE__) + extern ""C"" + { + #define APIENTRY + extern void* glXGetCurrentContext(); + extern void (*glXGetProcAddress(const char *procname))(); + } + #endif + + #if defined(__APPLE__) + #define APIENTRY + #include + #include + #include + + #define APIENTRY + extern ""C"" void* CGLGetCurrentContext(); + + #ifdef MAC_OS_X_VERSION_10_3 + #include + inline void* NSGLGetProcAddress(const char *name) + { + static void* image = NULL; + if (NULL == image) + { + image = dlopen(""/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"", RTLD_LAZY); + } + return image ? dlsym(image, (const char*)name) : NULL; + } + #else + #include + inline void* NSGLGetProcAddress(const char *name) + { + static const struct mach_header* image = NULL; + NSSymbol symbol; + char* symbolName; + if (NULL == image) + { + image = NSAddImage(""/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"", NSADDIMAGE_OPTION_RETURN_ON_ERROR); + } + // prepend a '_' for the Unix C symbol mangling convention + symbolName = malloc(strlen((const char*)name) + 2); + strcpy(symbolName+1, (const char*)name); + symbolName[0] = '_'; + symbol = NULL; + symbol = image ? NSLookupSymbolInImage(image, symbolName, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR) : NULL; + free(symbolName); + return symbol ? NSAddressOfSymbol(symbol) : NULL; + } + #endif /* MAC_OS_X_VERSION_10_3 */ + #endif /* __APPLE__ */ + + #if defined(__sgi) || defined (__sun) + #define APIENTRY + #include + #include + #include + inline void* LoadSymbol(const char *name) + { + // dlopen what? + if ((void *h = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL)) == NULL) return NULL; + return dlsym(h, ""glXGetProcAddress""); + } + inline void* dlGetProcAddress(const char *name) + { + static void* gpa = LoadSymbol(""glXGetProcAddress""); + + if (gpa != NULL) + return ((void*(*)(const char*))gpa)(name); + else + return dlsym(h, (const char*)name); + } + inline void* dlGetCurrentContext() + { + static void* gpa = LoadSymbol(""glXGetProcAddress""); + + if (gpa != NULL) + return ((void*(*)())gpa)(); + + return NULL; + } + #endif /* __sgi || __sun */ + + inline void* GetAddress(const char* name) + { + #if defined(_WIN32) + return (void*)wglGetProcAddress(name); + #elif defined(__APPLE__) + return (void*)NSGLGetProcAddress(name); + #elif defined(__sgi) || defined(__sun) + return (void*)dlGetProcAddress(name); + #else + return (void*)glXGetProcAddress((const char*)name); + #endif + } + + inline void* GetCurrentContext() + { + #if defined(_WIN32) + return wglGetCurrentContext(); + #elif defined(__APPLE__) + return CGLGetCurrentContext(); + #elif defined(__sgi) || defined(__sun) + return dlGetCurrentContext(); + #else + return glXGetCurrentContext(); + #endif + } + } + "; + + const string TypeDefinitions = @" + template + struct Enumeration + { + private: + int value; + + public: + inline Enumeration(int value) + { + this->value = value; + } + + inline operator int() const + { + return value; + } + }; + + typedef unsigned int GLenum; + typedef unsigned int GLbitfield; + typedef int GLsizei; // size_t + typedef bool GLboolean; + typedef signed char GLbyte; + typedef unsigned char GLubyte; + typedef short GLshort; + typedef unsigned short GLushort; + typedef int GLint; + typedef unsigned int GLuint; + typedef long GLlong; + typedef unsigned long GLulong; + typedef float GLfloat; + typedef float GLclampf; + typedef double GLdouble; + typedef double GLclampd; + typedef void GLvoid; + typedef const char* GLstring; + #if defined(_MSC_VER) && _MSC_VER < 1400 + typedef __int64 GLint64EXT; + typedef unsigned __int64 GLuint64EXT; + #else + typedef signed long long GLint64EXT; + typedef unsigned long long GLuint64EXT; + #endif + typedef GLint64EXT GLint64; + typedef GLuint64EXT GLuint64; + typedef struct __GLsync { } *GLsync; + + typedef char GLchar; + typedef void (*GLDEBUGPROCAMD)(GLuint id, + GLenum category, GLenum severity, GLsizei length, + const GLchar* message, GLvoid* userParam); + + /* For ARB_debug_output */ + + typedef void (*GLDEBUGPROCARB)(GLenum source, + GLenum type, GLuint id, GLenum severity, + GLsizei length, const GLchar* message, GLvoid* userParam); + + /* For GL_ARB_cl_event */ + + typedef struct _cl_context *cl_context; + typedef struct _cl_event *cl_event; + + //typedef GLsizei IntPtr; + typedef void* IntPtr; + typedef GLbyte SByte; + typedef GLubyte Byte; + typedef GLshort Int16; + typedef GLushort UInt16; + typedef GLint Int32; + typedef GLuint UInt32; + typedef GLlong Int64; + typedef GLulong UInt64; + typedef GLfloat Single; + typedef GLdouble Double; + typedef GLstring String; + typedef char* StringBuilder; + typedef GLDEBUGPROCAMD DebugProcAmd; + typedef GLDEBUGPROCARB DebugProcArb; + + struct Half + { + private: + UInt16 value; + public: + }; + "; + + #endregion BindStreamWriter sw_h = new BindStreamWriter(Path.GetTempFileName()); - BindStreamWriter sw_cpp = new BindStreamWriter(Path.GetTempFileName()); - BindStreamWriter sw_h_compat = new BindStreamWriter(Path.GetTempFileName()); - BindStreamWriter sw_cpp_compat = new BindStreamWriter(Path.GetTempFileName()); - BindStreamWriter sw_h_enums = new BindStreamWriter(Path.GetTempFileName()); #region WriteBindings @@ -78,47 +286,35 @@ namespace Bind Settings.DefaultOutputNamespace = "OpenTK"; - // Enums - using (var sw = sw_h_enums) - { - WriteEnums(sw, enums); - sw.Flush(); - sw.Close(); - } - - // Core definitions using (var sw = sw_h) { - WriteDefinitions(sw, enums, wrappers, Type.CSTypes, false); - sw.Flush(); - sw.Close(); - } + sw.WriteLine("#pragma once"); + sw.WriteLine("#ifndef GLPP_H"); + sw.WriteLine("#define GLPP_H"); + sw.WriteLine(); - // Compatibility definitions - using (var sw = sw_h_compat) - { - WriteDefinitions(sw, enums, wrappers, Type.CSTypes, true); - sw.Flush(); - sw.Close(); - } + WriteLicense(sw); + + sw.WriteLine("namespace {0}", Settings.OutputNamespace); + sw.WriteLine("{"); + sw.Indent(); + + WriteGetAddress(sw); + WriteTypes(sw); + WriteEnums(sw, enums); + WriteDefinitions(sw, enums, wrappers, Type.CSTypes); // Core definitions + + sw.Unindent(); + sw.WriteLine("}"); + + sw.WriteLine("#endif"); - // Core & compatibility declarations - using (var sw = sw_cpp) - { - WriteDeclarations(sw, wrappers, Type.CSTypes); sw.Flush(); sw.Close(); } string output_header = Path.Combine(Settings.OutputPath, OutputFileHeader); - string output_cpp = Path.Combine(Settings.OutputPath, OutputFileCpp); - string output_header_compat = Path.Combine(Settings.OutputPath, OutputFileHeaderCompat); - string output_header_enums = Path.Combine(Settings.OutputPath, OutputFileHeaderEnums); - Move(sw_h.File, output_header); - Move(sw_cpp.File, output_cpp); - Move(sw_h_compat.File, output_header_compat); - Move(sw_h_enums.File, output_header_enums); } void Move(string file, string dest) @@ -128,31 +324,43 @@ namespace Bind File.Move(file, dest); } + static Delegate WriteWrapper(Delegate last_delegate, Function f, BindStreamWriter sw) + { + if (last_delegate == f.WrappedDelegate) + return last_delegate; // Multiple wrappers for the same delegate are not necessary in C++ + last_delegate = f.WrappedDelegate; + + var parameters = f.WrappedDelegate.Parameters.ToString() + .Replace("String[]", "String*") + .Replace("[OutAttribute]", String.Empty); + sw.WriteLine("inline {0} {1}{2}", f.WrappedDelegate.ReturnType, + f.TrimmedName, parameters); + sw.WriteLine("{"); + sw.Indent(); + WriteMethodBody(sw, f); + sw.Unindent(); + sw.WriteLine("}"); + return last_delegate; + } + + static Delegate WriteInitDelegate(Delegate last_delegate, BindStreamWriter sw, Function f) + { + if (last_delegate != f.WrappedDelegate) + { + sw.WriteLine("Delegates::{0}() = (Delegates::p{0})OpenTK::Internals::GetAddress(\"gl{0}\");", f.WrappedDelegate.Name); + last_delegate = f.WrappedDelegate; + } + return last_delegate; + } + #endregion #region WriteDefinitions void WriteDefinitions(BindStreamWriter sw, EnumCollection enums, FunctionCollection wrappers, - Dictionary CSTypes, bool deprecated_only) + Dictionary CSTypes) { - sw.WriteLine("#pragma once"); - if (!deprecated_only) - { - sw.WriteLine("#ifndef GLCOREPP_H"); - sw.WriteLine("#define GLCOREPP_H"); - } - else - { - sw.WriteLine("#ifndef GLCOMPATPP_H"); - sw.WriteLine("#define GLCOMPATPP_H"); - } - sw.WriteLine(); - WriteLicense(sw); - - sw.WriteLine("namespace {0}", Settings.OutputNamespace); - sw.WriteLine("{"); - sw.Indent(); sw.WriteLine("namespace {0}", Settings.GLClass); sw.WriteLine("{"); sw.Indent(); @@ -173,36 +381,52 @@ namespace Bind sw.WriteLine("namespace Delegates"); sw.WriteLine("{"); sw.Indent(); - var functions = wrappers[extension].Where(f => f.Deprecated == deprecated_only); + var functions = wrappers[extension]; last_delegate = null; - foreach (var f in functions) + foreach (var f in functions.Where(f => !f.Deprecated)) { WriteDelegate(sw, f.WrappedDelegate, ref last_delegate); } + last_delegate = null; + sw.WriteLine("#if defined({0})", AllowDeprecated); + foreach (var f in functions.Where(f => f.Deprecated)) + { + WriteDelegate(sw, f.WrappedDelegate, ref last_delegate); + } + sw.WriteLine("#endif"); sw.Unindent(); sw.WriteLine("};"); // Write wrappers - sw.WriteLine("void Init();"); + sw.WriteLine("inline void Init()"); + sw.WriteLine("{"); + sw.Indent(); last_delegate = null; - foreach (var f in functions) + foreach (var f in functions.Where(f => !f.Deprecated)) { - if (last_delegate == f.WrappedDelegate) - continue; - last_delegate = f.WrappedDelegate; - - var parameters = f.WrappedDelegate.Parameters.ToString() - .Replace("String[]", "String*") - .Replace("[OutAttribute]", String.Empty); - sw.WriteLine("inline {0} {1}{2}", f.WrappedDelegate.ReturnType, - f.TrimmedName, parameters); - sw.WriteLine("{"); - sw.Indent(); - WriteMethodBody(sw, f); - sw.Unindent(); - sw.WriteLine("}"); + last_delegate = WriteInitDelegate(last_delegate, sw, f); } + last_delegate = null; + sw.WriteLine("#if defined({0})", AllowDeprecated); + foreach (var f in functions.Where(f => f.Deprecated)) + { + last_delegate = WriteInitDelegate(last_delegate, sw, f); + } + sw.WriteLine("#endif"); + sw.Unindent(); + sw.WriteLine("}"); + last_delegate = null; + foreach (var f in functions.Where(f => !f.Deprecated)) + { + last_delegate = WriteWrapper(last_delegate, f, sw); + } + sw.WriteLine("#if defined({0})", AllowDeprecated); + foreach (var f in functions.Where(f => f.Deprecated)) + { + last_delegate = WriteWrapper(last_delegate, f, sw); + } + sw.WriteLine("#endif"); if (extension != "Core") { @@ -216,79 +440,10 @@ namespace Bind sw.Unindent(); sw.WriteLine("}"); - - sw.WriteLine("#endif"); } #endregion - #region WriteDeclarations - - void WriteDeclarations(BindStreamWriter sw, FunctionCollection wrappers, - Dictionary CSTypes) - { - sw.WriteLine("#ifdef GLPP_INTERNAL_COMPILE_DECLARATIONS"); - - WriteLicense(sw); - - sw.WriteLine("namespace {0}", Settings.OutputNamespace); - sw.WriteLine("{"); - sw.Indent(); - - sw.WriteLine("using namespace Internals;"); - - // Used to avoid multiple declarations of the same function - Delegate last_delegate = null; - - // Declare all functions (deprecated and core). - // This is necessary for projects that wish to move from - // deprecated APIs to core piece-by-piece. - foreach (var ext in wrappers.Keys) - { - last_delegate = null; - var functions = wrappers[ext]; - foreach (var function in functions) - { - if (function.WrappedDelegate == last_delegate) - continue; - last_delegate = function.WrappedDelegate; - - string path = GetNamespace(ext); - sw.WriteLine("{0}::Delegates::p{1} {0}::Delegates::{1} = 0;", path, function.Name); - } - } - sw.WriteLine(); - - // Add Init() methods - foreach (var ext in wrappers.Keys) - { - string path = GetNamespace(ext); - - sw.WriteLine("void {0}::Init()", path); - sw.WriteLine("{"); - sw.Indent(); - - last_delegate = null; - var functions = wrappers[ext]; - foreach (var function in functions) - { - if (function.WrappedDelegate == last_delegate) - continue; - last_delegate = function.WrappedDelegate; - - sw.WriteLine("{0}::Delegates::{1} = ({0}::Delegates::p{1})GetAddress(\"gl{1}\");", - path, function.WrappedDelegate.Name); - } - sw.Unindent(); - sw.WriteLine("}"); - } - - sw.Unindent(); - sw.WriteLine("}"); - - sw.WriteLine("#endif"); - } - static string GetNamespace(string ext) { if (ext == "Core") @@ -297,24 +452,10 @@ namespace Bind return String.Format("{0}::{1}", Settings.GLClass, Char.IsDigit(ext[0]) ? DigitPrefix + ext : ext); } - #endregion - - #region ISpecWriter Members - #region WriteEnums public void WriteEnums(BindStreamWriter sw, EnumCollection enums) { - sw.WriteLine("#pragma once"); - sw.WriteLine("#ifndef GLENUMSPP_H"); - sw.WriteLine("#define GLENUMSPP_H"); - sw.WriteLine(); - WriteLicense(sw); - - sw.WriteLine("namespace {0}", Settings.OutputNamespace); - sw.WriteLine("{"); - sw.Indent(); - foreach (Enum @enum in enums.Values) { sw.WriteLine("struct {0} : Enumeration<{0}>", @enum.Name); @@ -338,35 +479,30 @@ namespace Bind sw.WriteLine("};"); sw.WriteLine(); } - - sw.Unindent(); - sw.WriteLine("}"); - - sw.WriteLine("#endif"); } #endregion #region WriteTypes - public void WriteTypes(BindStreamWriter sw, Dictionary CSTypes) + void WriteTypes(BindStreamWriter sw) { - sw.WriteLine(); - foreach (string s in CSTypes.Keys) - { - sw.WriteLine("typedef {0} {1};", s, CSTypes[s]); - } + sw.WriteLine(TypeDefinitions); } #endregion - #region WriteDelegates + #region WriteGetAddress - public void WriteDelegates(BindStreamWriter sw, DelegateCollection delegates) + void WriteGetAddress(BindStreamWriter sw) { - throw new NotSupportedException(); + sw.WriteLine(GetAddressDefinition); } + #endregion + + #region WriteDelegate + static void WriteDelegate(BindStreamWriter sw, Delegate d, ref Delegate last_delegate) { // Avoid multiple definitions of the same function @@ -377,37 +513,29 @@ namespace Bind .Replace("String[]", "String*") .Replace("[OutAttribute]", String.Empty); sw.WriteLine("typedef {0} (APIENTRY *p{1}){2};", d.ReturnType, d.Name, parameters); - sw.WriteLine("extern p{0} {0};", d.Name); + sw.WriteLine("inline p{0}& {0}()", d.Name); + sw.WriteLine("{"); + sw.Indent(); + sw.WriteLine("static p{0} address = 0;", d.Name); + sw.WriteLine("return address;"); + sw.Unindent(); + sw.WriteLine("}"); } } #endregion - #region WriteImports - - public void WriteImports(BindStreamWriter sw, DelegateCollection delegates) - { - throw new NotSupportedException(); - } - - #endregion - #region WriteWrappers - public void WriteWrappers(BindStreamWriter sw, FunctionCollection wrappers, - Dictionary CSTypes) - { - throw new NotSupportedException(); - } - static void WriteMethodBody(BindStreamWriter sw, Function f) { + var callstring = f.Parameters.CallString() .Replace("String[]", "String*"); if (f.ReturnType != null && !f.ReturnType.ToString().ToLower().Contains("void")) - sw.WriteLine("return Delegates::{0}{1};", f.WrappedDelegate.Name, callstring); + sw.WriteLine("return Delegates::{0}(){1};", f.WrappedDelegate.Name, callstring); else - sw.WriteLine("Delegates::{0}{1};", f.WrappedDelegate.Name, callstring); + sw.WriteLine("Delegates::{0}(){1};", f.WrappedDelegate.Name, callstring); } static DocProcessor processor = new DocProcessor(Path.Combine(Settings.DocPath, Settings.DocFile)); @@ -475,8 +603,6 @@ namespace Bind #endregion - #endregion - #region WriteLicense public void WriteLicense(BindStreamWriter sw) diff --git a/Source/Bind/Main.cs b/Source/Bind/Main.cs index 53ce13f1..566b366d 100644 --- a/Source/Bind/Main.cs +++ b/Source/Bind/Main.cs @@ -251,7 +251,7 @@ namespace Bind } else { - throw new NotImplementedException(); + throw new NotSupportedException(); } }