Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 1 | /*! |
| 2 | |
Camilla Berglund | 4591ad2 | 2014-09-18 15:03:29 +0200 | [diff] [blame] | 3 | @page context Context guide |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 4 | |
| 5 | @tableofcontents |
| 6 | |
Camilla Berglund | 4e375d0 | 2015-01-11 18:25:54 +0100 | [diff] [blame] | 7 | This guide introduces the OpenGL and OpenGL ES context related functions of |
| 8 | GLFW. There are also guides for the other areas of the GLFW API. |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 9 | |
Camilla Berglund | 4591ad2 | 2014-09-18 15:03:29 +0200 | [diff] [blame] | 10 | - @ref intro |
| 11 | - @ref window |
| 12 | - @ref monitor |
| 13 | - @ref input |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 14 | |
Camilla Berglund | 4591ad2 | 2014-09-18 15:03:29 +0200 | [diff] [blame] | 15 | |
| 16 | @section context_object Context objects |
| 17 | |
Camilla Berglund | 96d230b | 2014-10-07 02:15:36 +0200 | [diff] [blame] | 18 | A window object encapsulates both a top-level window and an OpenGL or OpenGL ES |
| 19 | context. It is created with @ref glfwCreateWindow and destroyed with @ref |
| 20 | glfwDestroyWindow or @ref glfwTerminate. See @ref window_creation for more |
| 21 | information. |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 22 | |
Camilla Berglund | 96d230b | 2014-10-07 02:15:36 +0200 | [diff] [blame] | 23 | As the window and context are inseparably linked, the window object also serves |
| 24 | as the context handle. |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 25 | |
Camilla Berglund | 4e375d0 | 2015-01-11 18:25:54 +0100 | [diff] [blame] | 26 | To test the creation of various kinds of contexts and see their properties, run |
| 27 | the `glfwinfo` test program. |
| 28 | |
| 29 | |
Camilla Berglund | 4591ad2 | 2014-09-18 15:03:29 +0200 | [diff] [blame] | 30 | @subsection context_hints Context creation hints |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 31 | |
| 32 | There are a number of hints, specified using @ref glfwWindowHint, related to |
| 33 | what kind of context is created. See |
Camilla Berglund | 4591ad2 | 2014-09-18 15:03:29 +0200 | [diff] [blame] | 34 | [context related hints](@ref window_hints_ctx) in the window guide. |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 35 | |
| 36 | |
Camilla Berglund | 4591ad2 | 2014-09-18 15:03:29 +0200 | [diff] [blame] | 37 | @subsection context_sharing Context object sharing |
Camilla Berglund | 5668eb0 | 2013-12-05 03:15:35 +0100 | [diff] [blame] | 38 | |
Camilla Berglund | 4591ad2 | 2014-09-18 15:03:29 +0200 | [diff] [blame] | 39 | When creating a window and its OpenGL or OpenGL ES context with @ref |
| 40 | glfwCreateWindow, you can specify another window whose context the new one |
| 41 | should share its objects (textures, vertex and element buffers, etc.) with. |
| 42 | |
| 43 | @code |
| 44 | GLFWwindow* second_window = glfwCreateWindow(640, 480, "Second Window", NULL, first_window); |
| 45 | @endcode |
| 46 | |
| 47 | Object sharing is implemented by the operating system and graphics driver. On |
| 48 | platforms where it is possible to choose which types of objects are shared, GLFW |
| 49 | requests that all types are shared. |
| 50 | |
| 51 | See the relevant chapter of the [OpenGL](https://www.opengl.org/registry/) or |
| 52 | [OpenGL ES](http://www.khronos.org/opengles/) reference documents for more |
| 53 | information. The name and number of this chapter unfortunately varies between |
Camilla Berglund | 95654cf | 2014-10-02 17:35:10 +0200 | [diff] [blame] | 54 | versions and APIs, but has at times been named _Shared Objects and Multiple |
| 55 | Contexts_. |
Camilla Berglund | 4591ad2 | 2014-09-18 15:03:29 +0200 | [diff] [blame] | 56 | |
| 57 | GLFW comes with a simple object sharing test program called `sharing`. |
Camilla Berglund | 5668eb0 | 2013-12-05 03:15:35 +0100 | [diff] [blame] | 58 | |
| 59 | |
Camilla Berglund | 96d230b | 2014-10-07 02:15:36 +0200 | [diff] [blame] | 60 | @subsection context_offscreen Offscreen contexts |
| 61 | |
| 62 | GLFW doesn't support creating contexts without an associated window. However, |
| 63 | contexts with hidden windows can be created with the |
| 64 | [GLFW_VISIBLE](@ref window_hints_wnd) window hint. |
| 65 | |
| 66 | @code |
Camilla Berglund | 0eccf75 | 2015-08-23 19:30:04 +0200 | [diff] [blame] | 67 | glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); |
Camilla Berglund | 96d230b | 2014-10-07 02:15:36 +0200 | [diff] [blame] | 68 | |
| 69 | GLFWwindow* offscreen_context = glfwCreateWindow(640, 480, "", NULL, NULL); |
| 70 | @endcode |
| 71 | |
| 72 | The window never needs to be shown and its context can be used as a plain |
Camilla Berglund | 2d13eb0 | 2014-10-13 16:00:11 +0200 | [diff] [blame] | 73 | offscreen context. Depending on the window manager, the size of a hidden |
| 74 | window's framebuffer may not be usable or modifiable, so framebuffer |
| 75 | objects are recommended for rendering with such contexts. |
Camilla Berglund | 96d230b | 2014-10-07 02:15:36 +0200 | [diff] [blame] | 76 | |
| 77 | __OS X:__ The first time a window is created the menu bar is populated with |
Camilla Berglund | 2d13eb0 | 2014-10-13 16:00:11 +0200 | [diff] [blame] | 78 | common commands like Hide, Quit and About. This is not desirable for example |
| 79 | when writing a command-line only application. The menu bar setup can be |
| 80 | disabled with a [compile-time option](@ref compile_options_osx). |
Camilla Berglund | 96d230b | 2014-10-07 02:15:36 +0200 | [diff] [blame] | 81 | |
| 82 | |
Camilla Berglund | 98b478f | 2015-11-05 13:44:15 +0100 | [diff] [blame] | 83 | @subsection context_less Windows without contexts |
| 84 | |
| 85 | You can disable context creation by setting the |
| 86 | [GLFW_CLIENT_API](@ref window_hints_ctx) hint to `GLFW_NO_API`. Windows without |
| 87 | contexts may not be passed to @ref glfwMakeContextCurrent or @ref |
| 88 | glfwSwapBuffers. |
| 89 | |
| 90 | |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 91 | @section context_current Current context |
| 92 | |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 93 | Before you can make OpenGL or OpenGL ES calls, you need to have a current |
Camilla Berglund | 2d13eb0 | 2014-10-13 16:00:11 +0200 | [diff] [blame] | 94 | context of the correct type. A context can only be current for a single thread |
| 95 | at a time, and a thread can only have a single context current at a time. |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 96 | |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 97 | The context of a window is made current with @ref glfwMakeContextCurrent. |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 98 | |
| 99 | @code |
| 100 | glfwMakeContextCurrent(window); |
| 101 | @endcode |
| 102 | |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 103 | The window of the current context is returned by @ref glfwGetCurrentContext. |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 104 | |
| 105 | @code |
| 106 | GLFWwindow* window = glfwGetCurrentContext(); |
| 107 | @endcode |
| 108 | |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 109 | The following GLFW functions require a context to be current. Calling any these |
| 110 | functions without a current context will generate a @ref GLFW_NO_CURRENT_CONTEXT |
| 111 | error. |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 112 | |
Camilla Berglund | 2d13eb0 | 2014-10-13 16:00:11 +0200 | [diff] [blame] | 113 | - @ref glfwSwapInterval |
| 114 | - @ref glfwExtensionSupported |
| 115 | - @ref glfwGetProcAddress |
| 116 | |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 117 | |
Camilla Berglund | 4591ad2 | 2014-09-18 15:03:29 +0200 | [diff] [blame] | 118 | @section context_swap Buffer swapping |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 119 | |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 120 | Buffer swapping is part of the window and framebuffer, not the context. See |
Camilla Berglund | 4188c26 | 2015-01-18 01:55:25 +0100 | [diff] [blame] | 121 | @ref buffer_swap. |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 122 | |
| 123 | |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 124 | @section context_glext OpenGL and OpenGL ES extensions |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 125 | |
Camilla Berglund | b312f5e | 2015-10-18 12:15:06 +0200 | [diff] [blame] | 126 | One of the benefits of OpenGL and OpenGL ES is their extensibility. |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 127 | Hardware vendors may include extensions in their implementations that extend the |
| 128 | API before that functionality is included in a new version of the OpenGL or |
| 129 | OpenGL ES specification, and some extensions are never included and remain |
| 130 | as extensions until they become obsolete. |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 131 | |
| 132 | An extension is defined by: |
| 133 | |
| 134 | - An extension name (e.g. `GL_ARB_debug_output`) |
| 135 | - New OpenGL tokens (e.g. `GL_DEBUG_SEVERITY_HIGH_ARB`) |
| 136 | - New OpenGL functions (e.g. `glGetDebugMessageLogARB`) |
| 137 | |
| 138 | Note the `ARB` affix, which stands for Architecture Review Board and is used |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 139 | for official extensions. The extension above was created by the ARB, but there |
| 140 | are many different affixes, like `NV` for Nvidia and `AMD` for, well, AMD. Any |
| 141 | group may also use the generic `EXT` affix. Lists of extensions, together with |
| 142 | their specifications, can be found at the |
| 143 | [OpenGL Registry](http://www.opengl.org/registry/) and |
| 144 | [OpenGL ES Registry](https://www.khronos.org/registry/gles/). |
| 145 | |
| 146 | |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 147 | @subsection context_glext_auto Loading extension with a loader library |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 148 | |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 149 | An extension loader library is the easiest and best way to access both OpenGL and |
| 150 | OpenGL ES extensions and modern versions of the core OpenGL or OpenGL ES APIs. |
| 151 | They will take care of all the details of declaring and loading everything you |
| 152 | need. One such library is [glad](https://github.com/Dav1dde/glad) and there are |
| 153 | several others. |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 154 | |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 155 | The following example will use glad but all extension loader libraries work |
Camilla Berglund | 138feb8 | 2015-01-05 16:46:04 +0100 | [diff] [blame] | 156 | similarly. |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 157 | |
| 158 | First you need to generate the source files using the glad Python script. This |
| 159 | example generates a loader for any version of OpenGL, which is the default for |
| 160 | both GLFW and glad, but loaders for OpenGL ES, as well as loaders for specific |
| 161 | API versions and extension sets can be generated. The generated files are |
| 162 | written to the `output` directory. |
| 163 | |
| 164 | @code{.sh} |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 165 | python main.py --generator c --no-loader --out-path output |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 166 | @endcode |
| 167 | |
Camilla Berglund | 2d13eb0 | 2014-10-13 16:00:11 +0200 | [diff] [blame] | 168 | The `--no-loader` option is added because GLFW already provides a function for |
| 169 | loading OpenGL and OpenGL ES function pointers and glad can call this instead of |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 170 | having to implement its own. There are several other command-line options as |
| 171 | well. See the glad documentation for details. |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 172 | |
| 173 | Add the generated `output/src/glad.c`, `output/include/glad/glad.h` and |
| 174 | `output/include/KHR/khrplatform.h` files to your build. Then you need to |
| 175 | include the glad header file, which will replace the OpenGL header of your |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 176 | development environment. By including the glad header before the GLFW header, |
| 177 | it suppresses the development environment's OpenGL or OpenGL ES header. |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 178 | |
| 179 | @code |
| 180 | #include <glad/glad.h> |
| 181 | #include <GLFW/glfw3.h> |
| 182 | @endcode |
| 183 | |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 184 | Finally you need to initialize glad once you have a suitable current context. |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 185 | |
| 186 | @code |
| 187 | window = glfwCreateWindow(640, 480, "My Window", NULL, NULL); |
| 188 | if (!window) |
| 189 | { |
| 190 | ... |
| 191 | } |
| 192 | |
| 193 | glfwMakeContextCurrent(window); |
| 194 | |
| 195 | gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); |
| 196 | @endcode |
| 197 | |
| 198 | Once glad has been loaded, you have access to all OpenGL core and extension |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 199 | functions supported by both the context you created and the glad loader you |
| 200 | generated and you are ready to start rendering. |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 201 | |
| 202 | You can specify a minimum required OpenGL or OpenGL ES version with |
| 203 | [context hints](@ref window_hints_ctx). If your needs are more complex, you can |
| 204 | check the actual OpenGL or OpenGL ES version with |
Camilla Berglund | 4188c26 | 2015-01-18 01:55:25 +0100 | [diff] [blame] | 205 | [context attributes](@ref window_attribs_ctx), or you can check whether |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 206 | a specific version is supported by the current context with the |
| 207 | `GLAD_GL_VERSION_x_x` booleans. |
| 208 | |
| 209 | @code |
| 210 | if (GLAD_GL_VERSION_3_2) |
| 211 | { |
| 212 | // Call OpenGL 3.2+ specific code |
| 213 | } |
| 214 | @endcode |
| 215 | |
| 216 | To check whether a specific extension is supported, use the `GLAD_GL_xxx` |
| 217 | booleans. |
| 218 | |
| 219 | @code |
| 220 | if (GLAD_GL_ARB_debug_output) |
| 221 | { |
| 222 | // Use GL_ARB_debug_output |
| 223 | } |
| 224 | @endcode |
| 225 | |
| 226 | |
| 227 | @subsection context_glext_manual Loading extensions manually |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 228 | |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 229 | __Do not use this technique__ unless it is absolutely necessary. An |
| 230 | [extension loader library](@ref context_glext_auto) will save you a ton of |
| 231 | tedious, repetitive, error prone work. |
| 232 | |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 233 | To use a certain extension, you must first check whether the context supports |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 234 | that extension and then, if it introduces new functions, retrieve the pointers |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 235 | to those functions. GLFW provides @ref glfwExtensionSupported and @ref |
| 236 | glfwGetProcAddress for manual loading of extensions and new API functions. |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 237 | |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 238 | This section will demonstrate manual loading of OpenGL extensions. The loading |
| 239 | of OpenGL ES extensions is identical except for the name of the extension header. |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 240 | |
| 241 | |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 242 | @subsubsection context_glext_header The glext.h header |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 243 | |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 244 | The `glext.h` extension header is a continually updated file that defines the |
| 245 | interfaces for all OpenGL extensions. The latest version of this can always be |
| 246 | found at the [OpenGL Registry](http://www.opengl.org/registry/). There are also |
| 247 | extension headers for the various versions of OpenGL ES at the |
| 248 | [OpenGL ES Registry](https://www.khronos.org/registry/gles/). It it strongly |
| 249 | recommended that you use your own copy of the extension header, as the one |
| 250 | included in your development environment may be several years out of date and |
| 251 | may not include the extensions you wish to use. |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 252 | |
| 253 | The header defines function pointer types for all functions of all extensions it |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 254 | supports. These have names like `PFNGLGETDEBUGMESSAGELOGARBPROC` (for |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 255 | `glGetDebugMessageLogARB`), i.e. the name is made uppercase and `PFN` (pointer |
| 256 | to function) and `PROC` (procedure) are added to the ends. |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 257 | |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 258 | To include the extension header, define [GLFW_INCLUDE_GLEXT](@ref build_macros) |
| 259 | before including the GLFW header. |
| 260 | |
| 261 | @code |
| 262 | #define GLFW_INCLUDE_GLEXT |
| 263 | #include <GLFW/glfw3.h> |
| 264 | @endcode |
| 265 | |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 266 | |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 267 | @subsubsection context_glext_string Checking for extensions |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 268 | |
| 269 | A given machine may not actually support the extension (it may have older |
| 270 | drivers or a graphics card that lacks the necessary hardware features), so it |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 271 | is necessary to check at run-time whether the context supports the extension. |
| 272 | This is done with @ref glfwExtensionSupported. |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 273 | |
| 274 | @code |
| 275 | if (glfwExtensionSupported("GL_ARB_debug_output")) |
| 276 | { |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 277 | // The extension is supported by the current context |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 278 | } |
| 279 | @endcode |
| 280 | |
| 281 | The argument is a null terminated ASCII string with the extension name. If the |
Camilla Berglund | 0eccf75 | 2015-08-23 19:30:04 +0200 | [diff] [blame] | 282 | extension is supported, @ref glfwExtensionSupported returns `GLFW_TRUE`, |
| 283 | otherwise it returns `GLFW_FALSE`. |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 284 | |
| 285 | |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 286 | @subsubsection context_glext_proc Fetching function pointers |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 287 | |
| 288 | Many extensions, though not all, require the use of new OpenGL functions. |
Camilla Berglund | e8e05d4 | 2014-04-23 13:30:11 +0200 | [diff] [blame] | 289 | These functions often do not have entry points in the client API libraries of |
| 290 | your operating system, making it necessary to fetch them at run time. You can |
Camilla Berglund | 138feb8 | 2015-01-05 16:46:04 +0100 | [diff] [blame] | 291 | retrieve pointers to these functions with @ref glfwGetProcAddress. |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 292 | |
| 293 | @code |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 294 | PFNGLGETDEBUGMESSAGELOGARBPROC pfnGetDebugMessageLog = glfwGetProcAddress("glGetDebugMessageLogARB"); |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 295 | @endcode |
| 296 | |
| 297 | In general, you should avoid giving the function pointer variables the (exact) |
| 298 | same name as the function, as this may confuse your linker. Instead, you can |
| 299 | use a different prefix, like above, or some other naming scheme. |
| 300 | |
| 301 | Now that all the pieces have been introduced, here is what they might look like |
| 302 | when used together. |
| 303 | |
| 304 | @code |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 305 | #define GLFW_INCLUDE_GLEXT |
| 306 | #include <GLFW/glfw3.h> |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 307 | |
| 308 | #define glGetDebugMessageLogARB pfnGetDebugMessageLog |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 309 | PFNGLGETDEBUGMESSAGELOGARBPROC pfnGetDebugMessageLog; |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 310 | |
Camilla Berglund | 1f5f20e | 2013-05-27 17:10:34 +0200 | [diff] [blame] | 311 | // Flag indicating whether the extension is supported |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 312 | int has_ARB_debug_output = 0; |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 313 | |
| 314 | void load_extensions(void) |
| 315 | { |
| 316 | if (glfwExtensionSupported("GL_ARB_debug_output")) |
| 317 | { |
Camilla Berglund | c8e0687 | 2015-08-27 21:40:22 +0200 | [diff] [blame] | 318 | pfnGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGARBPROC) |
| 319 | glfwGetProcAddress("glGetDebugMessageLogARB"); |
| 320 | has_ARB_debug_output = 1; |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 321 | } |
| 322 | } |
| 323 | |
| 324 | void some_function(void) |
| 325 | { |
Camilla Berglund | 500f5eb | 2015-01-10 23:05:20 +0100 | [diff] [blame] | 326 | if (has_ARB_debug_output) |
| 327 | { |
| 328 | // Now the extension function can be called as usual |
| 329 | glGetDebugMessageLogARB(...); |
| 330 | } |
Camilla Berglund | 608109c | 2013-04-11 20:18:46 +0200 | [diff] [blame] | 331 | } |
| 332 | @endcode |
| 333 | |
| 334 | */ |