I am starting to learn OpenGL and I read that I need a function loader framework (glad and the like) which will supply me with the pointers to opengl functions. I have been searching for information about why this is needed and I found only a vague description about ABI’s. My understanding is as follows:
I have opengl installed in my computer. This means I have libgl.so and whatever other .so needed (or .dll if you prefer, that does not matter right now).
I link towards these dynamic libraries.
My system has all the items needed during compile, link and runtime, so, in theory, it could be able to directly run the program.
My understanding is that the loader manually loads the functions, using OS system calls, from the dynamic library and obtains a pointer to the loade function. I understand how this is done but I don’t understand why it is needed at all. So the main question I have is: How is it that I need a loader to manually find the address where opengl functions got loaded during process launch?
My initial thought was that it was not actually needed, it will run without the need of a function loader as long as I have the .so/.dll. Perhaps the problem will may come when moving the program to another computer. But then I don’t understand that either… as long as libgl.so and the like are installed, as any other lib.so needed, it will work. In the worst case, I should be able to bundle in a package (through dependencies or whatever) all the needed libs and it should work.
But everywhere I look points to the fact of using a function loader is a must.
I have struggled quite a bit to find a satisfying answer, but it seems that this question is avoided as a non-interesting matter (for instance: “For reasons that are ultimately irrelevant to this discussion, you must manually load functions via a platform-specific API call” on the opengl.org getting started page).
On Windows, the OpenGL library (opengl32.dll) only exports the functions which are part of OpenGL 1.1. The only way to use functions added in later versions or in extensions is to first use wglGetProcAddress() to get a pointer to the function.
On Linux, libGL.so conventionally exports all of the functions which it knows about. But this isn’t necessarily all of the functions which the video driver supports. Particularly as you can direct output to an X server running on a different system, which may support a newer version than the system on which the client is running.
I don’t know what the policy is for the Mac’s OpenGL library.
Apart from this, dynamic binding allows you to write a program which uses newer OpenGL features if they’re available without adding a hard dependency. Whereas if an executable includes a symbol in its import table and the library doesn’t provide that symbol, any attempt to execute the program will fail.
In short, direct linking will probably work if you only need OpenGL 1.1 or only need the program to work on Linux (but you may need to define the macro GL_GLEXT_PROTOTYPES in order to get the OpenGL headers to expose the function prototypes rather than just typedefs for function pointers). It won’t work on Windows if you need any features in OpenGL 1.2 or later, and may not even work on Linux if you’re using features from the latest version.
The key piece of information is that OpenGL is not software.
It’s not just a library that contains exported functions that you can link to and then use. What OpenGL functionality is available first and foremost depends on your hardware, your GPU. From there it also depends on your OpenGL implementation; i.e your vendor-provided device driver. It’s also possible to have hardware functionality that the driver doesn’t expose (hello, Mac users) or for drivers to implement functionality that the hardware doesn’t even have (via a software-emulated fallback).
What all of this means is that a program cannot know in advance what OpenGL features are available on any given machine that it runs on. The program must query the driver and ask what features are available before it can use them. So hence the fact that loaders are needed: they provide a simplified and cross-platform way of doing this.
So, a GPU manufacturer which is publishing its own open gl driver has to follow/implement not only the open gl API for a specific version but also the file generated (the .so/.dll) has to have a specific filename so that the loader can find it during runtime (libgl.so in linux, opengl.dll in windows). Am I correct?
It’s also possible … for drivers to implement functionality that the hardware doesn’t even have (via a software-emulated fallback).
That sounds very curious. Do you know of any open gl software implementation in Linux world? I know this is unrelated with my original question, but as the topic has appeared now…
Not quite. I don’t know the situation on Linux, but on Windows the vendor driver can actually be called anything at all. The OS-provided opengl32.dll is constant for all vendors, and is a software implementation written by Microsoft. How OpenGL works is that the Microsoft implementation checks if a vendor implementation is present, and re-routes each call to the vendor implementation if so. There is a well-defined registry key and loading procedure that is used to make all of this happen.
So the name and location of the vendor-provided OpenGL dll on any given Windows machine is allowed to be completely different to that on any other Windows machine, and you can’t (and shouldn’t) make assumptions about it.
Mesa is the software implementation you typically come across. As a general rule however, you don’t want to use a software implementation. People commonly state that it will be slower, and you might get the expectation that it’s something like 25% or even 10% of the speed of a hardware implementation. That’s not the case at all; more typically you’ll get less than 1 frame per second.
[QUOTE=vichor;1283315]So, a GPU manufacturer which is publishing its own open gl driver has to follow/implement not only the open gl API for a specific version but also the file generated (the .so/.dll) has to have a specific filename so that the loader can find it during runtime (libgl.so in linux, opengl.dll in windows). Am I correct?
The OpenGL library needs to have a specific name (and more) so that you don’t need a different executable for each vendor. But the OpenGL library is typically part of the OS, and simply calls out to the driver provided by the vendor (nVidia’s proprietary Linux driver includes its own libGL.so.1, but it’s binary-compatible with the one from X.org).