| /*! |
| |
| @page context Context 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. |
| |
| 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. |
| |
| - @ref intro |
| - @ref window |
| - @ref monitor |
| - @ref input |
| |
| |
| @section context_object Context objects |
| |
| @ref window_object encapsulate both the OS level window and a OpenGL or OpenGL |
| ES 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. See @ref window_creation for more information. |
| |
| |
| @subsection 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 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 |
| |
| 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. |
| |
| 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 |
| versions and APIs, but has at times been named _Shared Objects and Multiple |
| Contexts_. |
| |
| GLFW comes with a simple object sharing test program called `sharing`. |
| |
| |
| @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 can only be current for a single thread at a time, and a thread |
| can only have a single context current at a time. |
| |
| |
| @section context_swap Buffer swapping |
| |
| Buffer swapping is part of the window and framebuffer, not the context. See |
| @ref window_swap in the window 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 recommended that you use an existing extension loader library, as |
| described above, instead of loading manually. |
| |
| |
| @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 |
| |
| */ |