<p>After running across <a href="https://open.gl/context#Onemorething" rel="nofollow noreferrer">an aside in a tutorial</a> and doing some further digging, I think I understand this now.</p>

<p>According to the <a href="https://www.khronos.org/registry/OpenGL/ABI/#4" rel="nofollow noreferrer">OpenGL ABI specification</a>, only the functions defined in OpenGL 1.2 need to be present in the <code>GL/gl.h</code> header file. (At least for Linux - other platforms may be different. <a href="https://stackoverflow.com/a/17555881/3022952">This answer</a> indicates that Windows may expose only OpenGL 1.1 functions by default.) Functionality from more recent OpenGL versions (even commonly used functions) may not even be defined in the header files. -- This seems to be the case for glDrawElementsInstanced. In the headers of one Linux version I looked at, by default glDrawElementsInstanced isn't exposed by the the headers, even though OpenGL 4.5 is supported.</p>

<p>Instead, the functionality from newer OpenGL versions are apparently handled through the OpenGL extension system. (Even if it's not strictly an "extension", but part of standard functionality.) That is, each individual user is nominally responsible for loading the function address into the appropriate function variable using the appropriate (platform-specific) <code>*GetProcAddress()</code> function from the <code>GL/glext.h</code> header. <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glXGetProcAddress.xml" rel="nofollow noreferrer">The usage</a> is to pass the appropriate string to the function, which will return a function pointer to the appropriate function (if present), or a null pointer if the functionality can't be found. (See the <a href="https://open.gl/context#Onemorething" rel="nofollow noreferrer">tutorial section</a> for more detail on usage.)</p>

<p>This is, obviously, somewhat less than satisfactory if you're using modern OpenGL features. There is a preprocessor define GL_GLEXT_PROTOTYPES which, when defined prior to including <code>GL/glext.h</code>, will enable the definitions of a large number of standard functions. However, this may not work robustly if you're running on a computer which doesn't implement all of those functions which you're using. (You're likely to get missing symbol error during shared library loading.)</p>

<p>The better way to handle things is to use the <a href="http://glew.sourceforge.net/" rel="nofollow noreferrer">OpenGL Extension Wrangler</a> (GLEW). This hides the heavy lifting of the whole <code>*GetProcAddress()</code> process, defining symbols like <code>glDrawElementsInstanced</code> directly in the <code>glew.h</code> header. So long as you call <code>glewInit()</code> after initializing OpenGL but before using any version dependent function, these functions should be initialized appropriately if available, or to a null pointer if not. </p>

<p>You can either test for the function pointer being non-null, or use the GLEW-provided version test variables like <code>GLEW_VERSION_3_1</code>, which are booleans (not compile-time defines) indicating if that OpenGL version is supported on the computer the program is running on. Alternatively, you can <a href="http://glew.sourceforge.net/basic.html" rel="nofollow noreferrer">test on a feature-by-feature level</a> by using <code>glewIsSupported()</code>/<code>glewGetExtension()</code>. You can look up the respective strings for individual extensions at the <a href="https://www.khronos.org/registry/OpenGL/index_gl.php" rel="nofollow noreferrer">OpenGL Registry</a>. It doesn't lend itself to forward searching, but may permit use of features prior to the nominal version of OpenGL in use.</p>

<p>So why wasn't this clearer to me before? I think it's because most of the tutorials and documentation about OpenGL simply assume that you're using GLEW. Despite its name, GLEW isn't just about extensions, it also abstracts much of the version-to-version compatibility issues. As long as you put use behind version checks and don't actually attempt to call a non-supported function, GLEW hides all the pesky details about functions which aren't actually being implemented.</p>

CC BY-SA 3.0
2018-04-11T23:24:45.870Z
2018-04-11T23:24:45.870Z
R.M.
<p>I'm new to OpenGL, and I'm wondering what I need to pay attention to regarding versioning. The things I've been reading have been clear about there being version differences, and needing the appropriate OpenGL version for the functionality you're using. But they've mainly been talking about compiling and running programs on a single machine. For the most part they haven't explicitly dealt with complexities regarding compiling on one machine and running on another. (Specifically, what happens if the computer you're running on has an older version of OpenGL than the one you're compiling on.)</p>

<p>For example, take <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElementsInstanced.xhtml" rel="noreferrer">glDrawElementsInstanced</a>. The Khronos page indicates this is available with OpenGL 3.1 and later. Obviously, if the headers for OpenGL on the machine I'm compiling for are version 3.0 or earlier, I'll get a compiler error. So on the machine I'm compiling on, I'll need to have OpenGL 3.1+ available.</p>

<p>However, I'm wondering what might happen if the machine I compile for has OpenGL 3.1+ available, but the machine I'm running on only has support for 3.0 or earlier? Will the program that uses glDrawElementsInstanced refuse to load? Will it run but crash once I call the glDrawElementsInstanced() function? Will it work fine because the actual implementation is compiled into my program, and it only uses common back-end functionality? Is the answer different for static versus dynamic linkage? -- And perhaps most importantly, if it wasn't glDrawElementsInstanced but some other function, is there a way I can determine this on my own?</p>

<p>I'm interested in distributing on Windows, Mac and Linux, so if there's any differences in behavior between the platforms in this regards, I'd be interested in knowing.</p>

<opengl><compatibility>
Dealing with OpenGL versions across multiple computers
R.M.
# Dealing with OpenGL versions across multiple computers

(Asked by: username_0 on 2018-04-10)

I'm new to OpenGL, and I'm wondering what I need to pay attention to regarding versioning. The things I've been reading have been clear about there being version differences, and needing the appropriate OpenGL version for the functionality you're using. But they've mainly been talking about compiling and running programs on a single machine. For the most part they haven't explicitly dealt with complexities regarding compiling on one machine and running on another. (Specifically, what happens if the computer you're running on has an older version of OpenGL than the one you're compiling on.)

For example, take [glDrawElementsInstanced](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElementsInstanced.xhtml). The Khronos page indicates this is available with OpenGL 3.1 and later. Obviously, if the headers for OpenGL on the machine I'm compiling for are version 3.0 or earlier, I'll get a compiler error. So on the machine I'm compiling on, I'll need to have OpenGL 3.1+ available.

However, I'm wondering what might happen if the machine I compile for has OpenGL 3.1+ available, but the machine I'm running on only has support for 3.0 or earlier? Will the program that uses glDrawElementsInstanced refuse to load? Will it run but crash once I call the glDrawElementsInstanced() function? Will it work fine because the actual implementation is compiled into my program, and it only uses common back-end functionality? Is the answer different for static versus dynamic linkage? -- And perhaps most importantly, if it wasn't glDrawElementsInstanced but some other function, is there a way I can determine this on my own?

I'm interested in distributing on Windows, Mac and Linux, so if there's any differences in behavior between the platforms in this regards, I'd be interested in knowing.

**Tags:** opengl, compatibility


---

## 1 answers

### Answer by username_0 on 2018-04-11. Score: 3

After running across [an aside in a tutorial](https://open.gl/context#Onemorething) and doing some further digging, I think I understand this now.

According to the [OpenGL ABI specification](https://www.khronos.org/registry/OpenGL/ABI/#4), only the functions defined in OpenGL 1.2 need to be present in the `GL/gl.h` header file. (At least for Linux - other platforms may be different. [This answer](https://stackoverflow.com/a/17555881/3022952) indicates that Windows may expose only OpenGL 1.1 functions by default.) Functionality from more recent OpenGL versions (even commonly used functions) may not even be defined in the header files. -- This seems to be the case for glDrawElementsInstanced. In the headers of one Linux version I looked at, by default glDrawElementsInstanced isn't exposed by the the headers, even though OpenGL 4.5 is supported.

Instead, the functionality from newer OpenGL versions are apparently handled through the OpenGL extension system. (Even if it's not strictly an "extension", but part of standard functionality.) That is, each individual user is nominally responsible for loading the function address into the appropriate function variable using the appropriate (platform-specific) `*GetProcAddress()` function from the `GL/glext.h` header. [The usage](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glXGetProcAddress.xml) is to pass the appropriate string to the function, which will return a function pointer to the appropriate function (if present), or a null pointer if the functionality can't be found. (See the [tutorial section](https://open.gl/context#Onemorething) for more detail on usage.)

This is, obviously, somewhat less than satisfactory if you're using modern OpenGL features. There is a preprocessor define GL\_GLEXT\_PROTOTYPES which, when defined prior to including `GL/glext.h`, will enable the definitions of a large number of standard functions. However, this may not work robustly if you're running on a computer which doesn't implement all of those functions which you're using. (You're likely to get missing symbol error during shared library loading.)

The better way to handle things is to use the [OpenGL Extension Wrangler](http://glew.sourceforge.net/) (GLEW). This hides the heavy lifting of the whole `*GetProcAddress()` process, defining symbols like `glDrawElementsInstanced` directly in the `glew.h` header. So long as you call `glewInit()` after initializing OpenGL but before using any version dependent function, these functions should be initialized appropriately if available, or to a null pointer if not.

You can either test for the function pointer being non-null, or use the GLEW-provided version test variables like `GLEW_VERSION_3_1`, which are booleans (not compile-time defines) indicating if that OpenGL version is supported on the computer the program is running on. Alternatively, you can [test on a feature-by-feature level](http://glew.sourceforge.net/basic.html) by using `glewIsSupported()`/`glewGetExtension()`. You can look up the respective strings for individual extensions at the [OpenGL Registry](https://www.khronos.org/registry/OpenGL/index_gl.php). It doesn't lend itself to forward searching, but may permit use of features prior to the nominal version of OpenGL in use.

So why wasn't this clearer to me before? I think it's because most of the tutorials and documentation about OpenGL simply assume that you're using GLEW. Despite its name, GLEW isn't just about extensions, it also abstracts much of the version-to-version compatibility issues. As long as you put use behind version checks and don't actually attempt to call a non-supported function, GLEW hides all the pesky details about functions which aren't actually being implemented.


---

