== File sturcture ==

The Lua scripts here use standard Lua API calls and no external modules.

All Lua files that start with an "_" are library files. They usually add at least one global function, usually named the same as the filename (sans "_"). Some are just a collection of miscellaneous functions that do certain things.

Lua files that don't start with the underscore are to be executed on the command line. They may take parameters.

== The generation process ==

The code-generation process is 2-stage. The first stage is the conversion of the .spec and .tm files into a .lua file that returns a giant table containing all of this information. The .lua files responsible for this conversion are:

* ConvertAllSpecFilesToLua.lua: Causes generation of all .lua spec files. It doesn't take parameters.
** _ExtractSpecsToFile.lua: Generates a single .lua spec file.
*** _ExtractEnums.lua: Processes enumext.spec to retrieve the enums.
*** _ExtractExts.lua: Processes enumext.spec to retrieve the extension list.
*** _ExtractTypes.lua: Processes gl.tm to retrieve the typemap data.
*** _ExtractFuncs.lua: Processes gl.spec to retrieve the function data.
*** _TableWriter.lua: Writes a table as a Lua-compileable file. Think LSON.

The second stage uses the .lua file to generate the code. The output from this stage is described above. The files involved are:

* makeAllFiles.lua: Causes the generation of all code-gen files. It doesn't take parameters.
** _LoadLuaSpec.lua: Loads the spec we created above. However, it does some pre-processing to make the code-generation easier (tables indexed by enum and so forth). It also performs some data fixup that removes some... annoying things that the spec files leave in.
** _MakeInclTypeFile.lua: Generates a header file that contains the type information (GLuint, etc). Only used for core OpenGL. Always a .h file.
** _MakeInclCoreFile.lua: Generates header files that contains the enums and functions for a specific version of core OpenGL. It *only* includes those defs that are part of that specific version (and no core extensions). It can also take a parameter that removes removed functionality, up through a certain version. Generates .h and .hpp files.
** _MakeInclExtFile.lua: Generates a header file that contains the enums and functions for all OpenGL extensions. Generates .h and .hpp files.
** _MakeInclVersionFile.lua: Generates a header file that includes a number of the files generated by MakeIncl*File. Generates .h and .hpp files.
** _MakeExtHeaderFile.lua: Generates a header file for a particular OpenGL version. This is used by external code to use OpenGL. Only used for WGL/GLX.
** _MakeMainHeaderFile.lua: Generates an internal header that is used to load extension function pointers.
** _MakeMainSourceFile.lua: Generates an internal source file that does the loading of the extension function pointers.
** _MakeCoreHeaderFile.lua: Generates an internal header file that contains a struct defining all of the internal function pointers.
** _MakeCoreSourceFile.lua: Generates an internal source file that will fill this struct with function pointers from the standard gl.h.

== The gl.h issue ==

Different versions of OpenGL libraries have different base implementations. On Windows, 1.1 is the base, so all of those functions are statically defined. On other platforms, there will be different levels of GL.

What we will do is have a source file that includes the standard gl.h. It has a function that copies all the 1.1 function pointers into a prepared struct. Then, if a core function fails to get a function pointer, it can try to get it from the prepared struct. The struct is there to keep down name polution.

In order to make this work, core functions ''must'' be #defined with their name, rather than defined as variables. If you don't do this, you get linker errors (multiple definition). Thus, all core OpenGL functions (including core extensions) must #define the name as a variable, with the variable name being externed instead. The variable name will be of the form "__gle*", where "*" is the rest of the function name.

== The generated files ==

The code-generation process will generate a number of files. The types of these files is as follows.

* ''Include headers:'' These are the header files that the user #includes into their project. They define OpenGL entrypoints and enums for a particular OpenGL version/profile pair.

* ''Main internal header:'' This header exposes the extension function loading functions to the non-code-generated GLE runtime.

* ''Main source file:'' This implements the functions exposed by the Main internal header.

* ''Core internal header:'' This header exposes a struct containing all of the core entrypoints. It also has a function to load standard core function pointers from this.

* ''Core source header:'' Implements the functions from the Core internal header.

=== External headers ===

The standard generation process will create headers for the following combination of GL versions and profiles:

* GL 2.1
* GL 3.0
* GL 3.1 core
* GL 3.1 compatibility
* GL 3.2 core
* GL 3.2 compatibility
* etc.

The external code simply includes one of these header files. That will get them access to what they need.

These files will have the following in them:

* Core and extension #defines, as appropriate to the version.
* Core and extension entrypoints, as appropriate to the version.
* For each extension, a variable extern; if the variable is GL_FALSE, then the extension is not defined.

=== Main internal header ===

There will be a single internal header to the main loading functions. This file contains the following declarations:

* A mapping table. An array of map objects, where the map object contains a string extension name, an integer pointer to the "is extension loaded" variable for that extension, and a function pointer to a loader for that extension (NULL if has no functions).
* The size of the mapping table.
* A function to clear all of the extension variables.
* For each of the possible version/profile combinations, a function that loads the core entrypoints, including core extensions appropriate to the verison/profile (but not including regular extensions). Returns 1 if the function pointers could be loaded, and 0 otherwise. Will set the extension variables for any core extensions it loads.
* A function to load the "base" entrypoints. See below.
* The "base" entrypoint declarations, as well as "base" enum defines.

All internal functions have the prefix "gleInt_".

==== Base declarations ====

The "base" declarations are those that the basic system needs to function. These are:

* ''glGetString'': Used to get the version number and extensions, possibly.
* ''glGetStringi'': Used to get the extensions in 3.x versions. Can be NULL.
* ''glGetIntegerv'': Used to get the number of extensions in 3.x versions.
* ''GL_VERSION'': Enum needed to version numbers.
* ''GL_EXTENSIONS'': Enum needed to get extensions.
* ''GL_NUM_EXTENSIONS'': Enum used to get the number of extensions.
* ''GL_CONTEXT_PROFILE_MASK'': Enum used to test the profile type.
* ''GL_CONTEXT_CORE_PROFILE_BIT'': Enum for the core profile.
* ''GL_CONTEXT_COMPATIBILITY_PROFILE_BIT'': Enum for the compatibility profile.
* ''GL_TRUE'' and ''GL_FALSE'': so that we can use them.

=== Core internal header ===

This header file exposes a struct (with an expected name) that stores function pointers for ''all'' core functions. It also exposes a single function that will clear this struct, then load the standard function pointers into it.

=== Core source file ===

This file the standard #includes "gl/gl.h". It also implements the function above.

The first phase of the function will clear the struct. The second phase is platform-specific. Each platform in the code generator will have a define to #ifdef around, and it will also specify which core versions need to be looked at.

Note: the struct in question may require some defines for the functions to be placed in the source file.

=== Main source file ===

This file does the following:

* Define all of the externed extension variables.
* Define all of the externed function pointers.
* Initialize the mapping table from extension name to extension variable.
* Implement the function that clears extension variables.
* For each extension with function pointers, implement a ''static'' function to load the function pointers for it.
* For each of the version/profile pairs, implement a function that loads the core function pointers for that version/profile pair. This includes core extensions, but only those appropriate to the verison. If a core function pointer is not found, then check the core internal struct for one.
* Implement the function that loads the "base" stuff.

==== Extension loading ====

The functions that load extensions will return 0 if some of the function pointers were not there, and 1 otherwise. Unfortunately, to see if a function pointer is there, it must be tested against the values -1, 0, 1, 2, and 3.

==== Core loading ====

The first thing any of these functions will do is clear the Core Function struct.

The function that loads core entrypoints will also load entrypoints for appropriate core extensions. If a core extension loads successfully, its extension variable will be set.

If a core function pointer is not available, check the struct of core functions from the Core header. If it's in there, then use that. Otherwise, fail and return 0.

Loading a core extension is slightly different from loading a regular extension in this respect. If a core extension is being loaded as a core extension, then it should be loaded as a core extension, which requires checking variables in the struct on failure. Also, when a core extension is loaded as a core extension, the extension variable should be set.

===== Generating core loaders =====

To keep from regenerating the same loading code over and over again, the process will work as follows.

First, we will scan all the functions and collect a list of the individual version numbers of the "deprecated" field.

Then, we generate a number of loader functions for core functions. There will be one "base" function that loads all entrypoints. Then, for each of the version numbers collected above, generate a set of alternative core loader functions up to and including that version number that write functions that haven't been removed up to that version.

As a further optimization, we will have the lower versions call the higher versions. So the base can call the lowest version (where available), the lowest version can call the next-lowest version (where available), and so on. Thus, the base version would only need to store the ''non'' deprecated ones.

Note that these functions must include core ''and'' core extension functions.

So, let's say you have removal on only one verison: 3.1. Therefore, you will write:

* base loader functions for every available GL version. Calling these will have the effect of loading *all* function pointers for that version (and only that version) of OpenGL. Internally, it will load only those functions which were removed in 3.1, and then call the equivalent 3.1 function (if any).
* loader functions for every GL version up to but not including 3.1. These functions will load only those functions which were *not* removed in 3.1. There will not be functions for GL version 3.1 and 3.2; the base versions will qualify.

To load the core 3.2 context, you call the base 3.2 loader, then call the 3.1 removal functions for everything else.

== Algorithm of gleLoadFunction ==

This function is hand-written, for now.

# Call the function to clear entrypoints.
# Call the base loading function to get the base entrypoints.
# Get the OpenGL version.
# Load the core entrypoints.
## If version is 2.1 or less, load 2_1.
## If version is 3.0, load 3.0.
## If the version is 3.1, check the extension string. If ARB_compatibility is defined, load 3.1 compatibility. Otherwise, load 3.1 core.
## If the version is 3.2 or greater, check the profile bit and load 3.2 accordingly.
# For each extension in the string:
## If the extension has no entry in the map table, continue.
## If the extension variable for it has already been set to GL_TRUE, do nothing. (it can be set to that because it's a core extension).
## If the extension has a loader, call it. If the loader returns 1, set the variable to GL_TRUE.
## If the extension doesn't have a loader, set the variable to GL_TRUE.

== Using the library ==

To initialize the OpenGL core function pointers, the user calls "gleLoadFunctions". This function takes no parameters, and it will load all available extensions and core functions for the [i]actual[/i] version of the OpenGL implementation. This is guaranteed to be greater than or equal to the version the user asked to be created.

The "gleLoadFunctions" will return GL_FALSE if the loading failed.

== Adding new spec files ==

Adding spec files uses the following procedure. The gl-xml-spec project is where the specification and conversion utilities are maintained. Once the gl-xml-spec project has generated new .lua spec files:

# Update the repo to the "latest-spec" tag. Change to the "glspec" branch.
# Drop the new spec files in the glload/codegen/glspecs directory.
# Commit these into the "glspec" branch. Include the changelist of the data from gl-xml-spec.
# Update the "latest-spec" tag to point to this newest commit.
# Merge the "glspec" head with the "default" branch.
# In the glload/codegen directory, run 'lua MakeAllFiles.lua'
# Verify that the tests and examples work.
# Check this into the "default" branch.

Any .spec file bugs that we need to fix should be fixed in gl-xml-spec project. That is where the .spec files are maintained.

If the spec files include a new OpenGL version, do the following steps ''before'' running the code generation process.

# In codegen/MakeAllFiles.lua, add lines to the `glOutputs` function to handle the new OpenGL version.
# In codegen/data/coreExtList.lua, add a new table to contain the core ARB extensions for the new version. Then add an entry into the `masterTable` table to reference it. Make sure to take the `GL_` prefixes out.
# In codegen/data/listOfCoreVersions.lua, add a new core version.
# If the new version removed (not just deprecated) functionality:
## In codegen/MakeAllFiles, add the version to the list `removalVersions`.