Compare commits

...

71 Commits

Author SHA1 Message Date
Doug Binks
b5c68787a7
Merge af6e36f250 into 8e15281d34 2025-09-01 18:40:23 +02:00
knokko
8e15281d34 Add glfwGetGLXFBConfig native access function
This adds the glfwGetGLXFBConfig function for querying the GLXFBConfig
the GLXWindow of a window.

This commit is a squashed and modified version of PR #1925 by knokko.
The following changes were made by elmindreda:

The function signature was changed to handle GLXFBConfig being an opaque
value in core GLX.  The function error checks were fixed and updated.
The struct member name was changed.  The struct member clearing on
context destruction was removed.  All documentation snippets were
updated.

Closes #1925
2025-09-01 16:05:26 +02:00
Camilla Löwy
621e99d53e Add glfwGetEGLConfig native access function
This adds the glfwGetEGLConfig function for querying the EGLConfig of
the EGLSurface of a window.

This is a re-implementation of the PR #2045 by knokko, slightly
redesigned to handle EGLConfig being an opaque type in core EGL.

Closes #2045
2025-09-01 16:05:24 +02:00
Camilla Löwy
1a0b7827d4 EGL: Fix error return value for glfwGetEGLSurface
This is a semantic fix only.  The behavior is unchanged.
2025-08-29 19:27:21 +02:00
Camilla Löwy
4c64184455 Remove title member from window config
The window title is already available in the window struct.
2025-08-29 19:27:21 +02:00
Camilla Löwy
bfcb98fb6c Replace some Doxygen aliases with Markdown 2025-08-29 19:27:21 +02:00
Camilla Löwy
f8582d26d0 Add Markdown files as sources to IDE docs target 2025-08-29 19:27:21 +02:00
Camilla Löwy
1fdd39cf3e Fix documentation target dependency
Related to #2704
2025-08-29 19:27:08 +02:00
Camilla Löwy
c9b129753a Update Doxygen version handling 2025-08-28 19:05:42 +02:00
Camilla Löwy
04a67c8267 Fix X11 clipboard compatibility description 2025-08-28 19:04:47 +02:00
Camilla Löwy
5c87937e44 Update README 2025-08-28 18:56:20 +02:00
Doug Binks
af6e36f250 Merge branch 'master' into multi-context-windows 2025-08-10 18:36:47 +02:00
Doug Binks
5c08ecbb5c Merge branch 'master' into multi-context-windows 2025-08-10 13:04:37 +02:00
Doug Binks
d35fdc21eb Merge branch 'master' into multi-context-windows 2025-07-05 19:22:48 +02:00
Doug Binks
32e0089b86 Merge branch 'master' into multi-context-windows 2025-07-05 19:22:07 +02:00
Doug Binks
e2f9340a8c Improved usercontext test with threading 2025-02-11 16:17:45 +00:00
Doug Binks
58aad6c136 Fix for not being able to clear the user context 2025-02-10 18:36:01 +00:00
Doug Binks
e4e46b4cc5 Merge branch 'multi-context-windows-merge-master' into multi-context-windows 2024-10-09 18:03:32 +02:00
Doug Binks
587025f9cb Merge branch 'master' into multi-context-windows-merge-master 2024-10-09 18:03:07 +02:00
Doug Binks
ca4485e12e Merge branch 'multi-context-windows-merge-master' into multi-context-windows 2024-03-07 16:05:47 +00:00
Doug Binks
ece28b0f19 Merge branch 'master' into multi-context-windows-merge-master 2024-03-07 15:21:24 +00:00
Doug Binks
df70d8e9bf Merge branch 'multi-context-windows-merge-master' into multi-context-windows 2024-01-25 18:10:38 +00:00
Doug Binks
6148990427 Merge branch 'master' into multi-context-windows-merge-master 2024-01-25 17:44:13 +00:00
Doug Binks
64694f17ab Merge branch 'multi-context-windows-merge-master' into multi-context-windows 2022-12-20 18:01:02 +00:00
Doug Binks
bbe6c4cfa1 Merge branch 'master' into multi-context-windows-merge-master 2022-12-20 18:00:47 +00:00
Doug Binks
c01d16a9ee Merge branch 'multi-context-windows-merge-master' into multi-context-windows 2022-06-26 17:20:39 +02:00
Doug Binks
f40442fa59 Merge branch 'master' into multi-context-windows-merge-master 2022-06-26 17:17:14 +02:00
Doug Binks
f2a9ea7b7e Merge branch 'multi-context-windows-merge-master' into multi-context-windows 2022-06-09 17:49:19 +01:00
Doug Binks
48c0cea73f Merge branch 'master' into multi-context-windows-merge-master 2022-06-09 17:49:06 +01:00
Doug Binks
7de1c5c10a Minor formating fix 2022-06-09 13:55:33 +01:00
Doug Binks
fc32eb48c5 Merge branch 'master' 2022-06-06 12:55:45 +01:00
Doug Binks
41bb2515ef Merge branch 'master' into multi-context-windows-merge-master 2022-04-05 20:17:23 +01:00
Doug Binks
dcf9a51b78 UserContext: fixed wayland platform 2022-03-31 19:53:09 +01:00
Doug Binks
23d31b805a UserContext: fixed x11 platform 2022-03-31 19:29:44 +01:00
Doug Binks
3b003dd5f0 UserContext: error return for CreateUserContext should be NULL 2022-03-31 19:21:42 +01:00
Doug Binks
9dfa1649ff UserContext: Null platform fixes 2022-03-31 16:59:01 +01:00
Doug Binks
c97e3a657b Merge branch 'master' into multi-context-windows-merge-master 2022-03-31 16:49:50 +01:00
Doug Binks
b88a8c9364 Fixed usercontext glad use after merge 2021-09-04 12:41:39 +01:00
Camilla Löwy
7a55ca34b9
Merge branch 'master' into multi-context-windows 2021-09-02 19:31:33 +02:00
Doug Binks
b0d196c43c Formatting consistency fixes 2021-03-23 18:45:29 +00:00
Doug Binks
7b6f25c360 Removed more trailing white space 2021-03-23 16:11:07 +00:00
Doug Binks
c01aa3fec4 Removed trailing white space 2021-03-23 15:56:56 +00:00
Doug Binks
1ba83ede44 User contexts: added context documentation and updated references 2021-03-23 14:40:54 +00:00
Doug Binks
7874992888 User contexts: added news entry 2021-03-23 13:09:17 +00:00
Doug Binks
350aebf20a User contexts: added change log entry in README.md, listing all new symbols 2021-03-23 12:53:17 +00:00
Doug Binks
e91b1820dd Modified clear colour of usercontext test to remove transparency 2021-03-23 12:37:54 +00:00
Doug Binks
ab4b4e95f6 Merge branch 'master' into merge 2021-03-22 15:33:40 +00:00
Doug Binks
e2016291f1 Merge branch 'master' into multi-context-windows 2020-09-04 17:44:36 +01:00
Doug Binks
375fcdeadb Added GLFW_NO_API check to glfwCreateUserContext and error documentation. 2020-07-16 15:20:25 +01:00
Doug Binks
1d647668af EGL user context code simplification 2020-07-16 14:02:32 +01:00
Doug Binks
cd68bac78d Initial user context documentation 2020-07-16 11:59:23 +01:00
Doug Binks
1cb8ab8dc6 Make user context non current when destroyed 2020-07-16 11:59:11 +01:00
Doug Binks
87ddca831a Removed unused EGL defines. 2020-07-15 19:49:35 +01:00
Doug Binks
2f2e7f041a Simplified fallback pbuffer surface path. 2020-07-15 19:40:00 +01:00
Doug Binks
e55a552eee User context EGL fixes. 2020-07-15 14:31:05 +01:00
Doug Binks
5f52f2a7f8 Fix for ELG wrong surface passed 2020-07-15 13:23:38 +01:00
Doug Binks
3de9ed6453 Fixed EGL glfwMakeUserContextCurrent - requires different surface 2020-07-15 13:21:02 +01:00
Doug Binks
d01ad1a78d Improved usercontext.c test 2020-07-15 13:19:47 +01:00
Doug Binks
f2806aa9ab Added glfwGetCurrentUserContext 2020-07-15 13:19:33 +01:00
Doug Binks
6539d101f3 Added TLS for current user context and simplified code 2020-07-15 13:19:14 +01:00
Doug Binks
a1a1b77150 Added _GLFW_REQUIRE* to user context functions. 2020-07-15 11:19:18 +01:00
Doug Binks
4caca8b20c glfwMakeUserContextCurrent now calls glfwMakeContextCurrent(NULL) to ensure TLS set. 2020-07-15 11:18:58 +01:00
Doug Binks
f2b86a25b3 Cocoa and NSGL Implementation 2020-07-14 19:10:31 +01:00
Doug Binks
dd854e47ba Formatting 2020-07-14 12:38:18 +01:00
Doug Binks
931ba89aad User context null platform and OSMESA implementation. 2020-07-14 11:41:42 +01:00
Doug Binks
51f11929f3 User context Wayland and EGL implementations 2020-07-13 19:05:36 +01:00
Doug Binks
5e94092263 Refactor user context implementation to use the standard GLFW platform / context approach 2020-07-13 18:06:48 +01:00
Doug Binks
3a0a3c540c Merge branch 'master' into multi-context-windows 2020-07-13 11:04:23 +01:00
Doug Binks
998036654c GLX user context implementation 2020-07-13 10:50:06 +01:00
Doug Binks
0ae4eb4d26 Improved User Context Win32 implementation
_glfwCreateContextWGL and _glfwPlatformCreateUserContext now use  new function _glfwCreateContextForDCWGL.
2020-07-12 12:21:18 +01:00
Doug Binks
a08bfd9891 User Contexts API with Win32 implementation. 2020-06-03 19:46:22 +01:00
40 changed files with 1417 additions and 275 deletions

View File

@ -23,6 +23,7 @@ video tutorials.
- Denis Bernard - Denis Bernard
- BiBi - BiBi
- Doug Binks - Doug Binks
- bitb4ker
- blanco - blanco
- Waris Boonyasiriwat - Waris Boonyasiriwat
- Kyle Brenneman - Kyle Brenneman
@ -123,6 +124,7 @@ video tutorials.
- Josh Kilmer - Josh Kilmer
- Byunghoon Kim - Byunghoon Kim
- Cameron King - Cameron King
- knokko
- Peter Knut - Peter Knut
- Christoph Kubisch - Christoph Kubisch
- Yuri Kunde Schlesner - Yuri Kunde Schlesner

135
README.md
View File

@ -9,34 +9,28 @@ GLFW is an Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan
application development. It provides a simple, platform-independent API for application development. It provides a simple, platform-independent API for
creating windows, contexts and surfaces, reading input, handling events, etc. creating windows, contexts and surfaces, reading input, handling events, etc.
GLFW natively supports Windows, macOS and Linux and other Unix-like systems. On GLFW is written primarily in C99, with parts of macOS support being written in
Linux both Wayland and X11 are supported. Objective-C.
GLFW supports Windows, macOS and Linux, and also works on many other Unix-like
systems. On Linux both Wayland and X11 are supported.
GLFW is licensed under the [zlib/libpng GLFW is licensed under the [zlib/libpng
license](https://www.glfw.org/license.html). license](https://www.glfw.org/license.html).
You can [download](https://www.glfw.org/download.html) the latest stable release You can [download](https://www.glfw.org/download.html) the latest stable release
as source or Windows binaries. Each release starting with 3.0 also has as source or Windows and macOS binaries. There are [release
a corresponding [annotated tag](https://github.com/glfw/glfw/releases) with tags](https://github.com/glfw/glfw/releases) with source and binary archives
source and binary archives. attached for every version since 3.0.
The [documentation](https://www.glfw.org/docs/latest/) is available online and is The [documentation](https://www.glfw.org/docs/latest/) is available online and is
included in all source and binary archives. See the [release also included in source and binary archives, except those generated
notes](https://www.glfw.org/docs/latest/news.html) for new features, caveats and automatically by Github. The documentation contains guides, a tutorial and the
deprecations in the latest release. For more details see the [version API reference. The [release
history](https://www.glfw.org/changelog.html). notes](https://www.glfw.org/docs/latest/news.html) list the new features,
caveats and deprecations in the latest release. The [version
The `master` branch is the stable integration branch and _should_ always compile history](https://www.glfw.org/changelog.html) lists every user-visible change
and run on all supported platforms, although details of newly added features may for every release.
change until they have been included in a release. New features and many bug
fixes live in [other branches](https://github.com/glfw/glfw/branches/all) until
they are stable enough to merge.
If you are new to GLFW, you may find the
[tutorial](https://www.glfw.org/docs/latest/quick.html) for GLFW 3 useful. If
you have used GLFW 2 in the past, there is a [transition
guide](https://www.glfw.org/docs/latest/moving.html) for moving to the GLFW
3 API.
GLFW exists because of the contributions of [many people](CONTRIBUTORS.md) GLFW exists because of the contributions of [many people](CONTRIBUTORS.md)
around the world, whether by reporting bugs, providing community support, adding around the world, whether by reporting bugs, providing community support, adding
@ -44,57 +38,37 @@ features, reviewing or testing code, debugging, proofreading docs, suggesting
features or fixing bugs. features or fixing bugs.
## Compiling GLFW
GLFW is written primarily in C99, with parts of macOS support being written in
Objective-C. GLFW itself requires only the headers and libraries for your OS
and window system. It does not need any additional headers for context creation
APIs (WGL, GLX, EGL, NSGL, OSMesa) or rendering APIs (OpenGL, OpenGL ES, Vulkan)
to enable support for them.
GLFW supports compilation on Windows with Visual C++ (2013 and later) and
MinGW-w64, on macOS with Clang and on Linux and other Unix-like systems with GCC
and Clang. It will likely compile in other environments as well, but this is
not regularly tested.
There are [pre-compiled binaries](https://www.glfw.org/download.html) available
for all supported compilers on Windows and macOS.
See the [compilation guide](https://www.glfw.org/docs/latest/compile.html) for
more information about how to compile GLFW yourself.
## Using GLFW
See the [documentation](https://www.glfw.org/docs/latest/) for tutorials, guides
and the API reference.
## Contributing to GLFW
See the [contribution
guide](https://github.com/glfw/glfw/blob/master/docs/CONTRIBUTING.md) for
more information.
## System requirements ## System requirements
GLFW supports Windows 7 and later and macOS 10.11 and later. Linux and other GLFW supports Windows 7 and later and macOS 10.11 and later. On GNOME Wayland,
Unix-like systems running the X Window System are supported even without window decorations will be very basic unless the
a desktop environment or modern extensions, although some features require [libdecor](https://gitlab.freedesktop.org/libdecor/libdecor) package is
a running window or clipboard manager. The OSMesa backend requires Mesa 6.3. installed. Linux and other Unix-like systems running X11 are supported even
without a desktop environment or modern extensions, although some features
require a clipboard manager or a modern window manager.
See the [compatibility guide](https://www.glfw.org/docs/latest/compat.html) See the [compatibility guide](https://www.glfw.org/docs/latest/compat.html)
in the documentation for more information. for more detailed information.
## Dependencies ## Compiling GLFW
GLFW itself needs only CMake 3.16 or later and the headers and libraries for your GLFW supports compilation with Visual C++ (2013 and later), GCC and Clang. Both
OS and window system. Clang-CL and MinGW-w64 are supported. Other C99 compilers will likely also
work, but this is not regularly tested.
There are [pre-compiled binaries](https://www.glfw.org/download.html)
available for Windows and macOS.
GLFW itself needs only CMake and the headers and libraries for your operating
system and window system. No other SDKs are required.
See the [compilation guide](https://www.glfw.org/docs/latest/compile.html) for
more information about compiling GLFW and the exact dependencies required for
each window system.
The examples and test programs depend on a number of tiny libraries. These are The examples and test programs depend on a number of tiny libraries. These are
located in the `deps/` directory. bundled in the `deps/` directory. The repository has no submodules.
- [getopt\_port](https://github.com/kimgr/getopt_port/) for examples - [getopt\_port](https://github.com/kimgr/getopt_port/) for examples
with command-line options with command-line options
@ -107,8 +81,33 @@ located in the `deps/` directory.
- [Nuklear](https://github.com/Immediate-Mode-UI/Nuklear) for test and example UI - [Nuklear](https://github.com/Immediate-Mode-UI/Nuklear) for test and example UI
- [stb\_image\_write](https://github.com/nothings/stb) for writing images to disk - [stb\_image\_write](https://github.com/nothings/stb) for writing images to disk
The documentation is generated with [Doxygen](https://doxygen.org/) if CMake can The documentation is generated with [Doxygen](https://doxygen.org/) when the
find that tool. library is built, provided CMake could find a sufficiently new version of it
during configuration.
## Using GLFW
See the [HTML documentation](https://www.glfw.org/docs/latest/) for a tutorial,
guides and the API reference.
## Contributing to GLFW
See the [contribution
guide](https://github.com/glfw/glfw/blob/master/docs/CONTRIBUTING.md) for
more information.
The `master` branch is the stable integration branch and _should_ always compile
and run on all supported platforms. Details of a newly added feature,
including the public API, may change until it has been included in a release.
The `latest` branch is equivalent to the [highest numbered](https://semver.org/)
release, although it may not always point to the same commit as the tag for that
release.
The `ci` branch is used to trigger continuous integration jobs for code under
testing and should never be relied on for any purpose.
## Reporting bugs ## Reporting bugs
@ -121,8 +120,13 @@ information on what to include when reporting a bug.
## Changelog since 3.4 ## Changelog since 3.4
- Added OpenGL and OpenGL ES user contexts for multiple window contexts via
`GLFWusercontext`, `glfwCreateUserContext`, `glfwDestroyUserContext`,
`glfwMakeUserContextCurrent`, `glfwGetCurrentUserContext` (#1687,#1870)
- Added `GLFW_UNLIMITED_MOUSE_BUTTONS` input mode that allows mouse buttons beyond - Added `GLFW_UNLIMITED_MOUSE_BUTTONS` input mode that allows mouse buttons beyond
the limit of the mouse button tokens to be reported (#2423) the limit of the mouse button tokens to be reported (#2423)
- Added `glfwGetEGLConfig` function to query the `EGLConfig` of a window (#2045)
- Added `glfwGetGLXFBConfig` function to query the `GLXFBConfig` of a window (#1925)
- Updated minimum CMake version to 3.16 (#2541) - Updated minimum CMake version to 3.16 (#2541)
- Removed support for building with original MinGW (#2540) - Removed support for building with original MinGW (#2540)
- [Win32] Removed support for Windows XP and Vista (#2505) - [Win32] Removed support for Windows XP and Vista (#2505)
@ -149,7 +153,6 @@ information on what to include when reporting a bug.
- [EGL] Allowed native access on Wayland with `GLFW_CONTEXT_CREATION_API` set to - [EGL] Allowed native access on Wayland with `GLFW_CONTEXT_CREATION_API` set to
`GLFW_NATIVE_CONTEXT_API` (#2518) `GLFW_NATIVE_CONTEXT_API` (#2518)
## Contact ## Contact
On [glfw.org](https://www.glfw.org/) you can find the latest version of GLFW, as On [glfw.org](https://www.glfw.org/) you can find the latest version of GLFW, as

View File

@ -1,4 +1,8 @@
# Because of bugs and limitations in its Markdown support, only fairly recent
# versions of Doxygen can produce acceptable output
set(MINIMUM_DOXYGEN_VERSION 1.9.8)
# NOTE: The order of this list determines the order of items in the Guides # NOTE: The order of this list determines the order of items in the Guides
# (i.e. Pages) list in the generated documentation # (i.e. Pages) list in the generated documentation
set(source_files set(source_files
@ -32,10 +36,10 @@ foreach(file IN LISTS source_files)
endforeach() endforeach()
set(DOXYGEN_SKIP_DOT TRUE) set(DOXYGEN_SKIP_DOT TRUE)
find_package(Doxygen) find_package(Doxygen ${MINIMUM_DOXYGEN_VERSION} QUIET)
if (NOT DOXYGEN_FOUND OR DOXYGEN_VERSION VERSION_LESS "1.9.8") if (NOT DOXYGEN_FOUND)
message(STATUS "Documentation generation requires Doxygen 1.9.8 or later") message(STATUS "Documentation generation requires Doxygen ${MINIMUM_DOXYGEN_VERSION} or later")
else() else()
configure_file(Doxyfile.in Doxyfile @ONLY) configure_file(Doxyfile.in Doxyfile @ONLY)
add_custom_command(OUTPUT "html/index.html" add_custom_command(OUTPUT "html/index.html"
@ -46,7 +50,7 @@ else()
COMMENT "Generating HTML documentation" COMMENT "Generating HTML documentation"
VERBATIM) VERBATIM)
add_custom_target(docs ALL SOURCES "html/index.html") add_custom_target(docs ALL SOURCES ${source_files} DEPENDS "html/index.html")
set_target_properties(docs PROPERTIES FOLDER "GLFW3") set_target_properties(docs PROPERTIES FOLDER "GLFW3")
if (GLFW_INSTALL) if (GLFW_INSTALL)

View File

@ -278,13 +278,7 @@ ALIASES = "thread_safety=@par Thread safety^^" \
"analysis=@par Analysis^^" \ "analysis=@par Analysis^^" \
"reentrancy=@par Reentrancy^^" \ "reentrancy=@par Reentrancy^^" \
"errors=@par Errors^^" \ "errors=@par Errors^^" \
"callback_signature=@par Callback signature^^" \ "callback_signature=@par Callback signature^^"
"glfw3=__GLFW 3:__" \
"x11=__X11:__" \
"wayland=__Wayland:__" \
"win32=__Windows:__" \
"macos=__macOS:__" \
"linux=__Linux:__"
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For # only. Doxygen will then generate output that is more tailored for C. For

View File

@ -50,10 +50,11 @@ compositing window manager to un-redirect full screen GLFW windows. If the
running window manager uses compositing but does not support this property then running window manager uses compositing but does not support this property then
additional copying may be performed for each buffer swap of full screen windows. additional copying may be performed for each buffer swap of full screen windows.
GLFW uses the [clipboard manager protocol][ClipboardManager] to push a clipboard GLFW uses the [clipboard manager protocol][ClipboardManager] to keep the
string (i.e. selection) owned by a GLFW window about to be destroyed to the clipboard string availble for the user after the libary has been terminated. If
clipboard manager. If there is no running clipboard manager, the clipboard there is no running clipboard manager and the clipboard contents has been set
string will be unavailable once the window has been destroyed. with @ref glfwSetClipboardString, the clipboard will be emptied when the library
is terminated.
[clipboardManager]: https://www.freedesktop.org/wiki/ClipboardManager/ [clipboardManager]: https://www.freedesktop.org/wiki/ClipboardManager/

View File

@ -91,6 +91,28 @@ You can disable context creation by setting the
Windows without contexts should not be passed to @ref glfwMakeContextCurrent or Windows without contexts should not be passed to @ref glfwMakeContextCurrent or
@ref glfwSwapBuffers. Doing this generates a @ref GLFW_NO_WINDOW_CONTEXT error. @ref glfwSwapBuffers. Doing this generates a @ref GLFW_NO_WINDOW_CONTEXT error.
@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`.
## Current context {#context_current} ## Current context {#context_current}
@ -121,6 +143,26 @@ error.
- @ref glfwExtensionSupported - @ref glfwExtensionSupported
- @ref glfwGetProcAddress - @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.
## Buffer swapping {#context_swap} ## Buffer swapping {#context_swap}

View File

@ -63,7 +63,7 @@ before the application exits. Modern systems are very good at freeing resources
allocated by programs that exit, but GLFW sometimes has to change global system allocated by programs that exit, but GLFW sometimes has to change global system
settings and these might not be restored without termination. settings and these might not be restored without termination.
@macos When the library is initialized the main menu and dock icon are created. __macOS:__ When the library is initialized the main menu and dock icon are created.
These are not desirable for a command-line only program. The creation of the These are not desirable for a command-line only program. The creation of the
main menu and dock icon can be disabled with the @ref GLFW_COCOA_MENUBAR init main menu and dock icon can be disabled with the @ref GLFW_COCOA_MENUBAR init
hint. hint.

View File

@ -255,7 +255,7 @@ hardware gamma correction, which today is typically an approximation of sRGB
gamma. This means that setting a perfectly linear ramp, or gamma 1.0, will gamma. This means that setting a perfectly linear ramp, or gamma 1.0, will
produce the default (usually sRGB-like) behavior. produce the default (usually sRGB-like) behavior.
@note @wayland An application cannot read or modify the monitor gamma ramp. The @note __Wayland:__ An application cannot read or modify the monitor gamma ramp.
@ref glfwGetGammaRamp, @ref glfwSetGammaRamp and @ref glfwSetGamma functions The @ref glfwGetGammaRamp, @ref glfwSetGammaRamp and @ref glfwSetGamma functions
emit @ref GLFW_FEATURE_UNAVAILABLE. emit @ref GLFW_FEATURE_UNAVAILABLE.

View File

@ -5,6 +5,15 @@
## New features {#features} ## New features {#features}
### Multiple window contexts {#multiple_window_contexts}
GLFW now provides the ability to create multiple OpenGL and OpenGL ES
contexts for a given window. Called user contexts, a [GLFWusercontext](@ref context_user)
can be created using @ref glfwCreateUserContext,
destroyed using @ref glfwDestroyUserContext, and managed with
@ref glfwMakeUserContextCurrent and @ref glfwGetCurrentUserContext.
For more information see the [user context](@ref context_user) documentation.
### Unlimited mouse buttons {#unlimited_mouse_buttons} ### Unlimited mouse buttons {#unlimited_mouse_buttons}
GLFW now has an input mode which allows an unlimited number of mouse buttons to GLFW now has an input mode which allows an unlimited number of mouse buttons to
@ -14,6 +23,19 @@ values over 8. For compatibility with older versions, the
@ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode needs to be set to make use of @ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode needs to be set to make use of
this. this.
### EGLConfig native access function {#eglconfig}
GLFW now provides the @ref glfwGetEGLConfig native access function for querying
the `EGLConfig` of a window that has a `EGLSurface`.
### GLXFBConfig native access function {#glxfbconfig}
GLFW now provides the @ref glfwGetGLXFBConfig native access function for
querying the `GLXFBConfig` of a window that has a `GLXWindow`.
## Caveats {#caveats} ## Caveats {#caveats}
## Deprecations {#deprecations} ## Deprecations {#deprecations}
@ -39,6 +61,10 @@ actively maintained and available on many platforms.
### New functions {#new_functions} ### New functions {#new_functions}
- @ref glfwGetEGLConfig
- @ref glfwGetGLXFBConfig
### New types {#new_types} ### New types {#new_types}
### New constants {#new_constants} ### New constants {#new_constants}

View File

@ -35,7 +35,7 @@ By default, GLFW will load the Vulkan loader dynamically at runtime via its stan
`vulkan-1.dll` on Windows, `libvulkan.so.1` on Linux and other Unix-like systems and `vulkan-1.dll` on Windows, `libvulkan.so.1` on Linux and other Unix-like systems and
`libvulkan.1.dylib` on macOS. `libvulkan.1.dylib` on macOS.
@macos GLFW will also look up and search the `Frameworks` subdirectory of your __macOS:__ GLFW will also look up and search the `Frameworks` subdirectory of your
application bundle. application bundle.
If your code is using a Vulkan loader with a different name or in a non-standard location If your code is using a Vulkan loader with a different name or in a non-standard location
@ -47,7 +47,7 @@ entry point retrieval. This prevents GLFW from dynamically loading the Vulkan l
glfwInitVulkanLoader(vkGetInstanceProcAddr); glfwInitVulkanLoader(vkGetInstanceProcAddr);
``` ```
@macos To make your application be redistributable you will need to set up the application __macOS:__ To make your application be redistributable you will need to set up the application
bundle according to the LunarG SDK documentation. This is explained in more detail in the bundle according to the LunarG SDK documentation. This is explained in more detail in the
[SDK documentation for macOS](https://vulkan.lunarg.com/doc/sdk/latest/mac/getting_started.html). [SDK documentation for macOS](https://vulkan.lunarg.com/doc/sdk/latest/mac/getting_started.html).
@ -186,7 +186,7 @@ check whether any extensions you wish to enable are already in the returned
array, as it is an error to specify an extension more than once in the array, as it is an error to specify an extension more than once in the
`VkInstanceCreateInfo` struct. `VkInstanceCreateInfo` struct.
@macos MoltenVK is (as of July 2022) not yet a fully conformant implementation __macOS:__ MoltenVK is (as of July 2022) not yet a fully conformant implementation
of Vulkan. As of Vulkan SDK 1.3.216.0, this means you must also enable the of Vulkan. As of Vulkan SDK 1.3.216.0, this means you must also enable the
`VK_KHR_portability_enumeration` instance extension and set the `VK_KHR_portability_enumeration` instance extension and set the
`VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR` bit in the instance creation `VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR` bit in the instance creation

View File

@ -363,10 +363,10 @@ which API was used to create the current context may fail if you change this
hint. This can be resolved by having it load functions via @ref hint. This can be resolved by having it load functions via @ref
glfwGetProcAddress. glfwGetProcAddress.
@note @wayland The EGL API _is_ the native context creation API, so this hint @note __Wayland:__ The EGL API _is_ the native context creation API, so this hint
will have no effect. will have no effect.
@note @x11 On some Linux systems, creating contexts via both the native and EGL @note __X11:__ On some Linux systems, creating contexts via both the native and EGL
APIs in a single process will cause the application to segfault. Stick to one APIs in a single process will cause the application to segfault. Stick to one
API or the other on Linux for now. API or the other on Linux for now.
@ -400,7 +400,7 @@ requested. Additionally, OpenGL ES 1.x cannot be returned if 2.0 or later was
requested, and vice versa. This is because OpenGL ES 3.x is backward compatible requested, and vice versa. This is because OpenGL ES 3.x is backward compatible
with 2.0, but OpenGL ES 2.0 is not backward compatible with 1.x. with 2.0, but OpenGL ES 2.0 is not backward compatible with 1.x.
@note @macos The OS only supports core profile contexts for OpenGL versions 3.2 @note __macOS:__ The OS only supports core profile contexts for OpenGL versions 3.2
and later. Before creating an OpenGL context of version 3.2 or later you must and later. Before creating an OpenGL context of version 3.2 or later you must
set the [GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint) hint accordingly. set the [GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint) hint accordingly.
OpenGL 3.0 and 3.1 contexts are not supported at all on macOS. OpenGL 3.0 and 3.1 contexts are not supported at all on macOS.
@ -893,7 +893,7 @@ int xpos, ypos;
glfwGetWindowPos(window, &xpos, &ypos); glfwGetWindowPos(window, &xpos, &ypos);
``` ```
@note @wayland An applications cannot know the positions of its windows or @note __Wayland:__ An applications cannot know the positions of its windows or
whether one has been moved. The @ref GLFW_POSITION_X and @ref GLFW_POSITION_Y whether one has been moved. The @ref GLFW_POSITION_X and @ref GLFW_POSITION_Y
window hints are ignored. The @ref glfwGetWindowPos and @ref glfwSetWindowPos window hints are ignored. The @ref glfwGetWindowPos and @ref glfwSetWindowPos
functions emit @ref GLFW_FEATURE_UNAVAILABLE. The window position callback will functions emit @ref GLFW_FEATURE_UNAVAILABLE. The window position callback will
@ -1044,7 +1044,7 @@ You can also get the current iconification state with @ref glfwGetWindowAttrib.
int iconified = glfwGetWindowAttrib(window, GLFW_ICONIFIED); int iconified = glfwGetWindowAttrib(window, GLFW_ICONIFIED);
``` ```
@note @wayland An application cannot know if any of its windows have been @note __Wayland:__ An application cannot know if any of its windows have been
iconified or restore one from iconification. The @ref glfwRestoreWindow iconified or restore one from iconification. The @ref glfwRestoreWindow
function can only restore windows from maximization and the iconify callback function can only restore windows from maximization and the iconify callback
will not be called. The [GLFW_ICONIFIED](@ref GLFW_ICONIFIED_attrib) attribute will not be called. The [GLFW_ICONIFIED](@ref GLFW_ICONIFIED_attrib) attribute

View File

@ -1228,13 +1228,13 @@ extern "C" {
* The top-left to bottom-right diagonal resize/move shape. This is usually * The top-left to bottom-right diagonal resize/move shape. This is usually
* a diagonal double-headed arrow. * a diagonal double-headed arrow.
* *
* @note @macos This shape is provided by a private system API and may fail * @note __macOS:__ This shape is provided by a private system API and may fail
* with @ref GLFW_CURSOR_UNAVAILABLE in the future. * with @ref GLFW_CURSOR_UNAVAILABLE in the future.
* *
* @note @wayland This shape is provided by a newer standard not supported by * @note __Wayland:__ This shape is provided by a newer standard not supported by
* all cursor themes. * all cursor themes.
* *
* @note @x11 This shape is provided by a newer standard not supported by all * @note __X11:__ This shape is provided by a newer standard not supported by all
* cursor themes. * cursor themes.
*/ */
#define GLFW_RESIZE_NWSE_CURSOR 0x00036007 #define GLFW_RESIZE_NWSE_CURSOR 0x00036007
@ -1243,13 +1243,13 @@ extern "C" {
* The top-right to bottom-left diagonal resize/move shape. This is usually * The top-right to bottom-left diagonal resize/move shape. This is usually
* a diagonal double-headed arrow. * a diagonal double-headed arrow.
* *
* @note @macos This shape is provided by a private system API and may fail * @note __macOS:__ This shape is provided by a private system API and may fail
* with @ref GLFW_CURSOR_UNAVAILABLE in the future. * with @ref GLFW_CURSOR_UNAVAILABLE in the future.
* *
* @note @wayland This shape is provided by a newer standard not supported by * @note __Wayland:__ This shape is provided by a newer standard not supported by
* all cursor themes. * all cursor themes.
* *
* @note @x11 This shape is provided by a newer standard not supported by all * @note __X11:__ This shape is provided by a newer standard not supported by all
* cursor themes. * cursor themes.
*/ */
#define GLFW_RESIZE_NESW_CURSOR 0x00036008 #define GLFW_RESIZE_NESW_CURSOR 0x00036008
@ -1264,10 +1264,10 @@ extern "C" {
* The operation-not-allowed shape. This is usually a circle with a diagonal * The operation-not-allowed shape. This is usually a circle with a diagonal
* line through it. * line through it.
* *
* @note @wayland This shape is provided by a newer standard not supported by * @note __Wayland:__ This shape is provided by a newer standard not supported by
* all cursor themes. * all cursor themes.
* *
* @note @x11 This shape is provided by a newer standard not supported by all * @note __X11:__ This shape is provided by a newer standard not supported by all
* cursor themes. * cursor themes.
*/ */
#define GLFW_NOT_ALLOWED_CURSOR 0x0003600A #define GLFW_NOT_ALLOWED_CURSOR 0x0003600A
@ -1403,6 +1403,18 @@ typedef struct GLFWmonitor GLFWmonitor;
*/ */
typedef struct GLFWwindow GLFWwindow; typedef struct GLFWwindow GLFWwindow;
/*! @brief Opaque user OpenGL & OpenGL ES context object.
*
* Opaque user OpenGL OpenGL ES context object.
*
* @see @ref context_user
*
* @since Added in version 3.4.
*
* @ingroup window
*/
typedef struct GLFWusercontext GLFWusercontext;
/*! @brief Opaque cursor object. /*! @brief Opaque cursor object.
* *
* Opaque cursor object. * Opaque cursor object.
@ -1629,7 +1641,7 @@ typedef void (* GLFWwindowposfun)(GLFWwindow* window, int xpos, int ypos);
* @sa @ref glfwSetWindowSizeCallback * @sa @ref glfwSetWindowSizeCallback
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -1649,7 +1661,7 @@ typedef void (* GLFWwindowsizefun)(GLFWwindow* window, int width, int height);
* @sa @ref glfwSetWindowCloseCallback * @sa @ref glfwSetWindowCloseCallback
* *
* @since Added in version 2.5. * @since Added in version 2.5.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -1669,7 +1681,7 @@ typedef void (* GLFWwindowclosefun)(GLFWwindow* window);
* @sa @ref glfwSetWindowRefreshCallback * @sa @ref glfwSetWindowRefreshCallback
* *
* @since Added in version 2.5. * @since Added in version 2.5.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -1800,7 +1812,7 @@ typedef void (* GLFWwindowcontentscalefun)(GLFWwindow* window, float xscale, flo
* @sa @ref glfwSetMouseButtonCallback * @sa @ref glfwSetMouseButtonCallback
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle and modifier mask parameters. * __GLFW 3:__ Added window handle and modifier mask parameters.
* *
* @ingroup input * @ingroup input
*/ */
@ -1891,7 +1903,7 @@ typedef void (* GLFWscrollfun)(GLFWwindow* window, double xoffset, double yoffse
* @sa @ref glfwSetKeyCallback * @sa @ref glfwSetKeyCallback
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle, scancode and modifier mask parameters. * __GLFW 3:__ Added window handle, scancode and modifier mask parameters.
* *
* @ingroup input * @ingroup input
*/ */
@ -1912,7 +1924,7 @@ typedef void (* GLFWkeyfun)(GLFWwindow* window, int key, int scancode, int actio
* @sa @ref glfwSetCharCallback * @sa @ref glfwSetCharCallback
* *
* @since Added in version 2.4. * @since Added in version 2.4.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup input * @ingroup input
*/ */
@ -2020,7 +2032,7 @@ typedef void (* GLFWjoystickfun)(int jid, int event);
* @sa @ref glfwGetVideoModes * @sa @ref glfwGetVideoModes
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added refresh rate member. * __GLFW 3:__ Added refresh rate member.
* *
* @ingroup monitor * @ingroup monitor
*/ */
@ -2083,7 +2095,7 @@ typedef struct GLFWgammaramp
* @sa @ref window_icon * @sa @ref window_icon
* *
* @since Added in version 2.1. * @since Added in version 2.1.
* @glfw3 Removed format and bytes-per-pixel members. * __GLFW 3:__ Removed format and bytes-per-pixel members.
* *
* @ingroup window * @ingroup window
*/ */
@ -2183,12 +2195,12 @@ typedef struct GLFWallocator
* @errors Possible errors include @ref GLFW_PLATFORM_UNAVAILABLE and @ref * @errors Possible errors include @ref GLFW_PLATFORM_UNAVAILABLE and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @macos This function will change the current directory of the * @remark __macOS:__ This function will change the current directory of the
* application to the `Contents/Resources` subdirectory of the application's * application to the `Contents/Resources` subdirectory of the application's
* bundle, if present. This can be disabled with the @ref * bundle, if present. This can be disabled with the @ref
* GLFW_COCOA_CHDIR_RESOURCES init hint. * GLFW_COCOA_CHDIR_RESOURCES init hint.
* *
* @remark @macos This function will create the main menu and dock icon for the * @remark __macOS:__ This function will create the main menu and dock icon for the
* application. If GLFW finds a `MainMenu.nib` it is loaded and assumed to * application. If GLFW finds a `MainMenu.nib` it is loaded and assumed to
* contain a menu bar. Otherwise a minimal menu bar is created manually with * contain a menu bar. Otherwise a minimal menu bar is created manually with
* common commands like Hide, Quit and About. The About entry opens a minimal * common commands like Hide, Quit and About. The About entry opens a minimal
@ -2203,7 +2215,7 @@ typedef struct GLFWallocator
* to something other than `wayland` or `x11`, the regular detection mechanism * to something other than `wayland` or `x11`, the regular detection mechanism
* will be used instead. * will be used instead.
* *
* @remark @x11 This function will set the `LC_CTYPE` category of the * @remark __X11:__ This function will set the `LC_CTYPE` category of the
* application locale according to the current environment if that category is * application locale according to the current environment if that category is
* still "C". This is because the "C" locale breaks Unicode text input. * still "C". This is because the "C" locale breaks Unicode text input.
* *
@ -2679,7 +2691,7 @@ GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* monitor, int* xpos, int* ypos,
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
* *
* @remark @win32 On Windows 8 and earlier the physical size is calculated from * @remark __Win32:__ On Windows 8 and earlier the physical size is calculated from
* the current resolution and system DPI instead of querying the monitor EDID data. * the current resolution and system DPI instead of querying the monitor EDID data.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -2713,7 +2725,7 @@ GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* monitor, int* widthMM, int*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @wayland Fractional scaling information is not yet available for * @remark __Wayland:__ Fractional scaling information is not yet available for
* monitors, so this function only returns integer content scales. * monitors, so this function only returns integer content scales.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -2861,7 +2873,7 @@ GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun callback);
* @sa @ref glfwGetVideoMode * @sa @ref glfwGetVideoMode
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Changed to return an array of modes for a specific monitor. * __GLFW 3:__ Changed to return an array of modes for a specific monitor.
* *
* @ingroup monitor * @ingroup monitor
*/ */
@ -2915,7 +2927,7 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_INVALID_VALUE, * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_INVALID_VALUE,
* @ref GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * @ref GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland Monitor gamma is a privileged protocol, so this function * @remark __Wayland:__ Monitor gamma is a privileged protocol, so this function
* cannot be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE. * cannot be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -2939,7 +2951,7 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR
* and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland Monitor gamma is a privileged protocol, so this function * @remark __Wayland:__ Monitor gamma is a privileged protocol, so this function
* cannot be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE while * cannot be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE while
* returning `NULL`. * returning `NULL`.
* *
@ -2981,9 +2993,9 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
* @remark The size of the specified gamma ramp should match the size of the * @remark The size of the specified gamma ramp should match the size of the
* current ramp for that monitor. * current ramp for that monitor.
* *
* @remark @win32 The gamma ramp size must be 256. * @remark __Win32:__ The gamma ramp size must be 256.
* *
* @remark @wayland Monitor gamma is a privileged protocol, so this function * @remark __Wayland:__ Monitor gamma is a privileged protocol, so this function
* cannot be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE. * cannot be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE.
* *
* @pointer_lifetime The specified gamma ramp is copied before this function * @pointer_lifetime The specified gamma ramp is copied before this function
@ -3159,32 +3171,32 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
* GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE, @ref * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE, @ref
* GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
* *
* @remark @win32 Window creation will fail if the Microsoft GDI software * @remark __Win32:__ Window creation will fail if the Microsoft GDI software
* OpenGL implementation is the only one available. * OpenGL implementation is the only one available.
* *
* @remark @win32 If the executable has an icon resource named `GLFW_ICON,` it * @remark __Win32:__ If the executable has an icon resource named `GLFW_ICON,` it
* will be set as the initial icon for the window. If no such icon is present, * will be set as the initial icon for the window. If no such icon is present,
* the `IDI_APPLICATION` icon will be used instead. To set a different icon, * the `IDI_APPLICATION` icon will be used instead. To set a different icon,
* see @ref glfwSetWindowIcon. * see @ref glfwSetWindowIcon.
* *
* @remark @win32 The context to share resources with must not be current on * @remark __Win32:__ The context to share resources with must not be current on
* any other thread. * any other thread.
* *
* @remark @macos The OS only supports core profile contexts for OpenGL * @remark __macOS:__ The OS only supports core profile contexts for OpenGL
* versions 3.2 and later. Before creating an OpenGL context of version 3.2 or * versions 3.2 and later. Before creating an OpenGL context of version 3.2 or
* later you must set the [GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint) * later you must set the [GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint)
* hint accordingly. OpenGL 3.0 and 3.1 contexts are not supported at all * hint accordingly. OpenGL 3.0 and 3.1 contexts are not supported at all
* on macOS. * on macOS.
* *
* @remark @macos The GLFW window has no icon, as it is not a document * @remark __macOS:__ The GLFW window has no icon, as it is not a document
* window, but the dock icon will be the same as the application bundle's icon. * window, but the dock icon will be the same as the application bundle's icon.
* For more information on bundles, see the * For more information on bundles, see the
* [Bundle Programming Guide][bundle-guide] in the Mac Developer Library. * [Bundle Programming Guide][bundle-guide] in the Mac Developer Library.
* *
* [bundle-guide]: https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/ * [bundle-guide]: https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/
* *
* @remark @macos The window frame will not be rendered at full resolution on * @remark __macOS:__ The window frame will not be rendered at full resolution
* Retina displays unless the * on Retina displays unless the
* [GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint) * [GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint)
* hint is `GLFW_TRUE` and the `NSHighResolutionCapable` key is enabled in the * hint is `GLFW_TRUE` and the `NSHighResolutionCapable` key is enabled in the
* application bundle's `Info.plist`. For more information, see * application bundle's `Info.plist`. For more information, see
@ -3195,11 +3207,11 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
* *
* [hidpi-guide]: https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html * [hidpi-guide]: https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
* *
* @remark @macos When activating frame autosaving with * @remark __macOS:__ When activating frame autosaving with
* [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified * [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified
* window size and position may be overridden by previously saved values. * window size and position may be overridden by previously saved values.
* *
* @remark @wayland GLFW uses [libdecor][] where available to create its window * @remark __Wayland:__ GLFW uses [libdecor][] where available to create its window
* decorations. This in turn uses server-side XDG decorations where available * decorations. This in turn uses server-side XDG decorations where available
* and provides high quality client-side decorations on compositors like GNOME. * and provides high quality client-side decorations on compositors like GNOME.
* If both XDG decorations and libdecor are unavailable, GLFW falls back to * If both XDG decorations and libdecor are unavailable, GLFW falls back to
@ -3208,15 +3220,15 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
* *
* [libdecor]: https://gitlab.freedesktop.org/libdecor/libdecor * [libdecor]: https://gitlab.freedesktop.org/libdecor/libdecor
* *
* @remark @x11 Some window managers will not respect the placement of * @remark __X11:__ Some window managers will not respect the placement of
* initially hidden windows. * initially hidden windows.
* *
* @remark @x11 Due to the asynchronous nature of X11, it may take a moment for * @remark __X11:__ Due to the asynchronous nature of X11, it may take a moment for
* a window to reach its requested state. This means you may not be able to * a window to reach its requested state. This means you may not be able to
* query the final size, position or other attributes directly after window * query the final size, position or other attributes directly after window
* creation. * creation.
* *
* @remark @x11 The class part of the `WM_CLASS` window property will by * @remark __X11:__ The class part of the `WM_CLASS` window property will by
* default be set to the window title passed to this function. The instance * default be set to the window title passed to this function. The instance
* part will use the contents of the `RESOURCE_NAME` environment variable, if * part will use the contents of the `RESOURCE_NAME` environment variable, if
* present and not empty, or fall back to the window title. Set the * present and not empty, or fall back to the window title. Set the
@ -3349,7 +3361,7 @@ GLFWAPI const char* glfwGetWindowTitle(GLFWwindow* window);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @macos The window title will not be updated until the next time you * @remark __macOS:__ The window title will not be updated until the next time you
* process events. * process events.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -3358,7 +3370,7 @@ GLFWAPI const char* glfwGetWindowTitle(GLFWwindow* window);
* @sa @ref glfwGetWindowTitle * @sa @ref glfwGetWindowTitle
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -3392,14 +3404,14 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
* @pointer_lifetime The specified image data is copied before this function * @pointer_lifetime The specified image data is copied before this function
* returns. * returns.
* *
* @remark @macos Regular windows do not have icons on macOS. This function * @remark __macOS:__ Regular windows do not have icons on macOS. This function
* will emit @ref GLFW_FEATURE_UNAVAILABLE. The dock icon will be the same as * will emit @ref GLFW_FEATURE_UNAVAILABLE. The dock icon will be the same as
* the application bundle's icon. For more information on bundles, see the * the application bundle's icon. For more information on bundles, see the
* [Bundle Programming Guide][bundle-guide] in the Mac Developer Library. * [Bundle Programming Guide][bundle-guide] in the Mac Developer Library.
* *
* [bundle-guide]: https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/ * [bundle-guide]: https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/
* *
* @remark @wayland There is no existing protocol to change an icon, the * @remark __Wayland:__ There is no existing protocol to change an icon, the
* window will thus inherit the one defined in the application's desktop file. * window will thus inherit the one defined in the application's desktop file.
* This function will emit @ref GLFW_FEATURE_UNAVAILABLE. * This function will emit @ref GLFW_FEATURE_UNAVAILABLE.
* *
@ -3430,7 +3442,7 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* i
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland Window positions are not currently part of any common * @remark __Wayland:__ Window positions are not currently part of any common
* Wayland protocol, so this function cannot be implemented and will emit @ref * Wayland protocol, so this function cannot be implemented and will emit @ref
* GLFW_FEATURE_UNAVAILABLE. * GLFW_FEATURE_UNAVAILABLE.
* *
@ -3464,7 +3476,7 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland Window positions are not currently part of any common * @remark __Wayland:__ Window positions are not currently part of any common
* Wayland protocol, so this function cannot be implemented and will emit @ref * Wayland protocol, so this function cannot be implemented and will emit @ref
* GLFW_FEATURE_UNAVAILABLE. * GLFW_FEATURE_UNAVAILABLE.
* *
@ -3474,7 +3486,7 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
* @sa @ref glfwGetWindowPos * @sa @ref glfwGetWindowPos
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -3504,7 +3516,7 @@ GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);
* @sa @ref glfwSetWindowSize * @sa @ref glfwSetWindowSize
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -3539,7 +3551,7 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
* @remark If you set size limits and an aspect ratio that conflict, the * @remark If you set size limits and an aspect ratio that conflict, the
* results are undefined. * results are undefined.
* *
* @remark @wayland The size limits will not be applied until the window is * @remark __Wayland:__ The size limits will not be applied until the window is
* actually resized, either by the user or by the compositor. * actually resized, either by the user or by the compositor.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -3582,7 +3594,7 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minhe
* @remark If you set size limits and an aspect ratio that conflict, the * @remark If you set size limits and an aspect ratio that conflict, the
* results are undefined. * results are undefined.
* *
* @remark @wayland The aspect ratio will not be applied until the window is * @remark __Wayland:__ The aspect ratio will not be applied until the window is
* actually resized, either by the user or by the compositor. * actually resized, either by the user or by the compositor.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -3628,7 +3640,7 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
* @sa @ref glfwSetWindowMonitor * @sa @ref glfwSetWindowMonitor
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -3778,7 +3790,7 @@ GLFWAPI float glfwGetWindowOpacity(GLFWwindow* window);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland There is no way to set an opacity factor for a window. * @remark __Wayland:__ There is no way to set an opacity factor for a window.
* This function will emit @ref GLFW_FEATURE_UNAVAILABLE. * This function will emit @ref GLFW_FEATURE_UNAVAILABLE.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -3814,7 +3826,7 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
* @sa @ref glfwMaximizeWindow * @sa @ref glfwMaximizeWindow
* *
* @since Added in version 2.1. * @since Added in version 2.1.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -3834,9 +3846,9 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow* window);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @wayland Restoring a window from maximization is not currently part * @remark __Wayland:__ Restoring a window from maximization is not currently
* of any common Wayland protocol, so this function can only restore windows * part of any common Wayland protocol, so this function can only restore
* from maximization. * windows from maximization.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
@ -3845,7 +3857,7 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow* window);
* @sa @ref glfwMaximizeWindow * @sa @ref glfwMaximizeWindow
* *
* @since Added in version 2.1. * @since Added in version 2.1.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -3892,7 +3904,7 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* window);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @wayland Because Wayland wants every frame of the desktop to be * @remark __Wayland:__ Because Wayland wants every frame of the desktop to be
* complete, this function does not immediately make the window visible. * complete, this function does not immediately make the window visible.
* Instead it will become visible the next time the window framebuffer is * Instead it will become visible the next time the window framebuffer is
* updated after this call. * updated after this call.
@ -3955,7 +3967,7 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @wayland The compositor will likely ignore focus requests unless * @remark __Wayland:__ The compositor will likely ignore focus requests unless
* another window created by the same application already has input focus. * another window created by the same application already has input focus.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -3983,7 +3995,7 @@ GLFWAPI void glfwFocusWindow(GLFWwindow* window);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @macos Attention is requested to the application as a whole, not the * @remark __macOS:__ Attention is requested to the application as a whole, not the
* specific window. * specific window.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -4058,7 +4070,7 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
* affected by any resizing or mode switching, although you may need to update * affected by any resizing or mode switching, although you may need to update
* your viewport if the framebuffer size has changed. * your viewport if the framebuffer size has changed.
* *
* @remark @wayland Window positions are not currently part of any common * @remark __Wayland:__ Window positions are not currently part of any common
* Wayland protocol. The window position arguments are ignored. * Wayland protocol. The window position arguments are ignored.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -4096,7 +4108,7 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int
* errors. However, this function should not fail as long as it is passed * errors. However, this function should not fail as long as it is passed
* valid arguments and the library has been [initialized](@ref intro_init). * valid arguments and the library has been [initialized](@ref intro_init).
* *
* @remark @wayland Checking whether a window is iconified is not currently * @remark __Wayland:__ Checking whether a window is iconified is not currently
* part of any common Wayland protocol, so the @ref GLFW_ICONIFIED attribute * part of any common Wayland protocol, so the @ref GLFW_ICONIFIED attribute
* cannot be implemented and is always `GLFW_FALSE`. * cannot be implemented and is always `GLFW_FALSE`.
* *
@ -4140,7 +4152,7 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
* @remark Calling @ref glfwGetWindowAttrib will always return the latest * @remark Calling @ref glfwGetWindowAttrib will always return the latest
* value, even if that value is ignored by the current mode of the window. * value, even if that value is ignored by the current mode of the window.
* *
* @remark @wayland The [GLFW_FLOATING](@ref GLFW_FLOATING_attrib) window attribute is * @remark __Wayland:__ The [GLFW_FLOATING](@ref GLFW_FLOATING_attrib) window attribute is
* not supported. Setting this will emit @ref GLFW_FEATURE_UNAVAILABLE. * not supported. Setting this will emit @ref GLFW_FEATURE_UNAVAILABLE.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -4220,7 +4232,7 @@ GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window);
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
* *
* @remark @wayland This callback will not be called. The Wayland protocol * @remark __Wayland:__ This callback will not be called. The Wayland protocol
* provides no way to be notified of when a window is moved. * provides no way to be notified of when a window is moved.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -4259,7 +4271,7 @@ GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindow
* @sa @ref window_size * @sa @ref window_size
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter and return value. * __GLFW 3:__ Added window handle parameter and return value.
* *
* @ingroup window * @ingroup window
*/ */
@ -4291,7 +4303,7 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwind
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
* *
* @remark @macos Selecting Quit from the application menu will trigger the * @remark __macOS:__ Selecting Quit from the application menu will trigger the
* close callback for all windows. * close callback for all windows.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -4299,7 +4311,7 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwind
* @sa @ref window_close * @sa @ref window_close
* *
* @since Added in version 2.5. * @since Added in version 2.5.
* @glfw3 Added window handle parameter and return value. * __GLFW 3:__ Added window handle parameter and return value.
* *
* @ingroup window * @ingroup window
*/ */
@ -4335,7 +4347,7 @@ GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwi
* @sa @ref window_refresh * @sa @ref window_refresh
* *
* @since Added in version 2.5. * @since Added in version 2.5.
* @glfw3 Added window handle parameter and return value. * __GLFW 3:__ Added window handle parameter and return value.
* *
* @ingroup window * @ingroup window
*/ */
@ -4396,7 +4408,7 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwi
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
* *
* @remark @wayland This callback will not be called. The Wayland protocol * @remark __Wayland:__ This callback will not be called. The Wayland protocol
* provides no way to be notified of when a window is iconified, and no way to * provides no way to be notified of when a window is iconified, and no way to
* check whether a window is currently iconified. * check whether a window is currently iconified.
* *
@ -4905,7 +4917,7 @@ GLFWAPI int glfwGetKeyScancode(int key);
* @sa @ref input_key * @sa @ref input_key
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup input * @ingroup input
*/ */
@ -4937,7 +4949,7 @@ GLFWAPI int glfwGetKey(GLFWwindow* window, int key);
* @sa @ref input_mouse_button * @sa @ref input_mouse_button
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup input * @ingroup input
*/ */
@ -5007,7 +5019,7 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland This function will only work when the cursor mode is * @remark __Wayland:__ This function will only work when the cursor mode is
* `GLFW_CURSOR_DISABLED`, otherwise it will emit @ref GLFW_FEATURE_UNAVAILABLE. * `GLFW_CURSOR_DISABLED`, otherwise it will emit @ref GLFW_FEATURE_UNAVAILABLE.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -5205,7 +5217,7 @@ GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor);
* @sa @ref input_key * @sa @ref input_key
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter and return value. * __GLFW 3:__ Added window handle parameter and return value.
* *
* @ingroup input * @ingroup input
*/ */
@ -5248,7 +5260,7 @@ GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun callback);
* @sa @ref input_char * @sa @ref input_char
* *
* @since Added in version 2.4. * @since Added in version 2.4.
* @glfw3 Added window handle parameter and return value. * __GLFW 3:__ Added window handle parameter and return value.
* *
* @ingroup input * @ingroup input
*/ */
@ -5332,7 +5344,7 @@ GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmods
* @sa @ref input_mouse_button * @sa @ref input_mouse_button
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter and return value. * __GLFW 3:__ Added window handle parameter and return value.
* *
* @ingroup input * @ingroup input
*/ */
@ -5562,7 +5574,7 @@ GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count);
* @sa @ref joystick_button * @sa @ref joystick_button
* *
* @since Added in version 2.2. * @since Added in version 2.2.
* @glfw3 Changed to return a dynamic array. * __GLFW 3:__ Changed to return a dynamic array.
* *
* @ingroup input * @ingroup input
*/ */
@ -5926,7 +5938,7 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @win32 The clipboard on Windows has a single global lock for reading and * @remark __Win32:__ The clipboard on Windows has a single global lock for reading and
* writing. GLFW tries to acquire it a few times, which is almost always enough. If it * writing. GLFW tries to acquire it a few times, which is almost always enough. If it
* cannot acquire the lock then this function emits @ref GLFW_PLATFORM_ERROR and returns. * cannot acquire the lock then this function emits @ref GLFW_PLATFORM_ERROR and returns.
* It is safe to try this multiple times. * It is safe to try this multiple times.
@ -5959,7 +5971,7 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. * GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
* *
* @remark @win32 The clipboard on Windows has a single global lock for reading and * @remark __Win32:__ The clipboard on Windows has a single global lock for reading and
* writing. GLFW tries to acquire it a few times, which is almost always enough. If it * writing. GLFW tries to acquire it a few times, which is almost always enough. If it
* cannot acquire the lock then this function emits @ref GLFW_PLATFORM_ERROR and returns. * cannot acquire the lock then this function emits @ref GLFW_PLATFORM_ERROR and returns.
* It is safe to try this multiple times. * It is safe to try this multiple times.
@ -6093,6 +6105,9 @@ GLFWAPI uint64_t glfwGetTimerFrequency(void);
* thread can have only a single current context at a time. Making a context * thread can have only a single current context at a time. Making a context
* current detaches any previously current context on the calling thread. * current detaches any previously current context on the calling thread.
* *
* Making a context of a window current on a given thread will detach
* any user context which is current on that thread and visa versa.
*
* When moving a context between threads, you must detach it (make it * When moving a context between threads, you must detach it (make it
* non-current) on the old thread before making it current on the new one. * non-current) on the old thread before making it current on the new one.
* *
@ -6120,6 +6135,9 @@ GLFWAPI uint64_t glfwGetTimerFrequency(void);
* *
* @sa @ref context_current * @sa @ref context_current
* @sa @ref glfwGetCurrentContext * @sa @ref glfwGetCurrentContext
* @sa @ref context_current_user
* @sa @ref glfwMakeUserContextCurrent
* @sa @ref glfwGetCurrentUserContext
* *
* @since Added in version 3.0. * @since Added in version 3.0.
* *
@ -6176,7 +6194,7 @@ GLFWAPI GLFWwindow* glfwGetCurrentContext(void);
* @sa @ref glfwSwapInterval * @sa @ref glfwSwapInterval
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -6308,6 +6326,147 @@ GLFWAPI int glfwExtensionSupported(const char* extension);
*/ */
GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname);
/*! @brief Create a new OpenGL or OpenGL ES user context for a window
*
* This function creates a new OpenGL or OpenGL ES user context for a
* window, which can be used to call OpenGL or OpenGL ES functions on
* another thread. For a valid user context the window must be created
* with a [GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) other than
* `GLFW_NO_API`.
*
* User context creation uses the window context and framebuffer related
* hints to ensure a valid context is created for that window, these hints
* should be the same at the time of user context creation as when the
* window was created.
*
* Contexts share resources with the window context and with any other
* user context created for that window.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED,
* @ref GLFW_INVALID_VALUE the window parameter is `NULL`,
* @ref GLFW_NO_WINDOW_CONTEXT if the window has no OpenGL or
* OpenGL US context, and @ref GLFW_PLATFORM_ERROR.
*
* @param[in] window The Window for which the user context is to be
* created.
* @return The handle of the user context created, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref context_user
* @sa @ref usercontext_creation
* @sa @ref glfwDestroyUserContext
* @sa @ref window_creation
* @sa @ref glfwCreateWindow
* @sa @ref glfwDestroyWindow
*
* @since Added in version 3.4.
*
* @ingroup context
*/
GLFWAPI GLFWusercontext* glfwCreateUserContext(GLFWwindow* window);
/*! @brief Destroys the specified user context
*
* This function destroys the specified user context.
* User contexts should be destroyed before destroying the
* window they were made with.
*
* If the user context is current on the main thread, it is
* detached before being destroyed.
*
* @param[in] context The user context to destroy.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @note The user context must not be current on any other
* thread when this function is called.
*
* @reentrancy This function must not be called from a callback.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref context_user
* @sa @ref usercontext_creation
* @sa @ref glfwCreateUserContext
* @sa @ref window_creation
* @sa @ref glfwCreateWindow
* @sa @ref glfwDestroyWindow
*
* @since Added in version 3.4.
*
* @ingroup context
*/
GLFWAPI void glfwDestroyUserContext(GLFWusercontext* context);
/*! @brief Makes the user context current for the calling thread.
*
* This function makes the OpenGL or OpenGL ES context of the specified user
* context current on the calling thread. A context must only be made current on
* a single thread at a time and each thread can have only a single current
* context at a time.
*
* Making a user context current on a given thread will detach the context of
* any window which is current on that thread and visa versa.
*
* When moving a context between threads, you must make it non-current on the
* old thread before making it current on the new one.
*
* By default, making a context non-current implicitly forces a pipeline flush.
* On machines that support `GL_KHR_context_flush_control`, you can control
* whether a context performs this flush by setting the
* [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_hint)
* hint.
*
* @param[in] context The user context to make current, or `NULL` to
* detach the current context.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED,
* and @ref GLFW_PLATFORM_ERROR.
*
* @thread_safety This function may be called from any thread.
*
* @sa @ref context_user
* @sa @ref context_current_user
* @sa @ref glfwGetCurrentUserContext
* @sa @ref context_current
* @sa @ref glfwMakeContextCurrent
* @sa @ref glfwGetCurrentContext
*
* @since Added in version 3.4.
*
* @ingroup context
*/
GLFWAPI void glfwMakeUserContextCurrent(GLFWusercontext* context);
/*! @brief Returns the current OpenGL or OpenGL ES user context
*
* This function returns the user context which is current
* on the calling thread.
*
* @return The user context current, or `NULL` if no user context
* is current.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function may be called from any thread.
*
* @sa @ref context_user
* @sa @ref context_current_user
* @sa @ref glfwMakeUserContextCurrent
* @sa @ref context_current
* @sa @ref glfwMakeContextCurrent
* @sa @ref glfwGetCurrentContext
*
* @since Added in version 3.4.
*
* @ingroup context
*/
GLFWAPI GLFWusercontext* glfwGetCurrentUserContext(void);
/*! @brief Returns whether the Vulkan loader and an ICD have been found. /*! @brief Returns whether the Vulkan loader and an ICD have been found.
* *
* This function returns whether the Vulkan loader and any minimally functional * This function returns whether the Vulkan loader and any minimally functional
@ -6443,7 +6602,7 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* p
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
* *
* @remark @macos This function currently always returns `GLFW_TRUE`, as the * @remark __macOS:__ This function currently always returns `GLFW_TRUE`, as the
* `VK_MVK_macos_surface` and `VK_EXT_metal_surface` extensions do not provide * `VK_MVK_macos_surface` and `VK_EXT_metal_surface` extensions do not provide
* a `vkGetPhysicalDevice*PresentationSupport` type function. * a `vkGetPhysicalDevice*PresentationSupport` type function.
* *
@ -6501,15 +6660,15 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhys
* @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should
* eliminate almost all occurrences of these errors. * eliminate almost all occurrences of these errors.
* *
* @remark @macos GLFW prefers the `VK_EXT_metal_surface` extension, with the * @remark __macOS:__ GLFW prefers the `VK_EXT_metal_surface` extension, with the
* `VK_MVK_macos_surface` extension as a fallback. The name of the selected * `VK_MVK_macos_surface` extension as a fallback. The name of the selected
* extension, if any, is included in the array returned by @ref * extension, if any, is included in the array returned by @ref
* glfwGetRequiredInstanceExtensions. * glfwGetRequiredInstanceExtensions.
* *
* @remark @macos This function creates and sets a `CAMetalLayer` instance for * @remark __macOS:__ This function creates and sets a `CAMetalLayer` instance for
* the window content view, which is required for MoltenVK to function. * the window content view, which is required for MoltenVK to function.
* *
* @remark @x11 By default GLFW prefers the `VK_KHR_xcb_surface` extension, * @remark __X11:__ By default GLFW prefers the `VK_KHR_xcb_surface` extension,
* with the `VK_KHR_xlib_surface` extension as a fallback. You can make * with the `VK_KHR_xlib_surface` extension as a fallback. You can make
* `VK_KHR_xlib_surface` the preferred extension by setting the * `VK_KHR_xlib_surface` the preferred extension by setting the
* [GLFW_X11_XCB_VULKAN_SURFACE](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint) init * [GLFW_X11_XCB_VULKAN_SURFACE](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint) init

View File

@ -478,6 +478,29 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
* @ingroup native * @ingroup native
*/ */
GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window);
/*! @brief Retrieves the `GLXFBConfig` of the specified window's `GLXWindow`.
*
* @param[in] window The window whose `GLXWindow` to query.
* @param[out] config The `GLXFBConfig` of the window `GLXWindow`, if available.
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
* [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_UNAVAILABLE.
*
* @remark `GLXFBConfig` is an opaque type. Unlike other GLFW functions, the
* @p config out parameter is not cleared on error, as core GLX does not define
* any invalid value.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.5
*
* @ingroup native
*/
GLFWAPI int glfwGetGLXFBConfig(GLFWwindow* window, GLXFBConfig* config);
#endif #endif
#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) #if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
@ -586,6 +609,29 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
* @ingroup native * @ingroup native
*/ */
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window); GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
/*! @brief Retrieves the `EGLConfig` of the specified window's `EGLSurface`.
*
* @param[in] window The window whose `EGLSurface` to query.
* @param[out] config The `EGLConfig` of the window `EGLSurface`, if available.
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
* [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_NO_WINDOW_CONTEXT.
*
* @remark `EGLConfig` is an opaque type. Unlike other GLFW functions, the @p
* config out parameter is not cleared on error, as core EGL does not define
* any invalid value.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.5.
*
* @ingroup native
*/
GLFWAPI int glfwGetEGLConfig(GLFWwindow* window, EGLConfig* config);
#endif #endif
#if defined(GLFW_EXPOSE_NATIVE_OSMESA) #if defined(GLFW_EXPOSE_NATIVE_OSMESA)

View File

@ -559,6 +559,7 @@ GLFWbool _glfwConnectCocoa(int platformID, _GLFWplatform* platform)
.waitEvents = _glfwWaitEventsCocoa, .waitEvents = _glfwWaitEventsCocoa,
.waitEventsTimeout = _glfwWaitEventsTimeoutCocoa, .waitEventsTimeout = _glfwWaitEventsTimeoutCocoa,
.postEmptyEvent = _glfwPostEmptyEventCocoa, .postEmptyEvent = _glfwPostEmptyEventCocoa,
.createUserContext = _glfwCreateUserContextCocoa,
.getEGLPlatform = _glfwGetEGLPlatformCocoa, .getEGLPlatform = _glfwGetEGLPlatformCocoa,
.getEGLNativeDisplay = _glfwGetEGLNativeDisplayCocoa, .getEGLNativeDisplay = _glfwGetEGLNativeDisplayCocoa,
.getEGLNativeWindow = _glfwGetEGLNativeWindowCocoa, .getEGLNativeWindow = _glfwGetEGLNativeWindowCocoa,

View File

@ -107,6 +107,7 @@ typedef VkResult (APIENTRY *PFN_vkCreateMetalSurfaceEXT)(VkInstance,const VkMeta
#define GLFW_NSGL_CONTEXT_STATE _GLFWcontextNSGL nsgl; #define GLFW_NSGL_CONTEXT_STATE _GLFWcontextNSGL nsgl;
#define GLFW_NSGL_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl; #define GLFW_NSGL_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl;
#define GLFW_NSGL_USER_CONTEXT_STATE _GLFWusercontextNSGL nsgl;
// HIToolbox.framework pointer typedefs // HIToolbox.framework pointer typedefs
#define kTISPropertyUnicodeKeyLayoutData _glfw.ns.tis.kPropertyUnicodeKeyLayoutData #define kTISPropertyUnicodeKeyLayoutData _glfw.ns.tis.kPropertyUnicodeKeyLayoutData
@ -134,6 +135,14 @@ typedef struct _GLFWlibraryNSGL
CFBundleRef framework; CFBundleRef framework;
} _GLFWlibraryNSGL; } _GLFWlibraryNSGL;
// NSGL-specific per usercontext data
//
typedef struct _GLFWusercontextNSGL
{
id object;
} _GLFWusercontextNSGL;
// Cocoa-specific per-window data // Cocoa-specific per-window data
// //
typedef struct _GLFWwindowNS typedef struct _GLFWwindowNS
@ -300,3 +309,5 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);
void _glfwDestroyContextNSGL(_GLFWwindow* window); void _glfwDestroyContextNSGL(_GLFWwindow* window);
_GLFWusercontext* _glfwCreateUserContextCocoa(_GLFWwindow* window);
_GLFWusercontext* _glfwCreateUserContextNSGL(_GLFWwindow* window);

View File

@ -884,7 +884,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
[window->ns.object setContentView:window->ns.view]; [window->ns.object setContentView:window->ns.view];
[window->ns.object makeFirstResponder:window->ns.view]; [window->ns.object makeFirstResponder:window->ns.view];
[window->ns.object setTitle:@(wndconfig->title)]; [window->ns.object setTitle:@(window->title)];
[window->ns.object setDelegate:window->ns.delegate]; [window->ns.object setDelegate:window->ns.delegate];
[window->ns.object setAcceptsMouseMovedEvents:YES]; [window->ns.object setAcceptsMouseMovedEvents:YES];
[window->ns.object setRestorable:NO]; [window->ns.object setRestorable:NO];
@ -2021,6 +2021,25 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance,
} }
_GLFWusercontext* _glfwCreateUserContextCocoa(_GLFWwindow* window)
{
if (window->context.nsgl.object)
{
return _glfwCreateUserContextNSGL(window);
}
else if (window->context.egl.handle)
{
return _glfwCreateUserContextEGL(window);
}
else if (window->context.osmesa.handle)
{
return _glfwCreateUserContextOSMesa(window);
}
return NULL;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW native API ////// ////// GLFW native API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View File

@ -619,7 +619,9 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFWwindow* previous; _GLFWwindow* previous;
_GLFWusercontext* previousUserContext;
previousUserContext = _glfwPlatformGetTls(&_glfw.usercontextSlot);
previous = _glfwPlatformGetTls(&_glfw.contextSlot); previous = _glfwPlatformGetTls(&_glfw.contextSlot);
if (window && window->context.client == GLFW_NO_API) if (window && window->context.client == GLFW_NO_API)
@ -629,6 +631,12 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
return; return;
} }
if (previousUserContext)
{
assert(previous==NULL);
previousUserContext->makeCurrent(NULL);
}
if (previous) if (previous)
{ {
if (!window || window->context.source != previous->context.source) if (!window || window->context.source != previous->context.source)
@ -763,3 +771,65 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
return window->context.getProcAddress(procname); return window->context.getProcAddress(procname);
} }
GLFWAPI GLFWusercontext* glfwCreateUserContext(GLFWwindow* handle)
{
_GLFWusercontext* context;
_GLFWwindow* window = (_GLFWwindow*)handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (!window)
{
_glfwInputError(GLFW_INVALID_VALUE,
"Cannot create a user context without a valid window handle");
return NULL;
}
if (window->context.client == GLFW_NO_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT,
"Cannot create a user context for a window that has no OpenGL or OpenGL ES context");
return NULL;
}
context = _glfw.platform.createUserContext(window);
return (GLFWusercontext*)context;
}
GLFWAPI void glfwDestroyUserContext(GLFWusercontext* handle)
{
_GLFWusercontext* context = (_GLFWusercontext*)handle;
_GLFWusercontext* current = _glfwPlatformGetTls(&_glfw.usercontextSlot);
_GLFW_REQUIRE_INIT();
if (context)
{
if(current==context)
glfwMakeContextCurrent(NULL);
context->destroy(context);
}
}
GLFWAPI void glfwMakeUserContextCurrent(GLFWusercontext* handle)
{
_GLFWusercontext* context = (_GLFWusercontext*)handle;
_GLFW_REQUIRE_INIT();
// Call glfwMakeContextCurrent(NULL) to both clear context TLS and set
// context to NULL if required by platform & context, and this
// handles case of calling glfwMakeUserContextCurrent(NULL)
glfwMakeContextCurrent(NULL);
if (context)
context->makeCurrent(context);
}
GLFWAPI GLFWusercontext* glfwGetCurrentUserContext(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return _glfwPlatformGetTls(&_glfw.usercontextSlot);
}

View File

@ -436,6 +436,10 @@ GLFWbool _glfwInitEGL(void)
_glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglQueryString"); _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglQueryString");
_glfw.egl.GetProcAddress = (PFN_eglGetProcAddress) _glfw.egl.GetProcAddress = (PFN_eglGetProcAddress)
_glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglGetProcAddress"); _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglGetProcAddress");
_glfw.egl.CreatePbufferSurface = (PFN_eglCreatePbufferSurface)
_glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglCreatePbufferSurface");
_glfw.egl.ChooseConfig = (PFN_eglChooseConfig)
_glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglChooseConfig");
if (!_glfw.egl.GetConfigAttrib || if (!_glfw.egl.GetConfigAttrib ||
!_glfw.egl.GetConfigs || !_glfw.egl.GetConfigs ||
@ -453,7 +457,9 @@ GLFWbool _glfwInitEGL(void)
!_glfw.egl.SwapBuffers || !_glfw.egl.SwapBuffers ||
!_glfw.egl.SwapInterval || !_glfw.egl.SwapInterval ||
!_glfw.egl.QueryString || !_glfw.egl.QueryString ||
!_glfw.egl.GetProcAddress) !_glfw.egl.GetProcAddress ||
!_glfw.egl.CreatePbufferSurface||
!_glfw.egl.ChooseConfig)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to load required entry points"); "EGL: Failed to load required entry points");
@ -569,17 +575,15 @@ void _glfwTerminateEGL(void)
attribs[index++] = v; \ attribs[index++] = v; \
} }
// Create the OpenGL or OpenGL ES context // Create the OpenGL or OpenGL ES context for the window eglConfig
// //
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, GLFWbool _glfwCreateContextForConfigEGL(EGLConfig eglConfig,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) EGLContext* context)
{ {
EGLint attribs[40]; EGLint attribs[40];
EGLConfig config;
EGLContext share = NULL;
EGLNativeWindowType native;
int index = 0; int index = 0;
EGLContext share = NULL;
if (!_glfw.egl.display) if (!_glfw.egl.display)
{ {
@ -590,9 +594,6 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
if (ctxconfig->share) if (ctxconfig->share)
share = ctxconfig->share->context.egl.handle; share = ctxconfig->share->context.egl.handle;
if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
return GLFW_FALSE;
if (ctxconfig->client == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
{ {
if (!eglBindAPI(EGL_OPENGL_ES_API)) if (!eglBindAPI(EGL_OPENGL_ES_API))
@ -688,10 +689,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
SET_ATTRIB(EGL_NONE, EGL_NONE); SET_ATTRIB(EGL_NONE, EGL_NONE);
window->context.egl.handle = eglCreateContext(_glfw.egl.display, *context = eglCreateContext(_glfw.egl.display, eglConfig, share, attribs);
config, share, attribs);
if (window->context.egl.handle == EGL_NO_CONTEXT) if (*context == EGL_NO_CONTEXT)
{ {
_glfwInputError(GLFW_VERSION_UNAVAILABLE, _glfwInputError(GLFW_VERSION_UNAVAILABLE,
"EGL: Failed to create context: %s", "EGL: Failed to create context: %s",
@ -699,9 +699,32 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
// Set up attributes for surface creation return GLFW_TRUE;
index = 0; }
// Create the OpenGL or OpenGL ES context
//
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
EGLNativeWindowType native;
EGLint attribs[40];
int index = 0;
if (!chooseEGLConfig(ctxconfig, fbconfig, &window->context.egl.config))
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"EGL: Failed to find a suitable EGLConfig");
return GLFW_FALSE;
}
if (!_glfwCreateContextForConfigEGL(window->context.egl.config,ctxconfig,&window->context.egl.handle))
{
return GLFW_FALSE;
}
// Set up attributes for surface creation
if (fbconfig->sRGB) if (fbconfig->sRGB)
{ {
if (_glfw.egl.KHR_gl_colorspace) if (_glfw.egl.KHR_gl_colorspace)
@ -735,18 +758,18 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
// implement eglCreatePlatformWindowSurfaceEXT despite reporting // implement eglCreatePlatformWindowSurfaceEXT despite reporting
// support for EGL_EXT_platform_base // support for EGL_EXT_platform_base
window->context.egl.surface = window->context.egl.surface =
eglCreateWindowSurface(_glfw.egl.display, config, native, attribs); eglCreateWindowSurface(_glfw.egl.display, window->context.egl.config, native, attribs);
} }
else if (_glfw.egl.platform == EGL_PLATFORM_SURFACELESS_MESA) else if (_glfw.egl.platform == EGL_PLATFORM_SURFACELESS_MESA)
{ {
// HACK: Use a pbuffer surface as the default framebuffer // HACK: Use a pbuffer surface as the default framebuffer
window->context.egl.surface = window->context.egl.surface =
eglCreatePbufferSurface(_glfw.egl.display, config, attribs); eglCreatePbufferSurface(_glfw.egl.display, window->context.egl.config, attribs);
} }
else else
{ {
window->context.egl.surface = window->context.egl.surface =
eglCreatePlatformWindowSurfaceEXT(_glfw.egl.display, config, native, attribs); eglCreatePlatformWindowSurfaceEXT(_glfw.egl.display, window->context.egl.config, native, attribs);
} }
if (window->context.egl.surface == EGL_NO_SURFACE) if (window->context.egl.surface == EGL_NO_SURFACE)
@ -757,7 +780,6 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
window->context.egl.config = config;
// Load the appropriate client library // Load the appropriate client library
if (!_glfw.egl.KHR_get_all_proc_addresses) if (!_glfw.egl.KHR_get_all_proc_addresses)
@ -895,6 +917,109 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
} }
#endif // _GLFW_X11 #endif // _GLFW_X11
static void _glfwMakeUserContextCurrentEGL(_GLFWusercontext* context)
{
if (context)
{
if (!eglMakeCurrent(_glfw.egl.display,
context->egl.surface,
context->egl.surface,
context->egl.handle))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to make user context current: %s",
getEGLErrorString(eglGetError()));
_glfwPlatformSetTls(&_glfw.usercontextSlot, NULL);
return;
}
}
else
{
if (!eglMakeCurrent(_glfw.egl.display,
EGL_NO_SURFACE,
EGL_NO_SURFACE,
EGL_NO_CONTEXT))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to clear current user context: %s",
getEGLErrorString(eglGetError()));
return;
}
}
_glfwPlatformSetTls(&_glfw.usercontextSlot, context);
}
static void _glfwDestroyUserContextEGL(_GLFWusercontext* context)
{
if (context->egl.surface!=EGL_NO_SURFACE)
eglDestroySurface(_glfw.egl.display,context->egl.surface);
eglDestroyContext(_glfw.egl.display, context->egl.handle);
free(context);
}
_GLFWusercontext* _glfwCreateUserContextEGL(_GLFWwindow* window)
{
_GLFWusercontext* context;
_GLFWctxconfig ctxconfig;
EGLint dummyConfigAttribs[] =
{
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1,
EGL_NONE
};
EGLint dummySurfaceAttribs[] =
{
EGL_WIDTH, 1, EGL_HEIGHT, 1,
EGL_NONE
};
EGLint dummySurfaceNumConfigs;
EGLConfig dummySurfaceConfig;
context = calloc(1, sizeof(_GLFWusercontext));
context->window = window;
ctxconfig = _glfw.hints.context;
ctxconfig.share = window;
if (!_glfwCreateContextForConfigEGL(window->context.egl.config,&ctxconfig,&context->egl.handle))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to create user OpenGL context");
free(context);
return NULL;
}
if (glfwExtensionSupported("EGL_KHR_surfaceless_context"))
context->egl.surface = EGL_NO_SURFACE;
else
{
eglChooseConfig(_glfw.egl.display, dummyConfigAttribs, &dummySurfaceConfig, 1, &dummySurfaceNumConfigs);
if (!dummySurfaceNumConfigs)
{
eglDestroyContext(_glfw.egl.display, context->egl.handle);
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to find surface config for user context: %s", getEGLErrorString(eglGetError()));
free(context);
return NULL;
}
context->egl.surface = eglCreatePbufferSurface(_glfw.egl.display, dummySurfaceConfig, dummySurfaceAttribs);
if (context->egl.surface == EGL_NO_SURFACE)
{
eglDestroyContext(_glfw.egl.display, context->egl.handle);
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to create surface for user context: %s for %s", getEGLErrorString(eglGetError()), eglQueryString(_glfw.egl.display,0x3054));
free(context);
return NULL;
}
}
context->makeCurrent = _glfwMakeUserContextCurrentEGL;
context->destroy = _glfwDestroyUserContextEGL;
return context;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW native API ////// ////// GLFW native API //////
@ -939,10 +1064,32 @@ GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle)
window->context.source != GLFW_NATIVE_CONTEXT_API) window->context.source != GLFW_NATIVE_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return EGL_NO_CONTEXT; return EGL_NO_SURFACE;
} }
} }
return window->context.egl.surface; return window->context.egl.surface;
} }
GLFWAPI int glfwGetEGLConfig(GLFWwindow* handle, EGLConfig* config)
{
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(config != NULL);
if (window->context.source != GLFW_EGL_CONTEXT_API)
{
if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND ||
window->context.source != GLFW_NATIVE_CONTEXT_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return GLFW_FALSE;
}
}
*config = window->context.egl.config;
return GLFW_TRUE;
}

View File

@ -447,26 +447,19 @@ void _glfwTerminateGLX(void)
attribs[index++] = v; \ attribs[index++] = v; \
} }
// Create the OpenGL or OpenGL ES context
// Create the OpenGL or OpenGL ES context for the window fbConfig
// //
GLFWbool _glfwCreateContextGLX(_GLFWwindow* window, GLFWbool _glfwCreateContextForFBGLX(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) GLXContext* context)
{ {
int attribs[40]; int attribs[40];
GLXFBConfig native = NULL;
GLXContext share = NULL; GLXContext share = NULL;
if (ctxconfig->share) if (ctxconfig->share)
share = ctxconfig->share->context.glx.handle; share = ctxconfig->share->context.glx.handle;
if (!chooseGLXFBConfig(fbconfig, &native))
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"GLX: Failed to find a suitable GLXFBConfig");
return GLFW_FALSE;
}
if (ctxconfig->client == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
{ {
if (!_glfw.glx.ARB_create_context || if (!_glfw.glx.ARB_create_context ||
@ -581,9 +574,9 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
SET_ATTRIB(None, None); SET_ATTRIB(None, None);
window->context.glx.handle = *context =
_glfw.glx.CreateContextAttribsARB(_glfw.x11.display, _glfw.glx.CreateContextAttribsARB(_glfw.x11.display,
native, window->context.glx.fbconfig,
share, share,
True, True,
attribs); attribs);
@ -592,40 +585,64 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
// implementation of GLX_ARB_create_context_profile that fail // implementation of GLX_ARB_create_context_profile that fail
// default 1.0 context creation with a GLXBadProfileARB error in // default 1.0 context creation with a GLXBadProfileARB error in
// violation of the extension spec // violation of the extension spec
if (!window->context.glx.handle) if (!(*context))
{ {
if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB && if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&
ctxconfig->client == GLFW_OPENGL_API && ctxconfig->client == GLFW_OPENGL_API &&
ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE && ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&
ctxconfig->forward == GLFW_FALSE) ctxconfig->forward == GLFW_FALSE)
{ {
window->context.glx.handle = *context =
createLegacyContextGLX(window, native, share); createLegacyContextGLX(window, window->context.glx.fbconfig, share);
} }
} }
} }
else else
{ {
window->context.glx.handle = *context =
createLegacyContextGLX(window, native, share); createLegacyContextGLX(window, window->context.glx.fbconfig, share);
} }
_glfwReleaseErrorHandlerX11(); _glfwReleaseErrorHandlerX11();
if (!window->context.glx.handle) if (!(*context))
{ {
_glfwInputErrorX11(GLFW_VERSION_UNAVAILABLE, "GLX: Failed to create context"); _glfwInputErrorX11(GLFW_VERSION_UNAVAILABLE, "GLX: Failed to create context");
return GLFW_FALSE; return GLFW_FALSE;
} }
return GLFW_TRUE;
}
// Create the OpenGL or OpenGL ES context
//
GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
if (!chooseGLXFBConfig(fbconfig, &window->context.glx.fbconfig))
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"GLX: Failed to find a suitable GLXFBConfig");
return GLFW_FALSE;
}
if(!_glfwCreateContextForFBGLX(window,ctxconfig,&window->context.glx.handle))
{
return GLFW_FALSE;
}
window->context.glx.window = window->context.glx.window =
glXCreateWindow(_glfw.x11.display, native, window->x11.handle, NULL); glXCreateWindow(_glfw.x11.display, window->context.glx.fbconfig, window->x11.handle, NULL);
if (!window->context.glx.window) if (!window->context.glx.window)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to create window"); _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to create window");
return GLFW_FALSE; return GLFW_FALSE;
} }
window->context.glx.fbconfig = native;
window->context.makeCurrent = makeContextCurrentGLX; window->context.makeCurrent = makeContextCurrentGLX;
window->context.swapBuffers = swapBuffersGLX; window->context.swapBuffers = swapBuffersGLX;
window->context.swapInterval = swapIntervalGLX; window->context.swapInterval = swapIntervalGLX;
@ -670,6 +687,60 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
return GLFW_TRUE; return GLFW_TRUE;
} }
static void _glfwMakeUserContextCurrentGLX(_GLFWusercontext* context)
{
if (context)
{
if(!glXMakeCurrent(_glfw.x11.display, context->window->context.glx.window,context->glx.handle))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"GLX: Failed to make user context current");
_glfwPlatformSetTls(&_glfw.usercontextSlot, NULL);
return;
}
}
else
{
if (!glXMakeCurrent(_glfw.x11.display, None, NULL))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"GLX: Failed to clear current user context");
return;
}
}
_glfwPlatformSetTls(&_glfw.usercontextSlot, context);
}
static void _glfwDestroyUserContextGLX(_GLFWusercontext* context)
{
glXDestroyContext(_glfw.x11.display, context->glx.handle);
free(context);
}
_GLFWusercontext* _glfwCreateUserContextGLX(_GLFWwindow* window)
{
_GLFWusercontext* context;
_GLFWctxconfig ctxconfig;
context = calloc(1, sizeof(_GLFWusercontext));
context->window = window;
ctxconfig = _glfw.hints.context;
ctxconfig.share = window;
if(!_glfwCreateContextForFBGLX(window,&ctxconfig,&context->glx.handle))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"GLX: Failed to create user OpenGL context");
free(context);
return NULL;
}
context->makeCurrent = _glfwMakeUserContextCurrentGLX;
context->destroy = _glfwDestroyUserContextGLX;
return context;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW native API ////// ////// GLFW native API //////
@ -719,5 +790,29 @@ GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)
return window->context.glx.window; return window->context.glx.window;
} }
GLFWAPI int glfwGetGLXFBConfig(GLFWwindow* handle, GLXFBConfig* config)
{
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
if (_glfw.platform.platformID != GLFW_PLATFORM_X11)
{
_glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "GLX: Platform not initialized");
return GLFW_FALSE;
}
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(config != NULL);
if (window->context.source != GLFW_NATIVE_CONTEXT_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return GLFW_FALSE;
}
*config = window->context.glx.fbconfig;
return GLFW_TRUE;
}
#endif // _GLFW_X11 #endif // _GLFW_X11

View File

@ -132,6 +132,7 @@ static void terminate(void)
_glfw_free(error); _glfw_free(error);
} }
_glfwPlatformDestroyTls(&_glfw.usercontextSlot);
_glfwPlatformDestroyTls(&_glfw.contextSlot); _glfwPlatformDestroyTls(&_glfw.contextSlot);
_glfwPlatformDestroyTls(&_glfw.errorSlot); _glfwPlatformDestroyTls(&_glfw.errorSlot);
_glfwPlatformDestroyMutex(&_glfw.errorLock); _glfwPlatformDestroyMutex(&_glfw.errorLock);
@ -410,7 +411,8 @@ GLFWAPI int glfwInit(void)
if (!_glfwPlatformCreateMutex(&_glfw.errorLock) || if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
!_glfwPlatformCreateTls(&_glfw.errorSlot) || !_glfwPlatformCreateTls(&_glfw.errorSlot) ||
!_glfwPlatformCreateTls(&_glfw.contextSlot)) !_glfwPlatformCreateTls(&_glfw.contextSlot) ||
!_glfwPlatformCreateTls(&_glfw.usercontextSlot))
{ {
terminate(); terminate();
return GLFW_FALSE; return GLFW_FALSE;

View File

@ -79,6 +79,7 @@ typedef struct _GLFWmapping _GLFWmapping;
typedef struct _GLFWjoystick _GLFWjoystick; typedef struct _GLFWjoystick _GLFWjoystick;
typedef struct _GLFWtls _GLFWtls; typedef struct _GLFWtls _GLFWtls;
typedef struct _GLFWmutex _GLFWmutex; typedef struct _GLFWmutex _GLFWmutex;
typedef struct _GLFWusercontext _GLFWusercontext;
#define GL_VERSION 0x1f02 #define GL_VERSION 0x1f02
#define GL_NONE 0 #define GL_NONE 0
@ -217,6 +218,7 @@ typedef EGLBoolean (APIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface);
typedef EGLBoolean (APIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint); typedef EGLBoolean (APIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint);
typedef const char* (APIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint); typedef const char* (APIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint);
typedef GLFWglproc (APIENTRY * PFN_eglGetProcAddress)(const char*); typedef GLFWglproc (APIENTRY * PFN_eglGetProcAddress)(const char*);
typedef EGLBoolean (APIENTRY * PFN_eglChooseConfig)(EGLDisplay,EGLint const*,EGLConfig*,EGLint,EGLint*);
#define eglGetConfigAttrib _glfw.egl.GetConfigAttrib #define eglGetConfigAttrib _glfw.egl.GetConfigAttrib
#define eglGetConfigs _glfw.egl.GetConfigs #define eglGetConfigs _glfw.egl.GetConfigs
#define eglGetDisplay _glfw.egl.GetDisplay #define eglGetDisplay _glfw.egl.GetDisplay
@ -234,6 +236,8 @@ typedef GLFWglproc (APIENTRY * PFN_eglGetProcAddress)(const char*);
#define eglSwapInterval _glfw.egl.SwapInterval #define eglSwapInterval _glfw.egl.SwapInterval
#define eglQueryString _glfw.egl.QueryString #define eglQueryString _glfw.egl.QueryString
#define eglGetProcAddress _glfw.egl.GetProcAddress #define eglGetProcAddress _glfw.egl.GetProcAddress
#define eglCreatePbufferSurface _glfw.egl.CreatePbufferSurface
#define eglChooseConfig _glfw.egl.ChooseConfig
typedef EGLDisplay (APIENTRY * PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum,void*,const EGLint*); typedef EGLDisplay (APIENTRY * PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum,void*,const EGLint*);
typedef EGLSurface (APIENTRY * PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)(EGLDisplay,EGLConfig,void*,const EGLint*); typedef EGLSurface (APIENTRY * PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)(EGLDisplay,EGLConfig,void*,const EGLint*);
@ -402,7 +406,6 @@ struct _GLFWwndconfig
int ypos; int ypos;
int width; int width;
int height; int height;
const char* title;
GLFWbool resizable; GLFWbool resizable;
GLFWbool visible; GLFWbool visible;
GLFWbool decorated; GLFWbool decorated;
@ -525,6 +528,29 @@ struct _GLFWcontext
GLFW_PLATFORM_CONTEXT_STATE GLFW_PLATFORM_CONTEXT_STATE
}; };
// User Context structure
//
struct _GLFWusercontext
{
_GLFWwindow* window;
void (*makeCurrent)(_GLFWusercontext* context);
void (*destroy)(_GLFWusercontext* context);
struct {
EGLContext handle;
EGLSurface surface;
} egl;
struct {
OSMesaContext handle;
} osmesa;
// This is defined in platform.h
GLFW_PLATFORM_USER_CONTEXT_STATE
};
// Window and context structure // Window and context structure
// //
struct _GLFWwindow struct _GLFWwindow
@ -751,6 +777,7 @@ struct _GLFWplatform
void (*waitEvents)(void); void (*waitEvents)(void);
void (*waitEventsTimeout)(double); void (*waitEventsTimeout)(double);
void (*postEmptyEvent)(void); void (*postEmptyEvent)(void);
_GLFWusercontext* (*createUserContext)(_GLFWwindow*);
// EGL // EGL
EGLenum (*getEGLPlatform)(EGLint**); EGLenum (*getEGLPlatform)(EGLint**);
EGLNativeDisplayType (*getEGLNativeDisplay)(void); EGLNativeDisplayType (*getEGLNativeDisplay)(void);
@ -792,6 +819,7 @@ struct _GLFWlibrary
_GLFWtls errorSlot; _GLFWtls errorSlot;
_GLFWtls contextSlot; _GLFWtls contextSlot;
_GLFWtls usercontextSlot;
_GLFWmutex errorLock; _GLFWmutex errorLock;
struct { struct {
@ -842,6 +870,7 @@ struct _GLFWlibrary
PFN_eglSwapInterval SwapInterval; PFN_eglSwapInterval SwapInterval;
PFN_eglQueryString QueryString; PFN_eglQueryString QueryString;
PFN_eglGetProcAddress GetProcAddress; PFN_eglGetProcAddress GetProcAddress;
PFN_eglChooseConfig ChooseConfig;
PFNEGLGETPLATFORMDISPLAYEXTPROC GetPlatformDisplayEXT; PFNEGLGETPLATFORMDISPLAYEXTPROC GetPlatformDisplayEXT;
PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC CreatePlatformWindowSurfaceEXT; PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC CreatePlatformWindowSurfaceEXT;
@ -992,6 +1021,7 @@ void _glfwTerminateEGL(void);
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);
_GLFWusercontext* _glfwCreateUserContextEGL(_GLFWwindow* window);
#if defined(_GLFW_X11) #if defined(_GLFW_X11)
GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig, GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
@ -1004,6 +1034,7 @@ void _glfwTerminateOSMesa(void);
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window, GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);
_GLFWusercontext* _glfwCreateUserContextOSMesa(_GLFWwindow* window);
GLFWbool _glfwInitVulkan(int mode); GLFWbool _glfwInitVulkan(int mode);
void _glfwTerminateVulkan(void); void _glfwTerminateVulkan(void);

View File

@ -353,6 +353,54 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
} }
static void _glfwMakeUserContextCurrentNSGL(_GLFWusercontext* context)
{
@autoreleasepool {
if (context)
[context->nsgl.object makeCurrentContext];
else
[NSOpenGLContext clearCurrentContext];
_glfwPlatformSetTls(&_glfw.usercontextSlot, context);
} // autoreleasepool
}
static void _glfwDestroyUserContextNSGL(_GLFWusercontext* context)
{
@autoreleasepool {
[context->nsgl.object release];
} // autoreleasepool
free(context);
}
_GLFWusercontext* _glfwCreateUserContextNSGL(_GLFWwindow* window)
{
_GLFWusercontext* context;
context = calloc(1, sizeof(_GLFWusercontext));
context->window = window;
context->nsgl.object =
[[NSOpenGLContext alloc] initWithFormat:window->context.nsgl.pixelFormat
shareContext:window->context.nsgl.object];
if (window->context.nsgl.object == nil)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"NSGL: Failed to create OpenGL user context");
free(context);
return NULL;
}
context->makeCurrent = _glfwMakeUserContextCurrentNSGL;
context->destroy = _glfwDestroyUserContextNSGL;
return context;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW native API ////// ////// GLFW native API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View File

@ -105,6 +105,7 @@ GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform)
.waitEvents = _glfwWaitEventsNull, .waitEvents = _glfwWaitEventsNull,
.waitEventsTimeout = _glfwWaitEventsTimeoutNull, .waitEventsTimeout = _glfwWaitEventsTimeoutNull,
.postEmptyEvent = _glfwPostEmptyEventNull, .postEmptyEvent = _glfwPostEmptyEventNull,
.createUserContext = _glfwCreateUserContextNull,
.getEGLPlatform = _glfwGetEGLPlatformNull, .getEGLPlatform = _glfwGetEGLPlatformNull,
.getEGLNativeDisplay = _glfwGetEGLNativeDisplayNull, .getEGLNativeDisplay = _glfwGetEGLNativeDisplayNull,
.getEGLNativeWindow = _glfwGetEGLNativeWindowNull, .getEGLNativeWindow = _glfwGetEGLNativeWindowNull,

View File

@ -32,6 +32,7 @@
#define GLFW_NULL_CONTEXT_STATE #define GLFW_NULL_CONTEXT_STATE
#define GLFW_NULL_CURSOR_STATE #define GLFW_NULL_CURSOR_STATE
#define GLFW_NULL_LIBRARY_CONTEXT_STATE #define GLFW_NULL_LIBRARY_CONTEXT_STATE
#define GLFW_NULL_USER_CONTEXT_STATE
#define GLFW_NULL_SC_FIRST GLFW_NULL_SC_SPACE #define GLFW_NULL_SC_FIRST GLFW_NULL_SC_SPACE
#define GLFW_NULL_SC_SPACE 1 #define GLFW_NULL_SC_SPACE 1
@ -280,3 +281,5 @@ VkResult _glfwCreateWindowSurfaceNull(VkInstance instance, _GLFWwindow* window,
void _glfwPollMonitorsNull(void); void _glfwPollMonitorsNull(void);
_GLFWusercontext* _glfwCreateUserContextNull(_GLFWwindow* window);

View File

@ -747,3 +747,12 @@ VkResult _glfwCreateWindowSurfaceNull(VkInstance instance,
return err; return err;
} }
_GLFWusercontext* _glfwCreateUserContextNull(_GLFWwindow* window)
{
if (window->context.osmesa.handle)
{
return _glfwCreateUserContextOSMesa(window);
}
return NULL;
}

View File

@ -194,9 +194,9 @@ void _glfwTerminateOSMesa(void)
attribs[index++] = v; \ attribs[index++] = v; \
} }
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window, GLFWbool _glfwCreateContextForConfigOSMesa(const _GLFWctxconfig* ctxconfig,
const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig,
const _GLFWfbconfig* fbconfig) OSMesaContext* context )
{ {
OSMesaContext share = NULL; OSMesaContext share = NULL;
const int accumBits = fbconfig->accumRedBits + const int accumBits = fbconfig->accumRedBits +
@ -247,7 +247,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
SET_ATTRIB(0, 0); SET_ATTRIB(0, 0);
window->context.osmesa.handle = *context =
OSMesaCreateContextAttribs(attribs, share); OSMesaCreateContextAttribs(attribs, share);
} }
else else
@ -259,7 +259,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
window->context.osmesa.handle = *context =
OSMesaCreateContextExt(OSMESA_RGBA, OSMesaCreateContextExt(OSMESA_RGBA,
fbconfig->depthBits, fbconfig->depthBits,
fbconfig->stencilBits, fbconfig->stencilBits,
@ -267,13 +267,27 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
share); share);
} }
if (window->context.osmesa.handle == NULL) if (*context == NULL)
{ {
_glfwInputError(GLFW_VERSION_UNAVAILABLE, _glfwInputError(GLFW_VERSION_UNAVAILABLE,
"OSMesa: Failed to create context"); "OSMesa: Failed to create context");
return GLFW_FALSE; return GLFW_FALSE;
} }
return GLFW_TRUE;
}
#undef setAttrib
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
if(!_glfwCreateContextForConfigOSMesa(ctxconfig,fbconfig,&window->context.osmesa.handle))
{
return GLFW_FALSE;
}
window->context.makeCurrent = makeContextCurrentOSMesa; window->context.makeCurrent = makeContextCurrentOSMesa;
window->context.swapBuffers = swapBuffersOSMesa; window->context.swapBuffers = swapBuffersOSMesa;
window->context.swapInterval = swapIntervalOSMesa; window->context.swapInterval = swapIntervalOSMesa;
@ -284,8 +298,62 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
return GLFW_TRUE; return GLFW_TRUE;
} }
#undef SET_ATTRIB static void _glfwMakeUserContextCurrentOSMesa(_GLFWusercontext* context)
{
if (context)
{
if (!OSMesaMakeCurrent(context->osmesa.handle,
context->window->context.osmesa.buffer,
GL_UNSIGNED_BYTE,
context->window->context.osmesa.width, context->window->context.osmesa.height))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"OSMesa: Failed to make user context current");
_glfwPlatformSetTls(&_glfw.usercontextSlot, NULL);
return;
}
}
_glfwPlatformSetTls(&_glfw.usercontextSlot, context);
}
static void _glfwDestroyUserContextOSMesa(_GLFWusercontext* context)
{
if (context->osmesa.handle)
{
OSMesaDestroyContext(context->osmesa.handle);
}
free(context);
}
_GLFWusercontext* _glfwCreateUserContextOSMesa(_GLFWwindow* window)
{
_GLFWusercontext* context;
_GLFWctxconfig ctxconfig;
_GLFWfbconfig fbconfig;
context = calloc(1, sizeof(_GLFWusercontext));
context->window = window;
ctxconfig = _glfw.hints.context;
ctxconfig.share = window;
fbconfig = _glfw.hints.framebuffer;
if(!_glfwCreateContextForConfigOSMesa(&ctxconfig,&fbconfig,&context->osmesa.handle))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"OSMesa: Failed to create user OpenGL context");
free(context);
return NULL;
}
context->makeCurrent = _glfwMakeUserContextCurrentOSMesa;
context->destroy = _glfwDestroyUserContextOSMesa;
return context;
}
#undef SET_ATTRIB
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW native API ////// ////// GLFW native API //////

View File

@ -52,6 +52,7 @@
#define GLFW_WIN32_LIBRARY_WINDOW_STATE #define GLFW_WIN32_LIBRARY_WINDOW_STATE
#define GLFW_WGL_CONTEXT_STATE #define GLFW_WGL_CONTEXT_STATE
#define GLFW_WGL_LIBRARY_CONTEXT_STATE #define GLFW_WGL_LIBRARY_CONTEXT_STATE
#define GLFW_WGL_USER_CONTEXT_STATE
#endif #endif
#if defined(_GLFW_COCOA) #if defined(_GLFW_COCOA)
@ -65,6 +66,7 @@
#define GLFW_COCOA_LIBRARY_WINDOW_STATE #define GLFW_COCOA_LIBRARY_WINDOW_STATE
#define GLFW_NSGL_CONTEXT_STATE #define GLFW_NSGL_CONTEXT_STATE
#define GLFW_NSGL_LIBRARY_CONTEXT_STATE #define GLFW_NSGL_LIBRARY_CONTEXT_STATE
#define GLFW_NSGL_USER_CONTEXT_STATE
#endif #endif
#if defined(_GLFW_WAYLAND) #if defined(_GLFW_WAYLAND)
@ -88,6 +90,7 @@
#define GLFW_X11_LIBRARY_WINDOW_STATE #define GLFW_X11_LIBRARY_WINDOW_STATE
#define GLFW_GLX_CONTEXT_STATE #define GLFW_GLX_CONTEXT_STATE
#define GLFW_GLX_LIBRARY_CONTEXT_STATE #define GLFW_GLX_LIBRARY_CONTEXT_STATE
#define GLFW_GLX_USER_CONTEXT_STATE
#endif #endif
#include "null_joystick.h" #include "null_joystick.h"
@ -165,6 +168,11 @@
GLFW_NSGL_LIBRARY_CONTEXT_STATE \ GLFW_NSGL_LIBRARY_CONTEXT_STATE \
GLFW_GLX_LIBRARY_CONTEXT_STATE GLFW_GLX_LIBRARY_CONTEXT_STATE
#define GLFW_PLATFORM_USER_CONTEXT_STATE \
GLFW_WGL_USER_CONTEXT_STATE \
GLFW_NSGL_USER_CONTEXT_STATE \
GLFW_GLX_USER_CONTEXT_STATE
#if defined(_WIN32) #if defined(_WIN32)
#define GLFW_BUILD_WIN32_THREAD #define GLFW_BUILD_WIN32_THREAD
#else #else

View File

@ -536,47 +536,17 @@ void _glfwTerminateWGL(void)
attribs[index++] = v; \ attribs[index++] = v; \
} }
// Create the OpenGL or OpenGL ES context // Create the OpenGL or OpenGL ES context for the given HDC
// //
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, GLFWbool _glfwCreateContextForDCWGL(HDC dc, const _GLFWctxconfig* ctxconfig, HGLRC* context)
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{ {
int attribs[40]; int attribs[40];
int pixelFormat;
PIXELFORMATDESCRIPTOR pfd;
HGLRC share = NULL; HGLRC share = NULL;
*context = NULL;
if (ctxconfig->share) if (ctxconfig->share)
share = ctxconfig->share->context.wgl.handle; share = ctxconfig->share->context.wgl.handle;
window->context.wgl.dc = GetDC(window->win32.handle);
if (!window->context.wgl.dc)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve DC for window");
return GLFW_FALSE;
}
pixelFormat = choosePixelFormatWGL(window, ctxconfig, fbconfig);
if (!pixelFormat)
return GLFW_FALSE;
if (!DescribePixelFormat(window->context.wgl.dc,
pixelFormat, sizeof(pfd), &pfd))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve PFD for selected pixel format");
return GLFW_FALSE;
}
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to set selected pixel format");
return GLFW_FALSE;
}
if (ctxconfig->client == GLFW_OPENGL_API) if (ctxconfig->client == GLFW_OPENGL_API)
{ {
if (ctxconfig->forward) if (ctxconfig->forward)
@ -690,9 +660,9 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
SET_ATTRIB(0, 0); SET_ATTRIB(0, 0);
window->context.wgl.handle = *context =
wglCreateContextAttribsARB(window->context.wgl.dc, share, attribs); wglCreateContextAttribsARB(dc, share, attribs);
if (!window->context.wgl.handle) if (!(*context))
{ {
const DWORD error = GetLastError(); const DWORD error = GetLastError();
@ -742,8 +712,8 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
} }
else else
{ {
window->context.wgl.handle = wglCreateContext(window->context.wgl.dc); *context = wglCreateContext(dc);
if (!window->context.wgl.handle) if (!(*context) )
{ {
_glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE, _glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
"WGL: Failed to create OpenGL context"); "WGL: Failed to create OpenGL context");
@ -752,7 +722,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
if (share) if (share)
{ {
if (!wglShareLists(share, window->context.wgl.handle)) if (!wglShareLists(share, *context))
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to enable sharing with specified OpenGL context"); "WGL: Failed to enable sharing with specified OpenGL context");
@ -761,6 +731,50 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
} }
} }
return GLFW_TRUE;
}
// Create the OpenGL or OpenGL ES context
//
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
int pixelFormat;
PIXELFORMATDESCRIPTOR pfd;
window->context.wgl.dc = GetDC(window->win32.handle);
if (!window->context.wgl.dc)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve DC for window");
return GLFW_FALSE;
}
pixelFormat = choosePixelFormatWGL(window, ctxconfig, fbconfig);
if (!pixelFormat)
return GLFW_FALSE;
if (!DescribePixelFormat(window->context.wgl.dc,
pixelFormat, sizeof(pfd), &pfd))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve PFD for selected pixel format");
return GLFW_FALSE;
}
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to set selected pixel format");
return GLFW_FALSE;
}
if(!_glfwCreateContextForDCWGL( window->context.wgl.dc, ctxconfig, &window->context.wgl.handle ))
{
return GLFW_FALSE;
}
window->context.makeCurrent = makeContextCurrentWGL; window->context.makeCurrent = makeContextCurrentWGL;
window->context.swapBuffers = swapBuffersWGL; window->context.swapBuffers = swapBuffersWGL;
window->context.swapInterval = swapIntervalWGL; window->context.swapInterval = swapIntervalWGL;
@ -771,6 +785,65 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
return GLFW_TRUE; return GLFW_TRUE;
} }
static void _glfwMakeUserContextCurrentWGL(_GLFWusercontext* context)
{
if (context)
{
if (!wglMakeCurrent(context->window->context.wgl.dc,context->wgl.handle))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to make user context current");
_glfwPlatformSetTls(&_glfw.usercontextSlot, NULL);
return;
}
}
else
{
if (!wglMakeCurrent(NULL, NULL))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to clear current user context");
}
}
_glfwPlatformSetTls(&_glfw.usercontextSlot, context);
}
static void _glfwDestroyUserContextWGL(_GLFWusercontext* context)
{
wglDeleteContext(context->wgl.handle);
free(context);
}
_GLFWusercontext* _glfwCreateUserContextWGL(_GLFWwindow* window)
{
_GLFWusercontext* context;
_GLFWctxconfig ctxconfig;
context = calloc(1, sizeof(_GLFWusercontext));
context->window = window;
ctxconfig = _glfw.hints.context;
ctxconfig.share = window;
if (!_glfwCreateContextForDCWGL(window->context.wgl.dc, &ctxconfig, &context->wgl.handle))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to create user OpenGL context");
free(context);
return NULL;
}
context->makeCurrent = _glfwMakeUserContextCurrentWGL;
context->destroy = _glfwDestroyUserContextWGL;
return context;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW native API //////
//////////////////////////////////////////////////////////////////////////
#undef SET_ATTRIB #undef SET_ATTRIB
GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle) GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)

View File

@ -664,6 +664,7 @@ GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform)
.waitEvents = _glfwWaitEventsWin32, .waitEvents = _glfwWaitEventsWin32,
.waitEventsTimeout = _glfwWaitEventsTimeoutWin32, .waitEventsTimeout = _glfwWaitEventsTimeoutWin32,
.postEmptyEvent = _glfwPostEmptyEventWin32, .postEmptyEvent = _glfwPostEmptyEventWin32,
.createUserContext = _glfwCreateUserContextWin32,
.getEGLPlatform = _glfwGetEGLPlatformWin32, .getEGLPlatform = _glfwGetEGLPlatformWin32,
.getEGLNativeDisplay = _glfwGetEGLNativeDisplayWin32, .getEGLNativeDisplay = _glfwGetEGLNativeDisplayWin32,
.getEGLNativeWindow = _glfwGetEGLNativeWindowWin32, .getEGLNativeWindow = _glfwGetEGLNativeWindowWin32,

View File

@ -307,6 +307,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
#define GLFW_WGL_CONTEXT_STATE _GLFWcontextWGL wgl; #define GLFW_WGL_CONTEXT_STATE _GLFWcontextWGL wgl;
#define GLFW_WGL_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl; #define GLFW_WGL_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl;
#define GLFW_WGL_USER_CONTEXT_STATE _GLFWusercontextWGL wgl;
// WGL-specific per-context data // WGL-specific per-context data
@ -350,6 +351,14 @@ typedef struct _GLFWlibraryWGL
GLFWbool ARB_context_flush_control; GLFWbool ARB_context_flush_control;
} _GLFWlibraryWGL; } _GLFWlibraryWGL;
// WGL-specific per-usercontext data
//
typedef struct _GLFWusercontextWGL
{
HDC dc;
HGLRC handle;
} _GLFWusercontextWGL;
// Win32-specific per-window data // Win32-specific per-window data
// //
typedef struct _GLFWwindowWin32 typedef struct _GLFWwindowWin32
@ -565,3 +574,5 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);
_GLFWusercontext* _glfwCreateUserContextWin32(_GLFWwindow* window);
_GLFWusercontext* _glfwCreateUserContextWGL(_GLFWwindow* window);

View File

@ -1377,7 +1377,7 @@ static int createNativeWindow(_GLFWwindow* window,
frameHeight = rect.bottom - rect.top; frameHeight = rect.bottom - rect.top;
} }
wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title); wideTitle = _glfwCreateWideStringFromUTF8Win32(window->title);
if (!wideTitle) if (!wideTitle)
return GLFW_FALSE; return GLFW_FALSE;
@ -2562,6 +2562,28 @@ VkResult _glfwCreateWindowSurfaceWin32(VkInstance instance,
return err; return err;
} }
_GLFWusercontext* _glfwCreateUserContextWin32(_GLFWwindow* window)
{
if (window->context.wgl.handle)
{
return _glfwCreateUserContextWGL(window);
}
else if (window->context.egl.handle)
{
return _glfwCreateUserContextEGL(window);
}
else if (window->context.osmesa.handle)
{
return _glfwCreateUserContextOSMesa(window);
}
return GLFW_FALSE;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW native API //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle) GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);

View File

@ -208,7 +208,6 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
wndconfig.width = width; wndconfig.width = width;
wndconfig.height = height; wndconfig.height = height;
wndconfig.title = title;
ctxconfig.share = (_GLFWwindow*) share; ctxconfig.share = (_GLFWwindow*) share;
if (!_glfwIsValidContextConfig(&ctxconfig)) if (!_glfwIsValidContextConfig(&ctxconfig))

View File

@ -510,6 +510,7 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform)
.waitEvents = _glfwWaitEventsWayland, .waitEvents = _glfwWaitEventsWayland,
.waitEventsTimeout = _glfwWaitEventsTimeoutWayland, .waitEventsTimeout = _glfwWaitEventsTimeoutWayland,
.postEmptyEvent = _glfwPostEmptyEventWayland, .postEmptyEvent = _glfwPostEmptyEventWayland,
.createUserContext = _glfwCreateUserContextWayland,
.getEGLPlatform = _glfwGetEGLPlatformWayland, .getEGLPlatform = _glfwGetEGLPlatformWayland,
.getEGLNativeDisplay = _glfwGetEGLNativeDisplayWayland, .getEGLNativeDisplay = _glfwGetEGLNativeDisplayWayland,
.getEGLNativeWindow = _glfwGetEGLNativeWindowWayland, .getEGLNativeWindow = _glfwGetEGLNativeWindowWayland,

View File

@ -690,6 +690,8 @@ void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
void _glfwAddOutputWayland(uint32_t name, uint32_t version); void _glfwAddOutputWayland(uint32_t name, uint32_t version);
void _glfwUpdateBufferScaleFromOutputsWayland(_GLFWwindow* window); void _glfwUpdateBufferScaleFromOutputsWayland(_GLFWwindow* window);
_GLFWusercontext* _glfwCreateUserContextWayland(_GLFWwindow* window);
void _glfwAddSeatListenerWayland(struct wl_seat* seat); void _glfwAddSeatListenerWayland(struct wl_seat* seat);
void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device); void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device);

View File

@ -3324,6 +3324,19 @@ VkResult _glfwCreateWindowSurfaceWayland(VkInstance instance,
return err; return err;
} }
_GLFWusercontext* _glfwCreateUserContextWayland(_GLFWwindow* window)
{
if (window->context.egl.handle)
{
return _glfwCreateUserContextEGL(window);
}
else if (window->context.osmesa.handle)
{
return _glfwCreateUserContextOSMesa(window);
}
return NULL;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW native API ////// ////// GLFW native API //////

View File

@ -1241,6 +1241,7 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform)
.waitEvents = _glfwWaitEventsX11, .waitEvents = _glfwWaitEventsX11,
.waitEventsTimeout = _glfwWaitEventsTimeoutX11, .waitEventsTimeout = _glfwWaitEventsTimeoutX11,
.postEmptyEvent = _glfwPostEmptyEventX11, .postEmptyEvent = _glfwPostEmptyEventX11,
.createUserContext = _glfwCreateUserContextX11,
.getEGLPlatform = _glfwGetEGLPlatformX11, .getEGLPlatform = _glfwGetEGLPlatformX11,
.getEGLNativeDisplay = _glfwGetEGLNativeDisplayX11, .getEGLNativeDisplay = _glfwGetEGLNativeDisplayX11,
.getEGLNativeWindow = _glfwGetEGLNativeWindowX11, .getEGLNativeWindow = _glfwGetEGLNativeWindowX11,

View File

@ -462,7 +462,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(Vk
#define GLFW_GLX_CONTEXT_STATE _GLFWcontextGLX glx; #define GLFW_GLX_CONTEXT_STATE _GLFWcontextGLX glx;
#define GLFW_GLX_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx; #define GLFW_GLX_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx;
#define GLFW_GLX_USER_CONTEXT_STATE _GLFWusercontextGLX glx;
// GLX-specific per-context data // GLX-specific per-context data
// //
@ -470,6 +470,7 @@ typedef struct _GLFWcontextGLX
{ {
GLXContext handle; GLXContext handle;
GLXWindow window; GLXWindow window;
GLXFBConfig fbconfig;
} _GLFWcontextGLX; } _GLFWcontextGLX;
// GLX-specific global data // GLX-specific global data
@ -518,6 +519,13 @@ typedef struct _GLFWlibraryGLX
GLFWbool ARB_context_flush_control; GLFWbool ARB_context_flush_control;
} _GLFWlibraryGLX; } _GLFWlibraryGLX;
// GLX-specific per usercontext data
//
typedef struct _GLFWusercontextGLX
{
GLXContext handle;
} _GLFWusercontextGLX;
// X11-specific per-window data // X11-specific per-window data
// //
typedef struct _GLFWwindowX11 typedef struct _GLFWwindowX11
@ -1002,3 +1010,5 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
const _GLFWfbconfig* fbconfig, const _GLFWfbconfig* fbconfig,
Visual** visual, int* depth); Visual** visual, int* depth);
_GLFWusercontext* _glfwCreateUserContextX11(_GLFWwindow* window);
_GLFWusercontext* _glfwCreateUserContextGLX(_GLFWwindow* window);

View File

@ -754,13 +754,13 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
const char* resourceName = getenv("RESOURCE_NAME"); const char* resourceName = getenv("RESOURCE_NAME");
if (resourceName && strlen(resourceName)) if (resourceName && strlen(resourceName))
hint->res_name = (char*) resourceName; hint->res_name = (char*) resourceName;
else if (strlen(wndconfig->title)) else if (strlen(window->title))
hint->res_name = (char*) wndconfig->title; hint->res_name = (char*) window->title;
else else
hint->res_name = (char*) "glfw-application"; hint->res_name = (char*) "glfw-application";
if (strlen(wndconfig->title)) if (strlen(window->title))
hint->res_class = (char*) wndconfig->title; hint->res_class = (char*) window->title;
else else
hint->res_class = (char*) "GLFW-Application"; hint->res_class = (char*) "GLFW-Application";
} }
@ -780,7 +780,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
if (_glfw.x11.im) if (_glfw.x11.im)
_glfwCreateInputContextX11(window); _glfwCreateInputContextX11(window);
_glfwSetWindowTitleX11(window, wndconfig->title); _glfwSetWindowTitleX11(window, window->title);
_glfwGetWindowPosX11(window, &window->x11.xpos, &window->x11.ypos); _glfwGetWindowPosX11(window, &window->x11.xpos, &window->x11.ypos);
_glfwGetWindowSizeX11(window, &window->x11.width, &window->x11.height); _glfwGetWindowSizeX11(window, &window->x11.width, &window->x11.height);
@ -3282,6 +3282,24 @@ VkResult _glfwCreateWindowSurfaceX11(VkInstance instance,
} }
} }
_GLFWusercontext* _glfwCreateUserContextX11(_GLFWwindow* window)
{
if (window->context.glx.handle)
{
return _glfwCreateUserContextGLX(window);
}
else if (window->context.egl.handle)
{
return _glfwCreateUserContextEGL(window);
}
else if (window->context.osmesa.handle)
{
return _glfwCreateUserContextOSMesa(window);
}
return NULL;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW native API ////// ////// GLFW native API //////

View File

@ -28,6 +28,7 @@ add_executable(iconify iconify.c ${GETOPT} ${GLAD_GL})
add_executable(monitors monitors.c ${GETOPT} ${GLAD_GL}) add_executable(monitors monitors.c ${GETOPT} ${GLAD_GL})
add_executable(reopen reopen.c ${GLAD_GL}) add_executable(reopen reopen.c ${GLAD_GL})
add_executable(cursor cursor.c ${GLAD_GL}) add_executable(cursor cursor.c ${GLAD_GL})
add_executable(usercontext usercontext.c ${TINYCTHREAD} ${GLAD_GL})
add_executable(empty WIN32 MACOSX_BUNDLE empty.c ${TINYCTHREAD} ${GLAD_GL}) add_executable(empty WIN32 MACOSX_BUNDLE empty.c ${TINYCTHREAD} ${GLAD_GL})
add_executable(gamma WIN32 MACOSX_BUNDLE gamma.c ${GLAD_GL}) add_executable(gamma WIN32 MACOSX_BUNDLE gamma.c ${GLAD_GL})
@ -51,7 +52,7 @@ endif()
set(GUI_ONLY_BINARIES empty gamma icon inputlag joysticks tearing threads set(GUI_ONLY_BINARIES empty gamma icon inputlag joysticks tearing threads
timeout title triangle-vulkan window) timeout title triangle-vulkan window)
set(CONSOLE_BINARIES allocator clipboard events msaa glfwinfo iconify monitors set(CONSOLE_BINARIES allocator clipboard events msaa glfwinfo iconify monitors
reopen cursor) reopen cursor usercontext)
set_target_properties(${GUI_ONLY_BINARIES} ${CONSOLE_BINARIES} PROPERTIES set_target_properties(${GUI_ONLY_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
C_STANDARD 99 C_STANDARD 99

200
tests/usercontext.c Normal file
View File

@ -0,0 +1,200 @@
//========================================================================
// User context test
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test is intended to verify whether the OpenGL user context part of
// the GLFW API is able to be used from multiple threads
//
//========================================================================
#include "tinycthread.h"
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <stdio.h>
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static int thread_main(void* data)
{
GLFWusercontext* usercontext = (GLFWusercontext*)data;
/* set the user context current */
glfwMakeUserContextCurrent(usercontext);
if (glfwGetCurrentContext() != NULL)
{
fprintf(stderr, "Current glfw window context not NULL after glfwMakeUserContextCurrent\n");
glfwTerminate();
return -1;
}
if (glfwGetCurrentUserContext() != usercontext)
{
fprintf(stderr, "Current user context not correct after glfwMakeUserContextCurrent\n");
glfwTerminate();
return -1;
}
/* set the user context to NULL */
glfwMakeUserContextCurrent(NULL);
if (glfwGetCurrentUserContext() != NULL)
{
fprintf(stderr, "Current user context not NULL after glfwMakeContextCurrent\n");
glfwTerminate();
return -1;
}
return 0;
}
int main(void)
{
GLFWwindow* window;
GLFWusercontext* usercontext;
thrd_t thread_id;
int result, count;
glfwSetErrorCallback(error_callback);
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "User Context", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
/* make a new context */
usercontext = glfwCreateUserContext(window);
if (!usercontext)
{
fprintf(stderr, "Failed to create user context\n");
glfwTerminate();
return -1;
}
/* set the user context current */
glfwMakeUserContextCurrent(usercontext);
if (glfwGetCurrentContext() != NULL)
{
fprintf(stderr, "Current glfw window context not NULL after glfwMakeUserContextCurrent\n");
glfwTerminate();
return -1;
}
if (glfwGetCurrentUserContext() != usercontext)
{
fprintf(stderr, "Current user context not correct after glfwMakeUserContextCurrent\n");
glfwTerminate();
return -1;
}
/* set the window context current */
glfwMakeContextCurrent(window);
if (glfwGetCurrentUserContext() != NULL)
{
fprintf(stderr, "Current user context not NULL after glfwMakeContextCurrent\n");
glfwTerminate();
return -1;
}
if (glfwGetCurrentContext() != window)
{
fprintf(stderr, "Current glfw window context not correct after glfwMakeContextCurrent\n");
glfwTerminate();
return -1;
}
glClearColor( 0.4f, 0.3f, 0.4f, 1.0f );
// Launch a thread which should create and use the usercontext
if (thrd_create(&thread_id, thread_main, usercontext ) !=
thrd_success)
{
fprintf(stderr, "Failed to create secondary thread\n");
glfwTerminate();
exit(EXIT_FAILURE);
}
/* Loop 60 times or until the user closes the window */
count = 0;
while (!glfwWindowShouldClose(window) && count++ < 60)
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
thrd_join(thread_id, &result);
/* One more test now the thread has joined */
/* set the user context current */
glfwMakeUserContextCurrent(usercontext);
if (glfwGetCurrentContext() != NULL)
{
fprintf(stderr, "Current glfw window context not NULL after glfwMakeUserContextCurrent\n");
glfwTerminate();
return -1;
}
if (glfwGetCurrentUserContext() != usercontext)
{
fprintf(stderr, "Current user context not correct after glfwMakeUserContextCurrent\n");
glfwTerminate();
return -1;
}
/* set the user context to NULL */
glfwMakeUserContextCurrent(NULL);
if (glfwGetCurrentUserContext() != NULL)
{
fprintf(stderr, "Current user context not NULL after glfwMakeContextCurrent\n");
glfwTerminate();
return -1;
}
glfwDestroyUserContext(usercontext);
glfwTerminate();
return 0;
}