mirror of
https://github.com/glfw/glfw.git
synced 2025-09-05 21:40:41 +00:00
Compare commits
66 Commits
1d43570cdd
...
3a79504b14
Author | SHA1 | Date | |
---|---|---|---|
|
3a79504b14 | ||
|
63a7e8b7f8 | ||
|
acb92944d4 | ||
|
7ef6efeb66 | ||
|
3cf9f6726d | ||
|
bfa1c424e5 | ||
|
af6e36f250 | ||
|
5c08ecbb5c | ||
|
d35fdc21eb | ||
|
32e0089b86 | ||
|
e2f9340a8c | ||
|
58aad6c136 | ||
|
e4e46b4cc5 | ||
|
587025f9cb | ||
|
ca4485e12e | ||
|
ece28b0f19 | ||
|
df70d8e9bf | ||
|
6148990427 | ||
|
64694f17ab | ||
|
bbe6c4cfa1 | ||
|
c01d16a9ee | ||
|
f40442fa59 | ||
|
f2a9ea7b7e | ||
|
48c0cea73f | ||
|
7de1c5c10a | ||
|
fc32eb48c5 | ||
|
41bb2515ef | ||
|
dcf9a51b78 | ||
|
23d31b805a | ||
|
3b003dd5f0 | ||
|
9dfa1649ff | ||
|
c97e3a657b | ||
|
b88a8c9364 | ||
|
7a55ca34b9 | ||
|
b0d196c43c | ||
|
7b6f25c360 | ||
|
c01aa3fec4 | ||
|
1ba83ede44 | ||
|
7874992888 | ||
|
350aebf20a | ||
|
e91b1820dd | ||
|
ab4b4e95f6 | ||
|
e2016291f1 | ||
|
375fcdeadb | ||
|
1d647668af | ||
|
cd68bac78d | ||
|
1cb8ab8dc6 | ||
|
87ddca831a | ||
|
2f2e7f041a | ||
|
e55a552eee | ||
|
5f52f2a7f8 | ||
|
3de9ed6453 | ||
|
d01ad1a78d | ||
|
f2806aa9ab | ||
|
6539d101f3 | ||
|
a1a1b77150 | ||
|
4caca8b20c | ||
|
f2b86a25b3 | ||
|
dd854e47ba | ||
|
931ba89aad | ||
|
51f11929f3 | ||
|
5e94092263 | ||
|
3a0a3c540c | ||
|
998036654c | ||
|
0ae4eb4d26 | ||
|
a08bfd9891 |
@ -55,6 +55,7 @@ video tutorials.
|
|||||||
- Jason Daly
|
- Jason Daly
|
||||||
- danhambleton
|
- danhambleton
|
||||||
- Jarrod Davis
|
- Jarrod Davis
|
||||||
|
- decce
|
||||||
- Olivier Delannoy
|
- Olivier Delannoy
|
||||||
- Paul R. Deppe
|
- Paul R. Deppe
|
||||||
- Michael Dickens
|
- Michael Dickens
|
||||||
|
10
README.md
10
README.md
@ -121,6 +121,9 @@ 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)
|
||||||
- Updated minimum CMake version to 3.16 (#2541)
|
- Updated minimum CMake version to 3.16 (#2541)
|
||||||
@ -134,18 +137,21 @@ information on what to include when reporting a bug.
|
|||||||
- [Wayland] Bugfix: Ignore key repeat events when no window has keyboard focus (#2727)
|
- [Wayland] Bugfix: Ignore key repeat events when no window has keyboard focus (#2727)
|
||||||
- [Wayland] Bugfix: Reset key repeat timer when window destroyed (#2741,#2727)
|
- [Wayland] Bugfix: Reset key repeat timer when window destroyed (#2741,#2727)
|
||||||
- [Wayland] Bugfix: Memory would leak if reading a data offer failed midway
|
- [Wayland] Bugfix: Memory would leak if reading a data offer failed midway
|
||||||
- [Wayland] Bugfix: Keyboard leave event handler now processes key repeats (#2736)
|
|
||||||
- [Wayland] Bugfix: Retrieved cursor position would be incorrect when hovering over
|
- [Wayland] Bugfix: Retrieved cursor position would be incorrect when hovering over
|
||||||
fallback decorations
|
fallback decorations
|
||||||
- [Wayland] Bugfix: Fallback decorations would report scroll events
|
- [Wayland] Bugfix: Fallback decorations would report scroll events
|
||||||
- [Wayland] Bugfix: Keyboard repeat events halted when any key is released (#2568)
|
- [Wayland] Bugfix: Keyboard repeat events halted when any key is released (#2568)
|
||||||
|
- [Wayland] Bugfix: Fallback decorations would show menu at wrong position
|
||||||
|
- [Wayland] Bugfix: The cursor was not updated when clicking through from
|
||||||
|
a modal to a fallback decoration
|
||||||
|
- [Wayland] Bugfix: The cursor position was not updated when clicking through
|
||||||
|
from a modal to the content area
|
||||||
- [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631)
|
- [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631)
|
||||||
- [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface`
|
- [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface`
|
||||||
- [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`
|
- [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`
|
||||||
- [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
|
||||||
|
@ -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}
|
||||||
|
|
||||||
|
@ -255,3 +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
|
||||||
|
@ref glfwGetGammaRamp, @ref glfwSetGammaRamp and @ref glfwSetGamma functions
|
||||||
|
emit @ref GLFW_FEATURE_UNAVAILABLE.
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -893,6 +893,12 @@ int xpos, ypos;
|
|||||||
glfwGetWindowPos(window, &xpos, &ypos);
|
glfwGetWindowPos(window, &xpos, &ypos);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@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
|
||||||
|
window hints are ignored. The @ref glfwGetWindowPos and @ref glfwSetWindowPos
|
||||||
|
functions emit @ref GLFW_FEATURE_UNAVAILABLE. The window position callback will
|
||||||
|
not be called.
|
||||||
|
|
||||||
|
|
||||||
### Window title {#window_title}
|
### Window title {#window_title}
|
||||||
|
|
||||||
@ -1038,6 +1044,12 @@ 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
|
||||||
|
iconified or restore one from iconification. The @ref glfwRestoreWindow
|
||||||
|
function can only restore windows from maximization and the iconify callback
|
||||||
|
will not be called. The [GLFW_ICONIFIED](@ref GLFW_ICONIFIED_attrib) attribute
|
||||||
|
will be false. The @ref glfwIconifyWindow function works normally.
|
||||||
|
|
||||||
|
|
||||||
### Window maximization {#window_maximize}
|
### Window maximization {#window_maximize}
|
||||||
|
|
||||||
|
@ -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.
|
||||||
@ -2915,8 +2927,8 @@ 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 Gamma handling is a privileged protocol, this function
|
* @remark @wayland Monitor gamma is a privileged protocol, so this function
|
||||||
* will thus never 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,8 +2951,8 @@ 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 Gamma handling is a privileged protocol, this function
|
* @remark @wayland Monitor gamma is a privileged protocol, so this function
|
||||||
* will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE while
|
* cannot be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE while
|
||||||
* returning `NULL`.
|
* returning `NULL`.
|
||||||
*
|
*
|
||||||
* @pointer_lifetime The returned structure and its arrays are allocated and
|
* @pointer_lifetime The returned structure and its arrays are allocated and
|
||||||
@ -2983,8 +2995,8 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
|
|||||||
*
|
*
|
||||||
* @remark @win32 The gamma ramp size must be 256.
|
* @remark @win32 The gamma ramp size must be 256.
|
||||||
*
|
*
|
||||||
* @remark @wayland Gamma handling is a privileged protocol, this function
|
* @remark @wayland Monitor gamma is a privileged protocol, so this function
|
||||||
* will thus never 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
|
||||||
* returns.
|
* returns.
|
||||||
@ -3430,8 +3442,8 @@ 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 There is no way for an application to retrieve the global
|
* @remark @wayland Window positions are not currently part of any common
|
||||||
* position of its windows. This function will emit @ref
|
* Wayland protocol, so this function cannot be implemented and will emit @ref
|
||||||
* GLFW_FEATURE_UNAVAILABLE.
|
* 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.
|
||||||
@ -3464,8 +3476,8 @@ 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 There is no way for an application to set the global
|
* @remark @wayland Window positions are not currently part of any common
|
||||||
* position of its windows. This function will emit @ref
|
* Wayland protocol, so this function cannot be implemented and will emit @ref
|
||||||
* GLFW_FEATURE_UNAVAILABLE.
|
* 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.
|
||||||
@ -3807,10 +3819,6 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
|
|||||||
* @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 Once a window is iconified, @ref glfwRestoreWindow won’t
|
|
||||||
* be able to restore it. This is a design decision of the xdg-shell
|
|
||||||
* protocol.
|
|
||||||
*
|
|
||||||
* @thread_safety This function must only be called from the main thread.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref window_iconify
|
* @sa @ref window_iconify
|
||||||
@ -3838,6 +3846,10 @@ 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
|
||||||
|
* of any common Wayland protocol, so this function can only restore 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.
|
||||||
*
|
*
|
||||||
* @sa @ref window_iconify
|
* @sa @ref window_iconify
|
||||||
@ -4058,8 +4070,8 @@ 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 The desired window position is ignored, as there is no way
|
* @remark @wayland Window positions are not currently part of any common
|
||||||
* for an application to set this property.
|
* 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,8 +4108,9 @@ 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 The Wayland protocol provides no way to check whether a
|
* @remark @wayland Checking whether a window is iconified is not currently
|
||||||
* window is iconfied, so @ref GLFW_ICONIFIED always returns `GLFW_FALSE`.
|
* part of any common Wayland protocol, so the @ref GLFW_ICONIFIED attribute
|
||||||
|
* cannot be implemented and is always `GLFW_FALSE`.
|
||||||
*
|
*
|
||||||
* @thread_safety This function must only be called from the main thread.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
@ -4219,8 +4232,8 @@ 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 never be called, as there is no way for
|
* @remark @wayland This callback will not be called. The Wayland protocol
|
||||||
* an application to know its global position.
|
* 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.
|
||||||
*
|
*
|
||||||
@ -4395,6 +4408,10 @@ 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
|
||||||
|
* provides no way to be notified of when a window is iconified, and no way to
|
||||||
|
* check whether a window is currently iconified.
|
||||||
|
*
|
||||||
* @thread_safety This function must only be called from the main thread.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref window_iconify
|
* @sa @ref window_iconify
|
||||||
@ -6088,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.
|
||||||
*
|
*
|
||||||
@ -6115,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.
|
||||||
*
|
*
|
||||||
@ -6303,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
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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 //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -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);
|
||||||
|
}
|
@ -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 //////
|
||||||
|
@ -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,34 +585,56 @@ 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");
|
||||||
@ -670,6 +685,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 //////
|
||||||
|
@ -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;
|
||||||
|
@ -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*);
|
||||||
@ -525,6 +529,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 +778,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 +820,7 @@ struct _GLFWlibrary
|
|||||||
|
|
||||||
_GLFWtls errorSlot;
|
_GLFWtls errorSlot;
|
||||||
_GLFWtls contextSlot;
|
_GLFWtls contextSlot;
|
||||||
|
_GLFWtls usercontextSlot;
|
||||||
_GLFWmutex errorLock;
|
_GLFWmutex errorLock;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -842,6 +871,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 +1022,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 +1035,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);
|
||||||
|
@ -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 //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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 //////
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -405,13 +405,19 @@ static void handleFallbackDecorationButton(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
else if (button == BTN_RIGHT)
|
else if (button == BTN_RIGHT)
|
||||||
{
|
{
|
||||||
if (window->wl.xdg.toplevel)
|
if (!window->wl.xdg.toplevel)
|
||||||
{
|
return;
|
||||||
|
|
||||||
|
if (window->wl.fallback.focus != window->wl.fallback.top.surface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ypos < GLFW_BORDER_SIZE)
|
||||||
|
return;
|
||||||
|
|
||||||
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
|
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
|
||||||
_glfw.wl.seat, serial,
|
_glfw.wl.seat, serial,
|
||||||
window->wl.cursorPosX,
|
xpos,
|
||||||
window->wl.cursorPosY);
|
ypos - GLFW_CAPTION_HEIGHT - GLFW_BORDER_SIZE);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1532,11 +1538,21 @@ static void pointerHandleEnter(void* userData,
|
|||||||
window->wl.hovered = GLFW_TRUE;
|
window->wl.hovered = GLFW_TRUE;
|
||||||
_glfwSetCursorWayland(window, window->wl.currentCursor);
|
_glfwSetCursorWayland(window, window->wl.currentCursor);
|
||||||
_glfwInputCursorEnter(window, GLFW_TRUE);
|
_glfwInputCursorEnter(window, GLFW_TRUE);
|
||||||
|
|
||||||
|
if (window->cursorMode != GLFW_CURSOR_DISABLED)
|
||||||
|
{
|
||||||
|
window->wl.cursorPosX = wl_fixed_to_double(sx);
|
||||||
|
window->wl.cursorPosY = wl_fixed_to_double(sy);
|
||||||
|
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (window->wl.fallback.decorations)
|
if (window->wl.fallback.decorations)
|
||||||
|
{
|
||||||
window->wl.fallback.focus = surface;
|
window->wl.fallback.focus = surface;
|
||||||
|
updateFallbackDecorationCursor(window, sx, sy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3308,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 //////
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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 //////
|
||||||
|
@ -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
200
tests/usercontext.c
Normal 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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user