You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
260 lines
8.9 KiB
260 lines
8.9 KiB
/*! |
|
|
|
@page context Context handling guide |
|
|
|
@tableofcontents |
|
|
|
The primary purpose of GLFW is to provide a simple interface to window |
|
management and OpenGL and OpenGL ES context creation. GLFW supports |
|
multiple windows, with each window having its own context. |
|
|
|
|
|
@section context_object Context handles |
|
|
|
The @ref GLFWwindow object encapsulates both a [window](@ref window) and |
|
a context. It is created with @ref glfwCreateWindow and destroyed with @ref |
|
glfwDestroyWindow or @ref glfwTerminate. As the window and context are |
|
inseparably linked, the object pointer is used as both a context and window |
|
handle. |
|
|
|
|
|
@section context_hints Context creation hints |
|
|
|
There are a number of hints, specified using @ref glfwWindowHint, related to |
|
what kind of context is created. See |
|
[context related hints](@ref window_hints_ctx) in the window handling guide. |
|
|
|
|
|
@section context_sharing Context object sharing |
|
|
|
When creating a window and context with @ref glfwCreateWindow, you can specify |
|
another window whose context the new one should share its objects with. Object |
|
sharing is implemented by the operating system and graphics driver and is |
|
described in the OpenGL and OpenGL ES documentation. On platforms where it is |
|
possible to choose which types of objects are shared, GLFW requests that all are |
|
shared. |
|
|
|
|
|
@section context_current Current context |
|
|
|
Before you can make OpenGL or OpenGL ES calls, you need to have a current |
|
context of the proper type. The context encapsulates all render state and all |
|
objects like textures and shaders. |
|
|
|
A context is made current with @ref glfwMakeContextCurrent. |
|
|
|
@code |
|
glfwMakeContextCurrent(window); |
|
@endcode |
|
|
|
The current context is returned by @ref glfwGetCurrentContext. |
|
|
|
@code |
|
GLFWwindow* window = glfwGetCurrentContext(); |
|
@endcode |
|
|
|
@note A context must only be current for a single thread at a time, and a thread |
|
must only have a single context current at a time. |
|
|
|
|
|
@section context_swap Swapping buffers |
|
|
|
Buffer swapping is part of the window and framebuffer, not the context. See |
|
@ref window_swap in the window handling guide. |
|
|
|
|
|
@section context_glext OpenGL and OpenGL ES extensions |
|
|
|
One of the benefits of OpenGL and OpenGL ES are their extensibility. |
|
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. |
|
|
|
An extension is defined by: |
|
|
|
- An extension name (e.g. `GL_ARB_debug_output`) |
|
- New OpenGL tokens (e.g. `GL_DEBUG_SEVERITY_HIGH_ARB`) |
|
- New OpenGL functions (e.g. `glGetDebugMessageLogARB`) |
|
|
|
Note the `ARB` affix, which stands for Architecture Review Board and is used |
|
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 |
|
[OpenGL Registry](http://www.opengl.org/registry/) and |
|
[OpenGL ES Registry](https://www.khronos.org/registry/gles/). |
|
|
|
|
|
@subsection context_glext_auto Using an extension loader library |
|
|
|
This is the easiest and best way to load extensions and newer versions of the |
|
OpenGL or OpenGL ES API. One such library is |
|
[glad](https://github.com/Dav1dde/glad) and there are several others. They will |
|
take care of all the details of declaring and loading everything you need. |
|
|
|
The following example will use glad, but other extension loader libraries work |
|
similary. |
|
|
|
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. |
|
|
|
@code{.sh} |
|
python main.py --no-loader --out-path output |
|
@endcode |
|
|
|
@note The `--no-loader` option is used because GLFW already provides a function |
|
for loading OpenGL and OpenGL ES function pointers and glad can use this instead |
|
of having to add its own. |
|
|
|
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 |
|
development environment. |
|
|
|
@code |
|
#include <glad/glad.h> |
|
#include <GLFW/glfw3.h> |
|
@endcode |
|
|
|
Finally you need to initialize glad once you have a matching current context. |
|
|
|
@code |
|
window = glfwCreateWindow(640, 480, "My Window", NULL, NULL); |
|
if (!window) |
|
{ |
|
... |
|
} |
|
|
|
glfwMakeContextCurrent(window); |
|
|
|
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); |
|
@endcode |
|
|
|
Once glad has been loaded, you have access to all OpenGL core and extension |
|
functions supported by the context you created and you are ready to start |
|
rendering. |
|
|
|
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 |
|
[context attributes](@ref window_attribs_context), or you can check whether |
|
a specific version is supported by the current context with the |
|
`GLAD_GL_VERSION_x_x` booleans. |
|
|
|
@code |
|
if (GLAD_GL_VERSION_3_2) |
|
{ |
|
// Call OpenGL 3.2+ specific code |
|
} |
|
@endcode |
|
|
|
To check whether a specific extension is supported, use the `GLAD_GL_xxx` |
|
booleans. |
|
|
|
@code |
|
if (GLAD_GL_ARB_debug_output) |
|
{ |
|
// Use GL_ARB_debug_output |
|
} |
|
@endcode |
|
|
|
|
|
@subsection context_glext_manual Loading extensions manually |
|
|
|
To use a certain extension, you must first check whether the context supports |
|
that extension and then, if it introduces new functions, retrieve the pointers |
|
to those functions. GLFW provides @ref glfwExtensionSupported and @ref |
|
glfwGetProcAddress for manual loading of extensions and new API functions. |
|
|
|
@note It is strongly recommended that you use an existing extension loader |
|
library like [glad](https://github.com/Dav1dde/glad) instead of loading |
|
manually. Extension loading is a solved problem and you will gain nothing from |
|
solving it again by hand. |
|
|
|
|
|
@subsubsection context_glext_header The glext.h header |
|
|
|
The `glext.h` header is a continually updated file that defines the interfaces |
|
for all OpenGL extensions. The latest version of this can always be found at |
|
the [OpenGL Registry](http://www.opengl.org/registry/). It it strongly |
|
recommended that you use your own copy, as the one shipped with your development |
|
environment may be several years out of date and may not include the extensions |
|
you wish to use. |
|
|
|
The header defines function pointer types for all functions of all extensions it |
|
supports. These have names like `PFNGLGETDEBUGMESSAGELOGARB` (for |
|
`glGetDebugMessageLogARB`), i.e. the name is made uppercase and `PFN` (pointer |
|
to function) and `PROC` (procedure) are added to the ends. |
|
|
|
|
|
@subsubsection context_glext_string Checking for extensions |
|
|
|
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 |
|
is necessary to check whether the context supports the extension. This is done |
|
with @ref glfwExtensionSupported. |
|
|
|
@code |
|
if (glfwExtensionSupported("GL_ARB_debug_output")) |
|
{ |
|
// The extension is supported by the current context |
|
} |
|
@endcode |
|
|
|
The argument is a null terminated ASCII string with the extension name. If the |
|
extension is supported, @ref glfwExtensionSupported returns non-zero, otherwise |
|
it returns zero. |
|
|
|
|
|
@subsubsection context_glext_proc Fetching function pointers |
|
|
|
Many extensions, though not all, require the use of new OpenGL functions. |
|
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 |
|
retreive pointers to these functions with @ref glfwGetProcAddress. |
|
|
|
@code |
|
PFNGLGETDEBUGMESSAGELOGARB pfnGetDebugMessageLog = glfwGetProcAddress("glGetDebugMessageLogARB"); |
|
@endcode |
|
|
|
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. |
|
|
|
@code |
|
#include "glext.h" |
|
|
|
#define glGetDebugMessageLogARB pfnGetDebugMessageLog |
|
PFNGLGETDEBUGMESSAGELOGARB pfnGetDebugMessageLog; |
|
|
|
// Flag indicating whether the extension is supported |
|
int has_debug_output = 0; |
|
|
|
void load_extensions(void) |
|
{ |
|
if (glfwExtensionSupported("GL_ARB_debug_output")) |
|
{ |
|
pfnGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGARB) glfwGetProcAddress("glGetDebugMessageLogARB"); |
|
if (pfnGetDebugMessageLog) |
|
{ |
|
// Both the extension name and the function pointer are present |
|
has_debug_output = 1; |
|
} |
|
} |
|
} |
|
|
|
void some_function(void) |
|
{ |
|
// Now the extension function can be called as usual |
|
glGetDebugMessageLogARB(...); |
|
} |
|
@endcode |
|
|
|
*/
|
|
|