Effectively, AllegroPro exists in 2 layers: the internal layer, and the Platform/Compiler/Driver (PCD) specific layer. The internal layer is shared code among all platforms, compilers, and drivers. This allows us to define an API that we expose to the user, while still letting the PCD specific components be as small and simple (and, therefore, easy to develop/debug) as possible. Also, it helps insulate driver/platform-specific code from changes to the external API.
A platform refers to the OS that the program is running on. Examples would be MS Windows, Linux, and MacOS X to name a few.
A compiler refers to the program that is compiling this library. Examples would be MingW GCC, Linux GCC, etc. Many versions of GCC on different platforms are very similar, so it can be said that there is a general GCC compiling system.
A file can contain code that works only in the presence of a particular platform, OS, or even driver. For example, the OpenGL-based graphics driver can expose a small set of API functions that only work when given an OpenGL graphics driver.
There will be an "include" directory and a "src" directory. All API header files (header files that expose specific API's to the user, even if they are PCD-specific) and all driver defining header files will go into the include directory. API headers will be separated by platform and compiler, as per the above.\
Issue 1: This will require that the user actually match our build system's directory structure for each platform/compiler he/she uses.
Details: This is obviously not a good solution. Alternatives include using the platform/compiler specific includes to go to the appropriate directory, or having proxy files that do the same. The later might be the most reasonable alternative.
The structure of both directories will be as follows:
The AllegroPro build system will be designed to understand this hierarchy of folders and work within it. Any files that the given platform and compiler match to will be compiled as part of that version's AllegroPro.
These are a list of the platform-specific files required by each section of AllegroPro Tier 1&2. This list also specifies the expectations of what these files should do.
Each driver is defined by 2 kinds of objects: a driver object and a driver descriptor object.
Each system that has drivers will define a function for registering driver descriptor objects. For standard drivers (drivers that are part of the AllegroPro distribution), this registration function will be called during the initialization of that system.
A driver descriptor object is a struct that contains function pointers for describing the driver. At a minimum, it should contain a function to create a driver and destroy it. For component systems that support autodetection, the driver descriptor will also contain function pointers or member variables (or both) that will support querying for autodetection. Lazy autodetection can work off of a self-describing "priority" value that each driver descriptor object has.
Driver descriptor objects are assumed to be static, not dynamic, in allocation. As such, they will never be deallocated in any way.
Each driver descriptor, also, needs a field specifying the uint32_t name of the driver. While some driver systems may have other mechanisms of creating objects, every driver system must allow the user to specify a uint32_t name for their driver. The user may, also, query the name of an already existing driver object. By convention, all standard driver uint32_t names will have the high-bit clear. As such, user-created drivers can therefore have the high-bit set and be certain of avoiding naming collisions.
Because the registering of drivers actually allocates some memory (a linked-list, or possible a std::vector-like object), the registration functions must be called doing any AllegroPro pre-init work (like setting up memory management functions).
A driver object, as created by the driver descriptor, contains a number of function pointers. A driver, if the system allows it, is free to leave some of these function pointers NULL. The driver object will, also, have a void* object that represents the driver's internal data. This internal data will be passed to every member function pointer of the driver object, as though it were a C++ "this" pointer.
Drivers may create other driver-like objects. For example, a graphics driver can create bitmap objects that have a v-table much like a driver. This is valid behavior.
When a driver is destroyed, there is no overarching requirement for a driver to clean up all driver objects. Some systems will require that some cleanup work occurs, while other systems will require that the driver cleanup all driver-created data.
Use the "aldriver.h" file to define function pointers for v-tables/structs.
The AllegroPro build system will expose a number of #defines, where appropriate. In general, try to avoid using the platform and OS-specific defines for entire functions. Instead, use platform/OS specific files, and document what is expected out of these files.
All #defines that apply to the building for that specific OS/platform will be defined. For example, on Linux under Linux GCC, you will have AL_PLAT_LINUX, AL_COMP_GCC, and AL_COMP_GCC_LINUX defined.
In addition to these defines, there will be these optional defines available: