glfw/docs/context.md

383 lines
13 KiB
Markdown
Raw Normal View History

2024-02-13 19:45:29 +00:00
# Context guide {#context_guide}
2013-04-11 18:18:46 +00:00
[TOC]
2013-05-27 15:10:34 +00:00
2015-01-11 17:25:54 +00:00
This guide introduces the OpenGL and OpenGL ES context related functions of
2016-08-11 17:04:21 +00:00
GLFW. For details on a specific function in this category, see the @ref
context. There are also guides for the other areas of the GLFW API.
2013-05-27 15:10:34 +00:00
- @ref intro_guide
- @ref window_guide
- @ref vulkan_guide
- @ref monitor_guide
- @ref input_guide
2013-05-27 15:10:34 +00:00
2014-09-18 13:03:29 +00:00
2024-02-13 19:45:29 +00:00
## Context objects {#context_object}
2014-09-18 13:03:29 +00:00
2014-10-07 00:15:36 +00:00
A window object encapsulates both a top-level window and an OpenGL or OpenGL ES
context. It is created with @ref glfwCreateWindow and destroyed with @ref
glfwDestroyWindow or @ref glfwTerminate. See @ref window_creation for more
information.
2013-05-27 15:10:34 +00:00
2014-10-07 00:15:36 +00:00
As the window and context are inseparably linked, the window object also serves
as the context handle.
2013-05-27 15:10:34 +00:00
2015-01-11 17:25:54 +00:00
To test the creation of various kinds of contexts and see their properties, run
the `glfwinfo` test program.
@note Vulkan does not have a context and the Vulkan instance is created via the
Vulkan API itself. If you will be using Vulkan to render to a window, disable
2016-12-06 00:14:23 +00:00
context creation by setting the [GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint)
hint to `GLFW_NO_API`. For more information, see the @ref vulkan_guide.
2015-01-11 17:25:54 +00:00
2024-02-13 19:45:29 +00:00
### Context creation hints {#context_hints}
2013-05-27 15:10:34 +00:00
There are a number of hints, specified using @ref glfwWindowHint, related to
what kind of context is created. See
2014-09-18 13:03:29 +00:00
[context related hints](@ref window_hints_ctx) in the window guide.
2024-02-13 19:45:29 +00:00
### Context object sharing {#context_sharing}
2014-09-18 13:03:29 +00:00
When creating a window and its OpenGL or OpenGL ES context with @ref
glfwCreateWindow, you can specify another window whose context the new one
should share its objects (textures, vertex and element buffers, etc.) with.
```c
2014-09-18 13:03:29 +00:00
GLFWwindow* second_window = glfwCreateWindow(640, 480, "Second Window", NULL, first_window);
```
2013-05-27 15:10:34 +00:00
2014-09-18 13:03:29 +00:00
Object sharing is implemented by the operating system and graphics driver. On
platforms where it is possible to choose which types of objects are shared, GLFW
requests that all types are shared.
2013-05-27 15:10:34 +00:00
2014-09-18 13:03:29 +00:00
See the relevant chapter of the [OpenGL](https://www.opengl.org/registry/) or
2018-11-02 19:55:02 +00:00
[OpenGL ES](https://www.khronos.org/opengles/) reference documents for more
2014-09-18 13:03:29 +00:00
information. The name and number of this chapter unfortunately varies between
2014-10-02 15:35:10 +00:00
versions and APIs, but has at times been named _Shared Objects and Multiple
Contexts_.
2013-12-05 02:15:35 +00:00
GLFW comes with a bare-bones object sharing example program called `sharing`.
2013-12-05 02:15:35 +00:00
2024-02-13 19:45:29 +00:00
### Offscreen contexts {#context_offscreen}
2014-10-07 00:15:36 +00:00
GLFW doesn't support creating contexts without an associated window. However,
contexts with hidden windows can be created with the
2016-12-06 00:14:23 +00:00
[GLFW_VISIBLE](@ref GLFW_VISIBLE_hint) window hint.
2014-10-07 00:15:36 +00:00
```c
2015-08-23 17:30:04 +00:00
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
2014-10-07 00:15:36 +00:00
GLFWwindow* offscreen_context = glfwCreateWindow(640, 480, "", NULL, NULL);
```
2014-10-07 00:15:36 +00:00
The window never needs to be shown and its context can be used as a plain
2014-10-13 14:00:11 +00:00
offscreen context. Depending on the window manager, the size of a hidden
window's framebuffer may not be usable or modifiable, so framebuffer
objects are recommended for rendering with such contexts.
2014-10-07 00:15:36 +00:00
You should still [process events](@ref events) as long as you have at least one
window, even if none of them are visible.
2014-10-07 00:15:36 +00:00
2024-02-13 19:45:29 +00:00
### Windows without contexts {#context_less}
2015-11-05 12:44:15 +00:00
You can disable context creation by setting the
[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint to `GLFW_NO_API`.
Windows without contexts should not be passed to @ref glfwMakeContextCurrent or
@ref glfwSwapBuffers. Doing this generates a @ref GLFW_NO_WINDOW_CONTEXT error.
2015-11-05 12:44:15 +00:00
@subsection context_user User contexts for multi context windows
GLFW supports multiple OpenGL or OpenGL ES contexts per window. Providing
a window with an existing OpenGL or OpenGL ES context has been created further
user contexts can be created using @ref glfwCreateUserContext with the same
API sharing the window context objects.
@code
GLFWusercontext* usercontext = glfwCreateUserContext(window);
/* make the user context current */
glfwMakeUserContextCurrent(usercontext);
/* make the window context current */
glfwMakeContextCurrent(window);
/* destroy the user context */
glfwDestroyUserContext(usercontext);
@endcode
User contexts See also the test program `usercontext`.
2015-11-05 12:44:15 +00:00
2024-02-13 19:45:29 +00:00
## Current context {#context_current}
2013-05-27 15:10:34 +00:00
2014-04-23 11:30:11 +00:00
Before you can make OpenGL or OpenGL ES calls, you need to have a current
2014-10-13 14:00:11 +00:00
context of the correct type. A context can only be current for a single thread
at a time, and a thread can only have a single context current at a time.
2013-05-27 15:10:34 +00:00
2017-11-02 18:30:12 +00:00
When moving a context between threads, you must make it non-current on the old
thread before making it current on the new one.
2015-01-10 22:05:20 +00:00
The context of a window is made current with @ref glfwMakeContextCurrent.
2013-05-27 15:10:34 +00:00
```c
2013-05-27 15:10:34 +00:00
glfwMakeContextCurrent(window);
```
2013-05-27 15:10:34 +00:00
2015-01-10 22:05:20 +00:00
The window of the current context is returned by @ref glfwGetCurrentContext.
2013-05-27 15:10:34 +00:00
```c
2013-05-27 15:10:34 +00:00
GLFWwindow* window = glfwGetCurrentContext();
```
2013-05-27 15:10:34 +00:00
2015-01-10 22:05:20 +00:00
The following GLFW functions require a context to be current. Calling any these
functions without a current context will generate a @ref GLFW_NO_CURRENT_CONTEXT
error.
2014-04-23 11:30:11 +00:00
2014-10-13 14:00:11 +00:00
- @ref glfwSwapInterval
- @ref glfwExtensionSupported
- @ref glfwGetProcAddress
@subsection context_current_user Current user context
When using [user contexts](@ref context_user) the user context can be
made current using @ref glfwMakeUserContextCurrent.
@code
glfwMakeUserContextCurrent(usercontext);
@endcode
This makes the any window context non-current on the calling thread, such that
a call to @ref glfwGetCurrentContext will return `NULL`.
The current user context is returned by @ref glfwGetCurrentUserContext.
@code
GLFWusercontext* usercontext = glfwGetCurrentUserContext();
@endcode
This will return the current user context or `NULL` if either the main window context
or no context is current.
2013-05-27 15:10:34 +00:00
2024-02-13 19:45:29 +00:00
## Buffer swapping {#context_swap}
2013-05-27 15:10:34 +00:00
2017-11-27 00:18:51 +00:00
See @ref buffer_swap in the window guide.
2013-05-27 15:10:34 +00:00
2024-02-13 19:45:29 +00:00
## OpenGL and OpenGL ES extensions {#context_glext}
2013-04-11 18:18:46 +00:00
2015-10-18 10:15:06 +00:00
One of the benefits of OpenGL and OpenGL ES is their extensibility.
2014-04-23 11:30:11 +00:00
Hardware vendors may include extensions in their implementations that extend the
API before that functionality is included in a new version of the OpenGL or
OpenGL ES specification, and some extensions are never included and remain
as extensions until they become obsolete.
2013-04-11 18:18:46 +00:00
An extension is defined by:
- An extension name (e.g. `GL_ARB_gl_spirv`)
- New OpenGL tokens (e.g. `GL_SPIR_V_BINARY_ARB`)
- New OpenGL functions (e.g. `glSpecializeShaderARB`)
2013-04-11 18:18:46 +00:00
Note the `ARB` affix, which stands for Architecture Review Board and is used
2014-04-23 11:30:11 +00:00
for official extensions. The extension above was created by the ARB, but there
are many different affixes, like `NV` for Nvidia and `AMD` for, well, AMD. Any
group may also use the generic `EXT` affix. Lists of extensions, together with
their specifications, can be found at the
2018-11-02 19:55:02 +00:00
[OpenGL Registry](https://www.opengl.org/registry/) and
2014-04-23 11:30:11 +00:00
[OpenGL ES Registry](https://www.khronos.org/registry/gles/).
2024-02-13 19:45:29 +00:00
### Loading extension with a loader library {#context_glext_auto}
2014-04-23 11:30:11 +00:00
2015-01-10 22:05:20 +00:00
An extension loader library is the easiest and best way to access both OpenGL and
OpenGL ES extensions and modern versions of the core OpenGL or OpenGL ES APIs.
They will take care of all the details of declaring and loading everything you
need. One such library is [glad](https://github.com/Dav1dde/glad) and there are
2017-11-17 03:34:18 +00:00
several others.
2014-04-23 11:30:11 +00:00
2015-01-10 22:05:20 +00:00
The following example will use glad but all extension loader libraries work
2015-01-05 15:46:04 +00:00
similarly.
2014-04-23 11:30:11 +00:00
First you need to generate the source files using the glad Python script. This
example generates a loader for any version of OpenGL, which is the default for
both GLFW and glad, but loaders for OpenGL ES, as well as loaders for specific
API versions and extension sets can be generated. The generated files are
written to the `output` directory.
```sh
2015-01-10 22:05:20 +00:00
python main.py --generator c --no-loader --out-path output
```
2014-04-23 11:30:11 +00:00
2014-10-13 14:00:11 +00:00
The `--no-loader` option is added because GLFW already provides a function for
loading OpenGL and OpenGL ES function pointers, one that automatically uses the
selected context creation API, and glad can call this instead of having to
implement its own. There are several other command-line options as well. See
the glad documentation for details.
2014-04-23 11:30:11 +00:00
Add the generated `output/src/glad.c`, `output/include/glad/glad.h` and
`output/include/KHR/khrplatform.h` files to your build. Then you need to
include the glad header file, which will replace the OpenGL header of your
2015-01-10 22:05:20 +00:00
development environment. By including the glad header before the GLFW header,
it suppresses the development environment's OpenGL or OpenGL ES header.
2014-04-23 11:30:11 +00:00
```c
2014-04-23 11:30:11 +00:00
#include <glad/glad.h>
#include <GLFW/glfw3.h>
```
2014-04-23 11:30:11 +00:00
Finally, you need to initialize glad once you have a suitable current context.
2014-04-23 11:30:11 +00:00
```c
2014-04-23 11:30:11 +00:00
window = glfwCreateWindow(640, 480, "My Window", NULL, NULL);
if (!window)
{
...
}
glfwMakeContextCurrent(window);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
```
2014-04-23 11:30:11 +00:00
Once glad has been loaded, you have access to all OpenGL core and extension
2015-01-10 22:05:20 +00:00
functions supported by both the context you created and the glad loader you
generated. After that, you are ready to start rendering.
2014-04-23 11:30:11 +00:00
You can specify a minimum required OpenGL or OpenGL ES version with
[context hints](@ref window_hints_ctx). If your needs are more complex, you can
check the actual OpenGL or OpenGL ES version with
2015-01-18 00:55:25 +00:00
[context attributes](@ref window_attribs_ctx), or you can check whether
2014-04-23 11:30:11 +00:00
a specific version is supported by the current context with the
`GLAD_GL_VERSION_x_x` booleans.
```c
2014-04-23 11:30:11 +00:00
if (GLAD_GL_VERSION_3_2)
{
// Call OpenGL 3.2+ specific code
}
```
2014-04-23 11:30:11 +00:00
To check whether a specific extension is supported, use the `GLAD_GL_xxx`
booleans.
```c
if (GLAD_GL_ARB_gl_spirv)
2014-04-23 11:30:11 +00:00
{
// Use GL_ARB_gl_spirv
2014-04-23 11:30:11 +00:00
}
```
2014-04-23 11:30:11 +00:00
2024-02-13 19:45:29 +00:00
### Loading extensions manually {#context_glext_manual}
2013-04-11 18:18:46 +00:00
2015-01-10 22:05:20 +00:00
__Do not use this technique__ unless it is absolutely necessary. An
[extension loader library](@ref context_glext_auto) will save you a ton of
tedious, repetitive, error prone work.
2013-05-27 15:10:34 +00:00
To use a certain extension, you must first check whether the context supports
2013-04-11 18:18:46 +00:00
that extension and then, if it introduces new functions, retrieve the pointers
2014-04-23 11:30:11 +00:00
to those functions. GLFW provides @ref glfwExtensionSupported and @ref
glfwGetProcAddress for manual loading of extensions and new API functions.
2013-04-11 18:18:46 +00:00
2015-01-10 22:05:20 +00:00
This section will demonstrate manual loading of OpenGL extensions. The loading
of OpenGL ES extensions is identical except for the name of the extension header.
2013-04-11 18:18:46 +00:00
2024-02-13 19:45:29 +00:00
#### The glext.h header {#context_glext_header}
2013-04-11 18:18:46 +00:00
2015-01-10 22:05:20 +00:00
The `glext.h` extension header is a continually updated file that defines the
interfaces for all OpenGL extensions. The latest version of this can always be
2018-11-02 19:55:02 +00:00
found at the [OpenGL Registry](https://www.opengl.org/registry/). There are also
2015-01-10 22:05:20 +00:00
extension headers for the various versions of OpenGL ES at the
[OpenGL ES Registry](https://www.khronos.org/registry/gles/). It it strongly
recommended that you use your own copy of the extension header, as the one
included in your development environment may be several years out of date and
may not include the extensions you wish to use.
2013-04-11 18:18:46 +00:00
The header defines function pointer types for all functions of all extensions it
supports. These have names like `PFNGLSPECIALIZESHADERARBPROC` (for
`glSpecializeShaderARB`), i.e. the name is made uppercase and `PFN` (pointer
2014-04-23 11:30:11 +00:00
to function) and `PROC` (procedure) are added to the ends.
2013-04-11 18:18:46 +00:00
2016-12-06 00:14:23 +00:00
To include the extension header, define @ref GLFW_INCLUDE_GLEXT before including
the GLFW header.
2015-01-10 22:05:20 +00:00
```c
2015-01-10 22:05:20 +00:00
#define GLFW_INCLUDE_GLEXT
#include <GLFW/glfw3.h>
```
2015-01-10 22:05:20 +00:00
2013-04-11 18:18:46 +00:00
2024-02-13 19:45:29 +00:00
#### Checking for extensions {#context_glext_string}
2013-04-11 18:18:46 +00:00
A given machine may not actually support the extension (it may have older
drivers or a graphics card that lacks the necessary hardware features), so it
2015-01-10 22:05:20 +00:00
is necessary to check at run-time whether the context supports the extension.
This is done with @ref glfwExtensionSupported.
2013-04-11 18:18:46 +00:00
```c
if (glfwExtensionSupported("GL_ARB_gl_spirv"))
2013-04-11 18:18:46 +00:00
{
2013-05-27 15:10:34 +00:00
// The extension is supported by the current context
2013-04-11 18:18:46 +00:00
}
```
2013-04-11 18:18:46 +00:00
The argument is a null terminated ASCII string with the extension name. If the
2015-08-23 17:30:04 +00:00
extension is supported, @ref glfwExtensionSupported returns `GLFW_TRUE`,
otherwise it returns `GLFW_FALSE`.
2013-04-11 18:18:46 +00:00
2024-02-13 19:45:29 +00:00
#### Fetching function pointers {#context_glext_proc}
2013-04-11 18:18:46 +00:00
Many extensions, though not all, require the use of new OpenGL functions.
2014-04-23 11:30:11 +00:00
These functions often do not have entry points in the client API libraries of
your operating system, making it necessary to fetch them at run time. You can
2015-01-05 15:46:04 +00:00
retrieve pointers to these functions with @ref glfwGetProcAddress.
2013-04-11 18:18:46 +00:00
```c
PFNGLSPECIALIZESHADERARBPROC pfnSpecializeShaderARB = glfwGetProcAddress("glSpecializeShaderARB");
```
2013-04-11 18:18:46 +00:00
In general, you should avoid giving the function pointer variables the (exact)
same name as the function, as this may confuse your linker. Instead, you can
use a different prefix, like above, or some other naming scheme.
Now that all the pieces have been introduced, here is what they might look like
when used together.
```c
2015-01-10 22:05:20 +00:00
#define GLFW_INCLUDE_GLEXT
#include <GLFW/glfw3.h>
2013-04-11 18:18:46 +00:00
#define glSpecializeShaderARB pfnSpecializeShaderARB
PFNGLSPECIALIZESHADERARBPROC pfnSpecializeShaderARB;
2013-04-11 18:18:46 +00:00
2013-05-27 15:10:34 +00:00
// Flag indicating whether the extension is supported
int has_ARB_gl_spirv = 0;
2013-04-11 18:18:46 +00:00
void load_extensions(void)
{
if (glfwExtensionSupported("GL_ARB_gl_spirv"))
2013-04-11 18:18:46 +00:00
{
pfnSpecializeShaderARB = (PFNGLSPECIALIZESHADERARBPROC)
glfwGetProcAddress("glSpecializeShaderARB");
has_ARB_gl_spirv = 1;
2013-04-11 18:18:46 +00:00
}
}
void some_function(void)
{
if (has_ARB_gl_spirv)
2015-01-10 22:05:20 +00:00
{
// Now the extension function can be called as usual
glSpecializeShaderARB(...);
2015-01-10 22:05:20 +00:00
}
2013-04-11 18:18:46 +00:00
}
```
2013-04-11 18:18:46 +00:00