• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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