glfw/docs/context.dox

309 lines
10 KiB
Plaintext
Raw Normal View History

2013-04-11 20:18:46 +02:00
/*!
2014-09-18 15:03:29 +02:00
@page context Context guide
2013-05-27 17:10:34 +02:00
@tableofcontents
The primary purpose of GLFW is to provide a simple interface to window
management and OpenGL and OpenGL ES context creation. GLFW supports
2014-04-23 13:30:11 +02:00
multiple windows, with each window having its own context.
2013-05-27 17:10:34 +02:00
2014-09-18 15:03:29 +02:00
This guide introduces the functions related to managing OpenGL and OpenGL ES
contexts. There are also guides for the other areas of the GLFW API.
2013-05-27 17:10:34 +02:00
2014-09-18 15:03:29 +02:00
- @ref intro
- @ref window
- @ref monitor
- @ref input
2013-05-27 17:10:34 +02:00
2014-09-18 15:03:29 +02:00
@section context_object Context objects
2014-10-07 02:15:36 +02: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 17:10:34 +02:00
2014-10-07 02:15:36 +02:00
As the window and context are inseparably linked, the window object also serves
as the context handle.
2013-05-27 17:10:34 +02:00
2014-09-18 15:03:29 +02:00
@subsection context_hints Context creation hints
2013-05-27 17:10:34 +02:00
There are a number of hints, specified using @ref glfwWindowHint, related to
what kind of context is created. See
2014-09-18 15:03:29 +02:00
[context related hints](@ref window_hints_ctx) in the window guide.
@subsection context_sharing Context object sharing
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.
@code
GLFWwindow* second_window = glfwCreateWindow(640, 480, "Second Window", NULL, first_window);
@endcode
2013-05-27 17:10:34 +02:00
2014-09-18 15:03:29 +02: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 17:10:34 +02:00
2014-09-18 15:03:29 +02:00
See the relevant chapter of the [OpenGL](https://www.opengl.org/registry/) or
[OpenGL ES](http://www.khronos.org/opengles/) reference documents for more
information. The name and number of this chapter unfortunately varies between
2014-10-02 17:35:10 +02:00
versions and APIs, but has at times been named _Shared Objects and Multiple
Contexts_.
2013-12-05 03:15:35 +01:00
2014-09-18 15:03:29 +02:00
GLFW comes with a simple object sharing test program called `sharing`.
2013-12-05 03:15:35 +01:00
2014-10-07 02:15:36 +02:00
@subsection context_offscreen Offscreen contexts
GLFW doesn't support creating contexts without an associated window. However,
contexts with hidden windows can be created with the
[GLFW_VISIBLE](@ref window_hints_wnd) window hint.
@code
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
GLFWwindow* offscreen_context = glfwCreateWindow(640, 480, "", NULL, NULL);
@endcode
The window never needs to be shown and its context can be used as a plain
2014-10-13 16:00:11 +02: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 02:15:36 +02:00
__OS X:__ The first time a window is created the menu bar is populated with
2014-10-13 16:00:11 +02:00
common commands like Hide, Quit and About. This is not desirable for example
when writing a command-line only application. The menu bar setup can be
disabled with a [compile-time option](@ref compile_options_osx).
2014-10-07 02:15:36 +02:00
2013-05-27 17:10:34 +02:00
@section context_current Current context
2014-04-23 13:30:11 +02:00
Before you can make OpenGL or OpenGL ES calls, you need to have a current
2014-10-13 16:00:11 +02: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 17:10:34 +02:00
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
2014-10-13 16:00:11 +02:00
The following GLFW functions require a context to be current:
2014-04-23 13:30:11 +02:00
2014-10-13 16:00:11 +02:00
- @ref glfwSwapInterval
- @ref glfwExtensionSupported
- @ref glfwGetProcAddress
Calling any these functions without a current context will generate a @ref
GLFW_NO_CURRENT_CONTEXT error.
2013-05-27 17:10:34 +02:00
2014-09-18 15:03:29 +02:00
@section context_swap Buffer swapping
2013-05-27 17:10:34 +02:00
2014-04-23 13:30:11 +02:00
Buffer swapping is part of the window and framebuffer, not the context. See
2014-09-18 15:03:29 +02:00
@ref window_swap in the window guide.
2013-05-27 17:10:34 +02:00
2014-04-23 13:30:11 +02:00
@section context_glext OpenGL and OpenGL ES extensions
2013-04-11 20:18:46 +02:00
2014-04-23 13:30:11 +02:00
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.
2013-04-11 20:18:46 +02:00
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
2014-04-23 13:30:11 +02: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
[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
2015-01-05 16:46:04 +01:00
similarly.
2014-04-23 13:30:11 +02: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.
@code{.sh}
python main.py --no-loader --out-path output
@endcode
2014-10-13 16:00:11 +02:00
The `--no-loader` option is added because GLFW already provides a function for
loading OpenGL and OpenGL ES function pointers and glad can call this instead of
having to implement its own.
2014-04-23 13:30:11 +02: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
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
2013-04-11 20:18:46 +02:00
2013-05-27 17:10:34 +02:00
To use a certain extension, you must first check whether the context supports
2013-04-11 20:18:46 +02:00
that extension and then, if it introduces new functions, retrieve the pointers
2014-04-23 13:30:11 +02:00
to those functions. GLFW provides @ref glfwExtensionSupported and @ref
glfwGetProcAddress for manual loading of extensions and new API functions.
2013-04-11 20:18:46 +02:00
2014-09-18 15:03:29 +02:00
@note It is recommended that you use an existing extension loader library, as
described above, instead of loading manually.
2013-04-11 20:18:46 +02:00
2014-04-23 13:30:11 +02:00
@subsubsection context_glext_header The glext.h header
2013-04-11 20:18:46 +02:00
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
2014-04-23 13:30:11 +02:00
`glGetDebugMessageLogARB`), i.e. the name is made uppercase and `PFN` (pointer
to function) and `PROC` (procedure) are added to the ends.
2013-04-11 20:18:46 +02:00
2014-04-23 13:30:11 +02:00
@subsubsection context_glext_string Checking for extensions
2013-04-11 20:18:46 +02: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
2013-05-27 17:10:34 +02:00
is necessary to check whether the context supports the extension. This is done
2013-04-11 20:18:46 +02:00
with @ref glfwExtensionSupported.
@code
if (glfwExtensionSupported("GL_ARB_debug_output"))
{
2013-05-27 17:10:34 +02:00
// The extension is supported by the current context
2013-04-11 20:18:46 +02:00
}
@endcode
The argument is a null terminated ASCII string with the extension name. If the
2013-05-27 17:10:34 +02:00
extension is supported, @ref glfwExtensionSupported returns non-zero, otherwise
it returns zero.
2013-04-11 20:18:46 +02:00
2014-04-23 13:30:11 +02:00
@subsubsection context_glext_proc Fetching function pointers
2013-04-11 20:18:46 +02:00
Many extensions, though not all, require the use of new OpenGL functions.
2014-04-23 13:30:11 +02: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 16:46:04 +01:00
retrieve pointers to these functions with @ref glfwGetProcAddress.
2013-04-11 20:18:46 +02:00
@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;
2013-05-27 17:10:34 +02:00
// Flag indicating whether the extension is supported
2013-04-11 20:18:46 +02:00
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
*/