I am currently using the CG OpenGL binding automatically generated from Khrosos.spec files found in the registry .
I am quite satisfied with the quality of the bindings; here is an example function:
/// <summary> /// Binding for glGenFramebuffers function. /// </summary> /// <remarks> /// This function belongs to 'ARB_framebuffer_object'. /// <para> /// Depending on driver implementation, this routine could call the following (equivalent) routines: /// - glGenFramebuffers /// - glGenFramebuffersEXT /// </para> /// </remarks> /// <param name="n"> /// A <see cref="Int32"/>. /// </param> /// <param name="framebuffers"> /// A <see cref="UInt32*"/>. /// This parameter holds data returned from function. /// </param> public static void GenFramebuffer(Int32 n, [Out] UInt32[] framebuffers) { unsafe { fixed (UInt32* fp_framebuffers = framebuffers) { if (Delegates.pglGenFramebuffers != null) Delegates.pglGenFramebuffers(n, fp_framebuffers); else if (Delegates.pglGenFramebuffersEXT != null) Delegates.pglGenFramebuffersEXT(n, fp_framebuffers); else throw new InvalidOperationException("binding point GenFramebuffer cannot be found"); } } LogProc("glGenFramebuffers("+n+", "+framebuffers+")"); }
As you can see, the fixed block is trying to call two different delegates (Delegates.pglGenFramebuffers and Delegates.pglGenFramebuffersEXT).
This is possible because they have the same signature:
[System.Security.SuppressUnmanagedCodeSecurity()] internal unsafe delegate void glGenFramebuffers(Int32 n, [Out] UInt32* framebuffers); internal static glGenFramebuffers pglGenFramebuffers = null; [System.Security.SuppressUnmanagedCodeSecurity()] internal unsafe delegate void glGenFramebuffersEXT(Int32 n, [Out] UInt32* framebuffers); internal static glGenFramebuffersEXT pglGenFramebuffersEXT = null;
Delegates have the same signature because the specification (.spec file) is the same for the two routines introduced by the difference extensions.
Previously, bindings supported only kernel extensions, ARB, and EXT; the binding generator simply avoids defining this procedure in case there is another equivalent with high priority.
In order to increase support for the extension (stimulated by this SO question ), I need to declare delegates and import the declaration also for the procedure that was promoted to ARB or to the kernel implementation and write a shell implementation that calls all equivalent procedures (those that are defined).
So I got the source declared above.
Problems arise when working with 2K + ads. I have a binding generator as I cannot write all OpenGL bindings.
But how can the binding generator know if the func subroutine is semantically equivalent to another funcARB or funcEXT subroutine (with the same signature)?
I think the only option I have is to write an external file (controlled by the developer) that lists the exception cases (i.e. two routines that have the same base name and the same signature, are not are semantically equivalent).
The ultimate goal should be basically a collapsible OpenGL wrapper library to minimize the effort required to manage OpenGL extensions.
After some experimentation ...
It is possible that both suitable extensions are implemented (i.e. ARB_framebuffer_object and EXT_framebuffer_object). Since the entry points are different (different names), I need all the functions of both extensions .... but!
If I give priority to supported extensions (let's say that ARB has a higher priority than EXT, EXT has a higher privilege than VENDOR), the implementation proposed in my question is acceptable for the shell framework, since the ARB extension is implemented, the infrastructure implementation is preferable, than an EXT implementation (no matter what functionality).
This will work, but a side effect is that this policy is forced to use the OpenGL binding (no one at the moment! So no one will complain about it! :)).