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