Compare commits

..

2 Commits

Author SHA1 Message Date
Camilla Löwy 413ba1dceb Wayland: Fix EGL buffer swap blocking indefinitely
This re-implements the wait for a surface frame that previously happened
inside EGL, so that we can add a reasonable timeout.  That allows
applications to make progress despite the window being suspended.

This initial implementation still has a race between glfwHideWindow and
glfwSwapBuffers when rendering on a separate thread.

Related to #1350
Related to #2582
Related to #2640
Related to #2719
Related to #2723
Related to #2800
2026-02-20 16:28:19 +01:00
Camilla Löwy e59b5e1fda Fix cleanup on success in threaded rendering test 2026-02-18 19:13:16 +01:00
31 changed files with 350 additions and 394 deletions
+3 -3
View File
@@ -17,7 +17,7 @@ jobs:
CC: clang
CFLAGS: -Werror
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt update
@@ -57,7 +57,7 @@ jobs:
MACOSX_DEPLOYMENT_TARGET: 10.11
CMAKE_OSX_ARCHITECTURES: x86_64;arm64
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- name: Configure Null shared library
run: cmake -B build-null-shared -D GLFW_BUILD_COCOA=OFF -D BUILD_SHARED_LIBS=ON
@@ -81,7 +81,7 @@ jobs:
env:
CFLAGS: /WX
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- name: Configure Win32 shared x86 library
run: cmake -B build-win32-shared-x86 -G "Visual Studio 17 2022" -A Win32 -D BUILD_SHARED_LIBS=ON
-4
View File
@@ -10,7 +10,6 @@ video tutorials.
- Matt Arsenault
- Takuro Ashie
- ashishgamedev
- avagordon01
- David Avedissian
- Luca Bacci
- Keith Bauer
@@ -57,7 +56,6 @@ video tutorials.
- Jason Daly
- danhambleton
- Jarrod Davis
- Aaron Day
- decce
- Olivier Delannoy
- Paul R. Deppe
@@ -77,7 +75,6 @@ video tutorials.
- Nikita Fediuchin
- Felipe Ferreira
- Michael Fogleman
- Folling
- forworldm
- Jason Francis
- Gerald Franz
@@ -164,7 +161,6 @@ video tutorials.
- Bryce Mehring
- Jonathan Mercier
- Marcel Metz
- Lucas Michaudel
- Liam Middlebrook
- mightgoyardstill
- Mihail
+1 -4
View File
@@ -152,11 +152,8 @@ information on what to include when reporting a bug.
- [Wayland] Bugfix: The `libwayland-client` library was not unloaded at termination
- [Wayland] Bugfix: Scroll events were sent twice on some versions of GNOME (#2494)
- [Wayland] Bugfix: Two-dimensional scroll input was emitted as separate axes
- [Wayland] Bugfix: Mouse wheel scroll distance was incorrect on some compositors
- [Wayland] Bugfix: `glfwSwapBuffers` would halt with nonzero swap interval when window
was suspended (#1350,#2582,#2640,#2719,#2723,#2800,#2827)
- [Wayland] Bugfix: `glfwPostEmptyEvent` would leak a callback proxy (#2836)
- [Wayland] Bugfix: `glfwHideWindow` did not always send its request immediately
was suspended (#1350,#2582,#2640,#2719,#2723,#2800)
- [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631)
- [X11] Bugfix: Occasional crash when an idle display awakes (#2766)
- [X11] Bugfix: Prevent BadWindow when creating small windows with a content scale
-8
View File
@@ -1344,10 +1344,6 @@ extern "C" {
#define GLFW_PLATFORM_NULL 0x00060005
/*! @} */
/* Reserved platform define for external Emscripten ports: 0x00060006
* See https://github.com/pongasoft/emscripten-glfw
*/
#define GLFW_DONT_CARE -1
@@ -6174,10 +6170,6 @@ GLFWAPI GLFWwindow* glfwGetCurrentContext(void);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
*
* @remark __Wayland:__ When the swap interval is greater than zero and the
* window is not in view, this function may take a few extra milliseconds to
* return.
*
* @remark __EGL:__ The context of the specified window must be current on the
* calling thread.
*
+5 -10
View File
@@ -10,7 +10,7 @@ add_library(glfw ${GLFW_LIBRARY_TYPE}
# The time, thread and module code is shared between all backends on a given OS,
# including the null backend, which still needs those bits to be functional
if (APPLE)
target_sources(glfw PRIVATE macos_time.h macos_time.c posix_thread.h
target_sources(glfw PRIVATE cocoa_time.h cocoa_time.c posix_thread.h
posix_module.c posix_thread.c)
elseif (WIN32)
target_sources(glfw PRIVATE win32_time.h win32_thread.h win32_module.c
@@ -46,7 +46,7 @@ endif()
if (GLFW_BUILD_X11)
target_compile_definitions(glfw PRIVATE _GLFW_X11)
target_sources(glfw PRIVATE x11_platform.h x11_init.c
target_sources(glfw PRIVATE x11_platform.h xkb_unicode.h x11_init.c
x11_monitor.c x11_window.c xkb_unicode.c
glx_context.c)
endif()
@@ -145,11 +145,11 @@ endif()
if (GLFW_BUILD_COCOA)
target_link_libraries(glfw PRIVATE "-framework Cocoa"
"-framework IOKit"
"-framework CoreFoundation"
"-framework QuartzCore")
list(APPEND glfw_PKG_LIBS "-framework Cocoa"
"-framework IOKit"
"-framework QuartzCore")
set(glfw_PKG_DEPS "")
set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation -framework QuartzCore")
endif()
if (GLFW_BUILD_WAYLAND)
@@ -234,11 +234,6 @@ if (UNIX AND NOT APPLE)
endif()
endif()
if (APPLE)
target_link_libraries(glfw PRIVATE "-framework CoreFoundation")
list(APPEND glfw_PKG_LIBS "-framework CoreFoundation")
endif()
if (WIN32)
if (GLFW_USE_HYBRID_HPG)
target_compile_definitions(glfw PRIVATE _GLFW_USE_HYBRID_HPG)
+36 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Cocoa - www.glfw.org
// GLFW 3.5 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
//
@@ -450,6 +450,41 @@ static GLFWbool initializeTIS(void)
@end // GLFWApplicationDelegate
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
void* _glfwLoadLocalVulkanLoaderCocoa(void)
{
CFBundleRef bundle = CFBundleGetMainBundle();
if (!bundle)
return NULL;
CFURLRef frameworksUrl = CFBundleCopyPrivateFrameworksURL(bundle);
if (!frameworksUrl)
return NULL;
CFURLRef loaderUrl = CFURLCreateCopyAppendingPathComponent(
kCFAllocatorDefault, frameworksUrl, CFSTR("libvulkan.1.dylib"), false);
if (!loaderUrl)
{
CFRelease(frameworksUrl);
return NULL;
}
char path[PATH_MAX];
void* handle = NULL;
if (CFURLGetFileSystemRepresentation(loaderUrl, true, (UInt8*) path, sizeof(path) - 1))
handle = _glfwPlatformLoadModule(path);
CFRelease(loaderUrl);
CFRelease(frameworksUrl);
return handle;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Cocoa - www.glfw.org
// GLFW 3.5 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
+3 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Cocoa - www.glfw.org
// GLFW 3.5 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
//
@@ -291,6 +291,8 @@ void _glfwRestoreVideoModeCocoa(_GLFWmonitor* monitor);
float _glfwTransformYCocoa(float y);
void* _glfwLoadLocalVulkanLoaderCocoa(void);
GLFWbool _glfwInitNSGL(void);
void _glfwTerminateNSGL(void);
GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
+4 -4
View File
@@ -26,7 +26,7 @@
#include "internal.h"
#if defined(GLFW_BUILD_MACOS_TIMER)
#if defined(GLFW_BUILD_COCOA_TIMER)
#include <mach/mach_time.h>
@@ -40,7 +40,7 @@ void _glfwPlatformInitTimer(void)
mach_timebase_info_data_t info;
mach_timebase_info(&info);
_glfw.timer.macos.frequency = (info.denom * 1e9) / info.numer;
_glfw.timer.ns.frequency = (info.denom * 1e9) / info.numer;
}
uint64_t _glfwPlatformGetTimerValue(void)
@@ -50,8 +50,8 @@ uint64_t _glfwPlatformGetTimerValue(void)
uint64_t _glfwPlatformGetTimerFrequency(void)
{
return _glfw.timer.macos.frequency;
return _glfw.timer.ns.frequency;
}
#endif // GLFW_BUILD_MACOS_TIMER
#endif // GLFW_BUILD_COCOA_TIMER
+4 -4
View File
@@ -24,12 +24,12 @@
//
//========================================================================
#define GLFW_MACOS_LIBRARY_TIMER_STATE _GLFWtimerMacOS macos;
#define GLFW_COCOA_LIBRARY_TIMER_STATE _GLFWtimerNS ns;
// macOS-specific global timer data
// Cocoa-specific global timer data
//
typedef struct _GLFWtimerMacOS
typedef struct _GLFWtimerNS
{
uint64_t frequency;
} _GLFWtimerMacOS;
} _GLFWtimerNS;
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Cocoa - www.glfw.org
// GLFW 3.5 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
//
+1 -1
View File
@@ -195,7 +195,7 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
{
current = alternatives + i;
if (desired->stereo && !current->stereo)
if (desired->stereo > 0 && current->stereo == 0)
{
// Stereo is a hard constraint
continue;
+1 -2
View File
@@ -32,7 +32,6 @@
#include <stdlib.h>
#include <assert.h>
// Return a description of the specified EGL error
//
static const char* getEGLErrorString(EGLint error)
@@ -675,7 +674,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
if (ctxconfig->noerror)
{
if (_glfw.egl.KHR_create_context_no_error)
SET_ATTRIB(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, true);
SET_ATTRIB(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
}
if (mask)
+15 -13
View File
@@ -119,7 +119,9 @@ static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
u->accumAlphaBits = getGLXFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE);
u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
u->stereo = getGLXFBConfigAttrib(n, GLX_STEREO);
if (getGLXFBConfigAttrib(n, GLX_STEREO))
u->stereo = GLFW_TRUE;
if (_glfw.glx.ARB_multisample)
u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES);
@@ -365,7 +367,7 @@ GLFWbool _glfwInitGLX(void)
getProcAddressGLX("glXSwapIntervalEXT");
if (_glfw.glx.SwapIntervalEXT)
_glfw.glx.EXT_swap_control = true;
_glfw.glx.EXT_swap_control = GLFW_TRUE;
}
if (extensionSupportedGLX("GLX_SGI_swap_control"))
@@ -374,7 +376,7 @@ GLFWbool _glfwInitGLX(void)
getProcAddressGLX("glXSwapIntervalSGI");
if (_glfw.glx.SwapIntervalSGI)
_glfw.glx.SGI_swap_control = true;
_glfw.glx.SGI_swap_control = GLFW_TRUE;
}
if (extensionSupportedGLX("GLX_MESA_swap_control"))
@@ -383,17 +385,17 @@ GLFWbool _glfwInitGLX(void)
getProcAddressGLX("glXSwapIntervalMESA");
if (_glfw.glx.SwapIntervalMESA)
_glfw.glx.MESA_swap_control = true;
_glfw.glx.MESA_swap_control = GLFW_TRUE;
}
if (extensionSupportedGLX("GLX_ARB_multisample"))
_glfw.glx.ARB_multisample = true;
_glfw.glx.ARB_multisample = GLFW_TRUE;
if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB"))
_glfw.glx.ARB_framebuffer_sRGB = true;
_glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE;
if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB"))
_glfw.glx.EXT_framebuffer_sRGB = true;
_glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE;
if (extensionSupportedGLX("GLX_ARB_create_context"))
{
@@ -401,23 +403,23 @@ GLFWbool _glfwInitGLX(void)
getProcAddressGLX("glXCreateContextAttribsARB");
if (_glfw.glx.CreateContextAttribsARB)
_glfw.glx.ARB_create_context = true;
_glfw.glx.ARB_create_context = GLFW_TRUE;
}
if (extensionSupportedGLX("GLX_ARB_create_context_robustness"))
_glfw.glx.ARB_create_context_robustness = true;
_glfw.glx.ARB_create_context_robustness = GLFW_TRUE;
if (extensionSupportedGLX("GLX_ARB_create_context_profile"))
_glfw.glx.ARB_create_context_profile = true;
_glfw.glx.ARB_create_context_profile = GLFW_TRUE;
if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
_glfw.glx.EXT_create_context_es2_profile = true;
_glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE;
if (extensionSupportedGLX("GLX_ARB_create_context_no_error"))
_glfw.glx.ARB_create_context_no_error = true;
_glfw.glx.ARB_create_context_no_error = GLFW_TRUE;
if (extensionSupportedGLX("GLX_ARB_context_flush_control"))
_glfw.glx.ARB_context_flush_control = true;
_glfw.glx.ARB_context_flush_control = GLFW_TRUE;
return GLFW_TRUE;
}
+4 -4
View File
@@ -49,18 +49,18 @@ static GLFWerrorfun _glfwErrorCallback;
static GLFWallocator _glfwInitAllocator;
static _GLFWinitconfig _glfwInitHints =
{
.hatButtons = true,
.hatButtons = GLFW_TRUE,
.angleType = GLFW_ANGLE_PLATFORM_TYPE_NONE,
.platformID = GLFW_ANY_PLATFORM,
.vulkanLoader = NULL,
.ns =
{
.menubar = true,
.chdir = true
.menubar = GLFW_TRUE,
.chdir = GLFW_TRUE
},
.x11 =
{
.xcbVulkanSurface = true,
.xcbVulkanSurface = GLFW_TRUE,
},
.wl =
{
+11 -7
View File
@@ -333,8 +333,10 @@ void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
{
assert(window != NULL);
assert(isfinite(xoffset));
assert(isfinite(yoffset));
assert(xoffset > -FLT_MAX);
assert(xoffset < FLT_MAX);
assert(yoffset > -FLT_MAX);
assert(yoffset < FLT_MAX);
if (window->callbacks.scroll)
window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
@@ -373,8 +375,10 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
{
assert(window != NULL);
assert(isfinite(xpos));
assert(isfinite(ypos));
assert(xpos > -FLT_MAX);
assert(xpos < FLT_MAX);
assert(ypos > -FLT_MAX);
assert(ypos < FLT_MAX);
if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
return;
@@ -432,7 +436,6 @@ void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
assert(js != NULL);
assert(axis >= 0);
assert(axis < js->axisCount);
assert(isfinite(value));
js->axes[axis] = value;
}
@@ -815,7 +818,8 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (!isfinite(xpos) || !isfinite(ypos))
if (xpos != xpos || xpos < -DBL_MAX || xpos > DBL_MAX ||
ypos != ypos || ypos < -DBL_MAX || ypos > DBL_MAX)
{
_glfwInputError(GLFW_INVALID_VALUE,
"Invalid cursor position %f %f",
@@ -1495,7 +1499,7 @@ GLFWAPI void glfwSetTime(double time)
{
_GLFW_REQUIRE_INIT();
if (!isfinite(time) || time < 0.0 || time > 18446744073.0)
if (time != time || time < 0.0 || time > 18446744073.0)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time);
return;
+50 -50
View File
@@ -375,16 +375,16 @@ struct _GLFWerror
//
struct _GLFWinitconfig
{
bool hatButtons;
GLFWbool hatButtons;
int angleType;
int platformID;
PFN_vkGetInstanceProcAddr vulkanLoader;
struct {
bool menubar;
bool chdir;
GLFWbool menubar;
GLFWbool chdir;
} ns;
struct {
bool xcbVulkanSurface;
GLFWbool xcbVulkanSurface;
} x11;
struct {
int libdecorMode;
@@ -403,18 +403,18 @@ struct _GLFWwndconfig
int ypos;
int width;
int height;
bool resizable;
bool visible;
bool decorated;
bool focused;
bool autoIconify;
bool floating;
bool maximized;
bool centerCursor;
bool focusOnShow;
bool mousePassthrough;
bool scaleToMonitor;
bool scaleFramebuffer;
GLFWbool resizable;
GLFWbool visible;
GLFWbool decorated;
GLFWbool focused;
GLFWbool autoIconify;
GLFWbool floating;
GLFWbool maximized;
GLFWbool centerCursor;
GLFWbool focusOnShow;
GLFWbool mousePassthrough;
GLFWbool scaleToMonitor;
GLFWbool scaleFramebuffer;
struct {
char frameName[256];
} ns;
@@ -423,8 +423,8 @@ struct _GLFWwndconfig
char instanceName[256];
} x11;
struct {
bool keymenu;
bool showDefault;
GLFWbool keymenu;
GLFWbool showDefault;
} win32;
struct {
char appId[256];
@@ -443,15 +443,15 @@ struct _GLFWctxconfig
int source;
int major;
int minor;
bool forward;
bool debug;
bool noerror;
GLFWbool forward;
GLFWbool debug;
GLFWbool noerror;
int profile;
int robustness;
int release;
_GLFWwindow* share;
struct {
bool offline;
GLFWbool offline;
} nsgl;
};
@@ -476,11 +476,11 @@ struct _GLFWfbconfig
int accumBlueBits;
int accumAlphaBits;
int auxBuffers;
bool stereo;
GLFWbool stereo;
int samples;
bool sRGB;
bool doublebuffer;
bool transparent;
GLFWbool sRGB;
GLFWbool doublebuffer;
GLFWbool transparent;
uintptr_t handle;
};
@@ -807,22 +807,22 @@ struct _GLFWlibrary
EGLint major, minor;
GLFWbool prefix;
bool KHR_create_context;
bool KHR_create_context_no_error;
bool KHR_gl_colorspace;
bool KHR_get_all_proc_addresses;
bool KHR_context_flush_control;
bool EXT_client_extensions;
bool EXT_platform_base;
bool EXT_platform_x11;
bool EXT_platform_wayland;
bool EXT_present_opaque;
bool ANGLE_platform_angle;
bool ANGLE_platform_angle_opengl;
bool ANGLE_platform_angle_d3d;
bool ANGLE_platform_angle_vulkan;
bool ANGLE_platform_angle_metal;
bool MESA_platform_surfaceless;
GLFWbool KHR_create_context;
GLFWbool KHR_create_context_no_error;
GLFWbool KHR_gl_colorspace;
GLFWbool KHR_get_all_proc_addresses;
GLFWbool KHR_context_flush_control;
GLFWbool EXT_client_extensions;
GLFWbool EXT_platform_base;
GLFWbool EXT_platform_x11;
GLFWbool EXT_platform_wayland;
GLFWbool EXT_present_opaque;
GLFWbool ANGLE_platform_angle;
GLFWbool ANGLE_platform_angle_opengl;
GLFWbool ANGLE_platform_angle_d3d;
GLFWbool ANGLE_platform_angle_vulkan;
GLFWbool ANGLE_platform_angle_metal;
GLFWbool MESA_platform_surfaceless;
void* handle;
@@ -866,14 +866,14 @@ struct _GLFWlibrary
void* handle;
char* extensions[2];
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
bool KHR_surface;
bool KHR_win32_surface;
bool MVK_macos_surface;
bool EXT_metal_surface;
bool KHR_xlib_surface;
bool KHR_xcb_surface;
bool KHR_wayland_surface;
bool EXT_headless_surface;
GLFWbool KHR_surface;
GLFWbool KHR_win32_surface;
GLFWbool MVK_macos_surface;
GLFWbool EXT_metal_surface;
GLFWbool KHR_xlib_surface;
GLFWbool KHR_xcb_surface;
GLFWbool KHR_wayland_surface;
GLFWbool EXT_headless_surface;
} vk;
struct {
+2 -3
View File
@@ -467,15 +467,14 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
unsigned short* values;
GLFWgammaramp ramp;
const GLFWgammaramp* original;
assert(gamma > 0.f);
assert(isfinite(gamma));
assert(gamma <= FLT_MAX);
_GLFW_REQUIRE_INIT();
assert(handle != NULL);
if (!isfinite(gamma) || gamma <= 0.f)
if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
return;
+5 -6
View File
@@ -28,7 +28,7 @@
#if defined(GLFW_BUILD_WIN32_TIMER) || \
defined(GLFW_BUILD_WIN32_MODULE) || \
defined(GLFW_BUILD_WIN32_THREAD) || \
defined(GLFW_BUILD_MACOS_TIMER) || \
defined(GLFW_BUILD_COCOA_TIMER) || \
defined(GLFW_BUILD_POSIX_TIMER) || \
defined(GLFW_BUILD_POSIX_MODULE) || \
defined(GLFW_BUILD_POSIX_THREAD) || \
@@ -184,7 +184,7 @@
#if defined(_WIN32)
#define GLFW_BUILD_WIN32_TIMER
#elif defined(__APPLE__)
#define GLFW_BUILD_MACOS_TIMER
#define GLFW_BUILD_COCOA_TIMER
#else
#define GLFW_BUILD_POSIX_TIMER
#endif
@@ -192,9 +192,9 @@
#if defined(GLFW_BUILD_WIN32_TIMER)
#include "win32_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_WIN32_LIBRARY_TIMER_STATE
#elif defined(GLFW_BUILD_MACOS_TIMER)
#include "macos_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_MACOS_LIBRARY_TIMER_STATE
#elif defined(GLFW_BUILD_COCOA_TIMER)
#include "cocoa_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_COCOA_LIBRARY_TIMER_STATE
#elif defined(GLFW_BUILD_POSIX_TIMER)
#include "posix_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_POSIX_LIBRARY_TIMER_STATE
@@ -207,7 +207,6 @@
#endif
#if defined(_GLFW_WAYLAND) || defined(_GLFW_X11)
#include "posix_poll.h"
#define GLFW_BUILD_POSIX_POLL
#endif
+11 -44
View File
@@ -34,40 +34,6 @@
#define _GLFW_FIND_LOADER 1
#define _GLFW_REQUIRE_LOADER 2
#if defined(__APPLE__)
#include <CoreFoundation/CoreFoundation.h>
static void* loadLocalVulkanLoaderMacOS(void)
{
CFBundleRef bundle = CFBundleGetMainBundle();
if (!bundle)
return NULL;
CFURLRef frameworksUrl = CFBundleCopyPrivateFrameworksURL(bundle);
if (!frameworksUrl)
return NULL;
CFURLRef loaderUrl = CFURLCreateCopyAppendingPathComponent(
kCFAllocatorDefault, frameworksUrl, CFSTR("libvulkan.1.dylib"), false);
if (!loaderUrl)
{
CFRelease(frameworksUrl);
return NULL;
}
char path[PATH_MAX];
void* handle = NULL;
if (CFURLGetFileSystemRepresentation(loaderUrl, true, (UInt8*) path, sizeof(path) - 1))
handle = _glfwPlatformLoadModule(path);
CFRelease(loaderUrl);
CFRelease(frameworksUrl);
return handle;
}
#endif // __APPLE__
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
@@ -91,10 +57,11 @@ GLFWbool _glfwInitVulkan(int mode)
_glfw.vk.handle = _glfwPlatformLoadModule(_GLFW_VULKAN_LIBRARY);
#elif defined(_WIN32)
_glfw.vk.handle = _glfwPlatformLoadModule("vulkan-1.dll");
#elif defined(__APPLE__)
#elif defined(_GLFW_COCOA)
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib");
if (!_glfw.vk.handle)
_glfw.vk.handle = loadLocalVulkanLoaderMacOS();
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa();
#elif defined(__APPLE__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so");
#else
@@ -163,21 +130,21 @@ GLFWbool _glfwInitVulkan(int mode)
for (i = 0; i < count; i++)
{
if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
_glfw.vk.KHR_surface = true;
_glfw.vk.KHR_surface = GLFW_TRUE;
else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
_glfw.vk.KHR_win32_surface = true;
_glfw.vk.KHR_win32_surface = GLFW_TRUE;
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
_glfw.vk.MVK_macos_surface = true;
_glfw.vk.MVK_macos_surface = GLFW_TRUE;
else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0)
_glfw.vk.EXT_metal_surface = true;
_glfw.vk.EXT_metal_surface = GLFW_TRUE;
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
_glfw.vk.KHR_xlib_surface = true;
_glfw.vk.KHR_xlib_surface = GLFW_TRUE;
else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
_glfw.vk.KHR_xcb_surface = true;
_glfw.vk.KHR_xcb_surface = GLFW_TRUE;
else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
_glfw.vk.KHR_wayland_surface = true;
_glfw.vk.KHR_wayland_surface = GLFW_TRUE;
else if (strcmp(ep[i].extensionName, "VK_EXT_headless_surface") == 0)
_glfw.vk.EXT_headless_surface = true;
_glfw.vk.EXT_headless_surface = GLFW_TRUE;
}
_glfw_free(ep);
+14 -6
View File
@@ -186,22 +186,28 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
u->accumAlphaBits = FIND_ATTRIB_VALUE(WGL_ACCUM_ALPHA_BITS_ARB);
u->auxBuffers = FIND_ATTRIB_VALUE(WGL_AUX_BUFFERS_ARB);
u->stereo = FIND_ATTRIB_VALUE(WGL_STEREO_ARB);
if (FIND_ATTRIB_VALUE(WGL_STEREO_ARB))
u->stereo = GLFW_TRUE;
if (_glfw.wgl.ARB_multisample)
u->samples = FIND_ATTRIB_VALUE(WGL_SAMPLES_ARB);
if (ctxconfig->client == GLFW_OPENGL_API)
{
if (_glfw.wgl.ARB_framebuffer_sRGB || _glfw.wgl.EXT_framebuffer_sRGB)
u->sRGB = FIND_ATTRIB_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
if (_glfw.wgl.ARB_framebuffer_sRGB ||
_glfw.wgl.EXT_framebuffer_sRGB)
{
if (FIND_ATTRIB_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
u->sRGB = GLFW_TRUE;
}
}
else
{
if (_glfw.wgl.EXT_colorspace)
{
if (FIND_ATTRIB_VALUE(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT)
u->sRGB = true;
u->sRGB = GLFW_TRUE;
}
}
}
@@ -255,7 +261,9 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
u->accumAlphaBits = pfd.cAccumAlphaBits;
u->auxBuffers = pfd.cAuxBuffers;
u->stereo = (pfd.dwFlags & PFD_STEREO);
if (pfd.dwFlags & PFD_STEREO)
u->stereo = GLFW_TRUE;
}
u->handle = pixelFormat;
@@ -656,7 +664,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
if (ctxconfig->noerror)
{
if (_glfw.wgl.ARB_create_context_no_error)
SET_ATTRIB(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, true);
SET_ATTRIB(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
}
// NOTE: Only request an explicitly versioned context when necessary, as
+12 -12
View File
@@ -336,18 +336,18 @@ typedef struct _GLFWlibraryWGL
PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
bool EXT_swap_control;
bool EXT_colorspace;
bool ARB_multisample;
bool ARB_framebuffer_sRGB;
bool EXT_framebuffer_sRGB;
bool ARB_pixel_format;
bool ARB_create_context;
bool ARB_create_context_profile;
bool EXT_create_context_es2_profile;
bool ARB_create_context_robustness;
bool ARB_create_context_no_error;
bool ARB_context_flush_control;
GLFWbool EXT_swap_control;
GLFWbool EXT_colorspace;
GLFWbool ARB_multisample;
GLFWbool ARB_framebuffer_sRGB;
GLFWbool EXT_framebuffer_sRGB;
GLFWbool ARB_pixel_format;
GLFWbool ARB_create_context;
GLFWbool ARB_create_context_profile;
GLFWbool EXT_create_context_es2_profile;
GLFWbool ARB_create_context_robustness;
GLFWbool ARB_create_context_no_error;
GLFWbool ARB_context_flush_control;
} _GLFWlibraryWGL;
// Win32-specific per-window data
+39 -38
View File
@@ -32,7 +32,7 @@
#include <string.h>
#include <stdlib.h>
#include <float.h>
#include <math.h>
//////////////////////////////////////////////////////////////////////////
////// GLFW event API //////
@@ -135,9 +135,9 @@ void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscal
{
assert(window != NULL);
assert(xscale > 0.f);
assert(isfinite(xscale));
assert(xscale < FLT_MAX);
assert(yscale > 0.f);
assert(isfinite(yscale));
assert(yscale < FLT_MAX);
if (window->callbacks.scale)
window->callbacks.scale((GLFWwindow*) window, xscale, yscale);
@@ -265,16 +265,16 @@ void glfwDefaultWindowHints(void)
// The default is a focused, visible, resizable window with decorations
memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
_glfw.hints.window.resizable = true;
_glfw.hints.window.visible = true;
_glfw.hints.window.decorated = true;
_glfw.hints.window.focused = true;
_glfw.hints.window.autoIconify = true;
_glfw.hints.window.centerCursor = true;
_glfw.hints.window.focusOnShow = true;
_glfw.hints.window.resizable = GLFW_TRUE;
_glfw.hints.window.visible = GLFW_TRUE;
_glfw.hints.window.decorated = GLFW_TRUE;
_glfw.hints.window.focused = GLFW_TRUE;
_glfw.hints.window.autoIconify = GLFW_TRUE;
_glfw.hints.window.centerCursor = GLFW_TRUE;
_glfw.hints.window.focusOnShow = GLFW_TRUE;
_glfw.hints.window.xpos = GLFW_ANY_POSITION;
_glfw.hints.window.ypos = GLFW_ANY_POSITION;
_glfw.hints.window.scaleFramebuffer = true;
_glfw.hints.window.scaleFramebuffer = GLFW_TRUE;
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
// double buffered
@@ -285,7 +285,7 @@ void glfwDefaultWindowHints(void)
_glfw.hints.framebuffer.alphaBits = 8;
_glfw.hints.framebuffer.depthBits = 24;
_glfw.hints.framebuffer.stencilBits = 8;
_glfw.hints.framebuffer.doublebuffer = true;
_glfw.hints.framebuffer.doublebuffer = GLFW_TRUE;
// The default is to select the highest available refresh rate
_glfw.hints.refreshRate = GLFW_DONT_CARE;
@@ -331,40 +331,40 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfw.hints.framebuffer.auxBuffers = value;
return;
case GLFW_STEREO:
_glfw.hints.framebuffer.stereo = value;
_glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_DOUBLEBUFFER:
_glfw.hints.framebuffer.doublebuffer = value;
_glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_TRANSPARENT_FRAMEBUFFER:
_glfw.hints.framebuffer.transparent = value;
_glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_SAMPLES:
_glfw.hints.framebuffer.samples = value;
return;
case GLFW_SRGB_CAPABLE:
_glfw.hints.framebuffer.sRGB = value;
_glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_RESIZABLE:
_glfw.hints.window.resizable = value;
_glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_DECORATED:
_glfw.hints.window.decorated = value;
_glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_FOCUSED:
_glfw.hints.window.focused = value;
_glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_AUTO_ICONIFY:
_glfw.hints.window.autoIconify = value;
_glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_FLOATING:
_glfw.hints.window.floating = value;
_glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_MAXIMIZED:
_glfw.hints.window.maximized = value;
_glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_VISIBLE:
_glfw.hints.window.visible = value;
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_POSITION_X:
_glfw.hints.window.xpos = value;
@@ -373,29 +373,29 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfw.hints.window.ypos = value;
return;
case GLFW_WIN32_KEYBOARD_MENU:
_glfw.hints.window.win32.keymenu = value;
_glfw.hints.window.win32.keymenu = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_WIN32_SHOWDEFAULT:
_glfw.hints.window.win32.showDefault = value;
_glfw.hints.window.win32.showDefault = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_COCOA_GRAPHICS_SWITCHING:
_glfw.hints.context.nsgl.offline = value;
_glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_SCALE_TO_MONITOR:
_glfw.hints.window.scaleToMonitor = value;
_glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_SCALE_FRAMEBUFFER:
case GLFW_COCOA_RETINA_FRAMEBUFFER:
_glfw.hints.window.scaleFramebuffer = value;
_glfw.hints.window.scaleFramebuffer = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_CENTER_CURSOR:
_glfw.hints.window.centerCursor = value;
_glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_FOCUS_ON_SHOW:
_glfw.hints.window.focusOnShow = value;
_glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_MOUSE_PASSTHROUGH:
_glfw.hints.window.mousePassthrough = value;
_glfw.hints.window.mousePassthrough = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_CLIENT_API:
_glfw.hints.context.client = value;
@@ -413,13 +413,13 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfw.hints.context.robustness = value;
return;
case GLFW_OPENGL_FORWARD_COMPAT:
_glfw.hints.context.forward = value;
_glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_CONTEXT_DEBUG:
_glfw.hints.context.debug = value;
_glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_CONTEXT_NO_ERROR:
_glfw.hints.context.noerror = value;
_glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_OPENGL_PROFILE:
_glfw.hints.context.profile = value;
@@ -776,7 +776,7 @@ GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle)
GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
{
assert(isfinite(opacity));
assert(opacity == opacity);
assert(opacity >= 0.f);
assert(opacity <= 1.f);
@@ -785,7 +785,7 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (!isfinite(opacity) || opacity < 0.f || opacity > 1.f)
if (opacity != opacity || opacity < 0.f || opacity > 1.f)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity);
return;
@@ -1178,10 +1178,11 @@ GLFWAPI void glfwWaitEvents(void)
GLFWAPI void glfwWaitEventsTimeout(double timeout)
{
_GLFW_REQUIRE_INIT();
assert(isfinite(timeout));
assert(timeout == timeout);
assert(timeout >= 0.0);
assert(timeout <= DBL_MAX);
if (!isfinite(timeout) || timeout < 0.0)
if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", timeout);
return;
+9 -4
View File
@@ -135,7 +135,7 @@ static void registryHandleGlobal(void* userData,
{
_glfw.wl.seat =
wl_registry_bind(registry, name, &wl_seat_interface,
_glfw_min(8, version));
_glfw_min(5, version));
_glfwAddSeatListenerWayland(_glfw.wl.seat);
}
}
@@ -244,7 +244,10 @@ static void libdecorReadyCallback(void* userData,
uint32_t time)
{
_glfw.wl.libdecor.ready = GLFW_TRUE;
wl_callback_destroy(callback);
assert(_glfw.wl.libdecor.callback == callback);
wl_callback_destroy(_glfw.wl.libdecor.callback);
_glfw.wl.libdecor.callback = NULL;
}
static const struct wl_callback_listener libdecorReadyListener =
@@ -878,8 +881,10 @@ int _glfwInitWayland(void)
libdecor_dispatch(_glfw.wl.libdecor.context, 0);
// Create sync point to "know" when libdecor is ready for use
struct wl_callback* callback = wl_display_sync(_glfw.wl.display);
wl_callback_add_listener(callback, &libdecorReadyListener, NULL);
_glfw.wl.libdecor.callback = wl_display_sync(_glfw.wl.display);
wl_callback_add_listener(_glfw.wl.libdecor.callback,
&libdecorReadyListener,
NULL);
}
}
+3 -2
View File
@@ -42,6 +42,8 @@ typedef struct VkWaylandSurfaceCreateInfoKHR
typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWaylandSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
#include "posix_poll.h"
typedef int (* PFN_wl_display_flush)(struct wl_display* display);
typedef void (* PFN_wl_display_cancel_read)(struct wl_display* display);
typedef int (* PFN_wl_display_dispatch_pending)(struct wl_display* display);
@@ -496,8 +498,6 @@ typedef struct _GLFWlibraryWayland
double pointerY;
double scrollX;
double scrollY;
double discreteX;
double discreteY;
int button;
int action;
} pending;
@@ -595,6 +595,7 @@ typedef struct _GLFWlibraryWayland
struct {
void* handle;
struct libdecor* context;
struct wl_callback* callback;
GLFWbool ready;
PFN_libdecor_new libdecor_new_;
PFN_libdecor_unref libdecor_unref_;
+35 -66
View File
@@ -55,11 +55,10 @@
#define GLFW_BORDER_SIZE 4
#define GLFW_CAPTION_HEIGHT 24
#define GLFW_PENDING_SURFACE 1
#define GLFW_PENDING_BUTTON 2
#define GLFW_PENDING_MOTION 4
#define GLFW_PENDING_SCROLL 8
#define GLFW_PENDING_DISCRETE 16
#define GLFW_PENDING_SURFACE 1
#define GLFW_PENDING_BUTTON 2
#define GLFW_PENDING_MOTION 4
#define GLFW_PENDING_SCROLL 8
static int createTmpfileCloexec(char* tmpname)
{
@@ -199,16 +198,6 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
return buffer;
}
static void callbackHandleDone(void* userData, struct wl_callback* callback, uint32_t data)
{
wl_callback_destroy(callback);
}
static const struct wl_callback_listener noopCallbackListener =
{
callbackHandleDone
};
static void createFallbackEdge(_GLFWwindow* window,
_GLFWfallbackEdgeWayland* edge,
struct wl_surface* parent,
@@ -1751,9 +1740,7 @@ static void pointerHandleFrame(void* userData, struct wl_pointer* pointer)
if (_glfw.wl.pending.events & GLFW_PENDING_BUTTON)
processPointerButton(_glfw.wl.pending.button, _glfw.wl.pending.action);
if (_glfw.wl.pending.events & GLFW_PENDING_DISCRETE)
processPointerScroll(_glfw.wl.pending.discreteX, _glfw.wl.pending.discreteY);
else if (_glfw.wl.pending.events & GLFW_PENDING_SCROLL)
if (_glfw.wl.pending.events & GLFW_PENDING_SCROLL)
processPointerScroll(_glfw.wl.pending.scrollX, _glfw.wl.pending.scrollY);
memset(&_glfw.wl.pending, 0, sizeof(_glfw.wl.pending));
@@ -1779,21 +1766,6 @@ static void pointerHandleAxisDiscrete(void* userData,
{
}
static void pointerHandleAxisValue120(void* data,
struct wl_pointer* pointer,
uint32_t axis,
int32_t value120)
{
if (!_glfw.wl.pointerSurface)
return;
_glfw.wl.pending.events |= GLFW_PENDING_DISCRETE;
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
_glfw.wl.pending.discreteX = -(value120 / 120.0);
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
_glfw.wl.pending.discreteY = -(value120 / 120.0);
}
static const struct wl_pointer_listener pointerListener =
{
pointerHandleEnter,
@@ -1804,8 +1776,7 @@ static const struct wl_pointer_listener pointerListener =
pointerHandleFrame,
pointerHandleAxisSource,
pointerHandleAxisStop,
pointerHandleAxisDiscrete,
pointerHandleAxisValue120
pointerHandleAxisDiscrete
};
static void keyboardHandleKeymap(void* userData,
@@ -1828,7 +1799,7 @@ static void keyboardHandleKeymap(void* userData,
return;
}
mapStr = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
if (mapStr == MAP_FAILED)
{
close(fd);
@@ -2330,37 +2301,41 @@ void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device)
GLFWbool _glfwWaitForEGLFrameWayland(_GLFWwindow* window)
{
double timeout = 0.02;
while (window->wl.egl.callback)
for (int i = 0; i < window->wl.egl.interval; i++)
{
if (wl_display_prepare_read_queue(_glfw.wl.display, window->wl.egl.queue) != 0)
double timeout = 0.02;
while (window->wl.egl.callback)
{
while (wl_display_prepare_read_queue(_glfw.wl.display, window->wl.egl.queue) != 0)
wl_display_dispatch_queue_pending(_glfw.wl.display, window->wl.egl.queue);
if (!flushDisplay())
{
wl_display_cancel_read(_glfw.wl.display);
return GLFW_FALSE;
}
struct pollfd fd = { wl_display_get_fd(_glfw.wl.display), POLLIN };
if (!_glfwPollPOSIX(&fd, 1, &timeout))
{
wl_display_cancel_read(_glfw.wl.display);
return GLFW_FALSE;
}
wl_display_read_events(_glfw.wl.display);
wl_display_dispatch_queue_pending(_glfw.wl.display, window->wl.egl.queue);
continue;
}
if (!flushDisplay())
{
wl_display_cancel_read(_glfw.wl.display);
return GLFW_FALSE;
}
window->wl.egl.callback = wl_surface_frame(window->wl.egl.wrapper);
wl_callback_add_listener(window->wl.egl.callback, &frameCallbackListener, window);
struct pollfd fd = { wl_display_get_fd(_glfw.wl.display), POLLIN };
if (!_glfwPollPOSIX(&fd, 1, &timeout))
{
wl_display_cancel_read(_glfw.wl.display);
return GLFW_FALSE;
}
wl_display_read_events(_glfw.wl.display);
wl_display_dispatch_queue_pending(_glfw.wl.display, window->wl.egl.queue);
// Commit the old buffer for every frame but the last one so we get new callbacks
if (i + 1 < window->wl.egl.interval)
wl_surface_commit(window->wl.surface);
}
window->wl.egl.callback = wl_surface_frame(window->wl.egl.wrapper);
wl_callback_add_listener(window->wl.egl.callback, &frameCallbackListener, window);
// If the window is hidden when the wait is over then don't swap
return window->wl.visible;
}
@@ -2411,8 +2386,6 @@ GLFWbool _glfwCreateWindowWayland(_GLFWwindow* window,
wl_proxy_set_queue((struct wl_proxy*) window->wl.egl.wrapper,
window->wl.egl.queue);
window->wl.egl.interval = 1;
if (!_glfwInitEGL())
return GLFW_FALSE;
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
@@ -2726,8 +2699,6 @@ void _glfwHideWindowWayland(_GLFWwindow* window)
wl_surface_attach(window->wl.surface, NULL, 0, 0);
wl_surface_commit(window->wl.surface);
flushDisplay();
}
}
@@ -2942,9 +2913,7 @@ void _glfwWaitEventsTimeoutWayland(double timeout)
void _glfwPostEmptyEventWayland(void)
{
struct wl_callback* callback = wl_display_sync(_glfw.wl.display);
wl_callback_add_listener(callback, &noopCallbackListener, NULL);
wl_display_sync(_glfw.wl.display);
flushDisplay();
}
+15 -15
View File
@@ -452,6 +452,9 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(V
typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t);
#include "xkb_unicode.h"
#include "posix_poll.h"
#define GLFW_X11_WINDOW_STATE _GLFWwindowX11 x11;
#define GLFW_X11_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11;
#define GLFW_X11_MONITOR_STATE _GLFWmonitorX11 x11;
@@ -460,7 +463,6 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(Vk
#define GLFW_GLX_CONTEXT_STATE _GLFWcontextGLX glx;
#define GLFW_GLX_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx;
#define GLFW_INVALID_CODEPOINT 0xffffffffu
// GLX-specific per-context data
//
@@ -503,18 +505,18 @@ typedef struct _GLFWlibraryGLX
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
bool SGI_swap_control;
bool EXT_swap_control;
bool MESA_swap_control;
bool ARB_multisample;
bool ARB_framebuffer_sRGB;
bool EXT_framebuffer_sRGB;
bool ARB_create_context;
bool ARB_create_context_profile;
bool ARB_create_context_robustness;
bool EXT_create_context_es2_profile;
bool ARB_create_context_no_error;
bool ARB_context_flush_control;
GLFWbool SGI_swap_control;
GLFWbool EXT_swap_control;
GLFWbool MESA_swap_control;
GLFWbool ARB_multisample;
GLFWbool ARB_framebuffer_sRGB;
GLFWbool EXT_framebuffer_sRGB;
GLFWbool ARB_create_context;
GLFWbool ARB_create_context_profile;
GLFWbool ARB_create_context_robustness;
GLFWbool EXT_create_context_es2_profile;
GLFWbool ARB_create_context_no_error;
GLFWbool ARB_context_flush_control;
} _GLFWlibraryGLX;
// X11-specific per-window data
@@ -983,8 +985,6 @@ unsigned long _glfwGetWindowPropertyX11(Window window,
unsigned char** value);
GLFWbool _glfwIsVisualTransparentX11(Visual* visual);
uint32_t _glfwKeySym2UnicodeX11(unsigned int keysym);
void _glfwGrabErrorHandlerX11(void);
void _glfwReleaseErrorHandlerX11(void);
void _glfwInputErrorX11(int error, const char* message);
+2 -2
View File
@@ -1308,7 +1308,7 @@ static void processEvent(XEvent *event)
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
const uint32_t codepoint = _glfwKeySym2UnicodeX11(keysym);
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
if (codepoint != GLFW_INVALID_CODEPOINT)
_glfwInputChar(window, codepoint, mods, plain);
}
@@ -2944,7 +2944,7 @@ const char* _glfwGetScancodeNameX11(int scancode)
if (keysym == NoSymbol)
return NULL;
const uint32_t codepoint = _glfwKeySym2UnicodeX11(keysym);
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
if (codepoint == GLFW_INVALID_CODEPOINT)
return NULL;
+3 -3
View File
@@ -27,7 +27,7 @@
#include "internal.h"
#if defined(_GLFW_X11)
#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND)
/*
* Marcus: This code was originally written by Markus G. Kuhn.
@@ -906,7 +906,7 @@ static const struct codepair {
// Convert XKB KeySym to Unicode
//
uint32_t _glfwKeySym2UnicodeX11(unsigned int keysym)
uint32_t _glfwKeySym2Unicode(unsigned int keysym)
{
int min = 0;
int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
@@ -939,5 +939,5 @@ uint32_t _glfwKeySym2UnicodeX11(unsigned int keysym)
return GLFW_INVALID_CODEPOINT;
}
#endif // _GLFW_X11
#endif // _GLFW_WAYLAND or _GLFW_X11
+30
View File
@@ -0,0 +1,30 @@
//========================================================================
// GLFW 3.5 Linux - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
//
// 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.
//
//========================================================================
#define GLFW_INVALID_CODEPOINT 0xffffffffu
uint32_t _glfwKeySym2Unicode(unsigned int keysym);
+30 -75
View File
@@ -23,10 +23,7 @@
//
//========================================================================
//
// This test is intended to verify that the posting of empty events works.
// Background colors are produced on a secondary thread, which then wakes
// the main thread with glfwPostEmptyEvent when a new one is available.
// This allows the main thread to wait for events unconditionally.
// This test is intended to verify that posting of empty events works
//
//========================================================================
@@ -40,53 +37,25 @@
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
struct State
{
mtx_t lock;
bool running;
bool needs_update;
int width;
int height;
float r, g, b;
};
static volatile int running = GLFW_TRUE;
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void generate_color(struct State* state)
{
const float r = (float) rand() / (float) RAND_MAX;
const float g = (float) rand() / (float) RAND_MAX;
const float b = (float) rand() / (float) RAND_MAX;
const float l = sqrtf(r * r + g * g + b * b);
mtx_lock(&state->lock);
state->r = r / l;
state->g = g / l;
state->b = b / l;
state->needs_update = true;
mtx_unlock(&state->lock);
}
static int thread_main(void* data)
{
struct State* const state = data;
struct timespec time;
srand((unsigned int) time(NULL));
while (state->running)
while (running)
{
generate_color(state);
glfwPostEmptyEvent();
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
time.tv_sec += 1;
thrd_sleep(&time, NULL);
glfwPostEmptyEvent();
}
return 0;
@@ -95,38 +64,28 @@ static int thread_main(void* data)
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
static float nrand(void)
{
struct State* const state = glfwGetWindowUserPointer(window);
mtx_lock(&state->lock);
state->width = width;
state->height = height;
state->needs_update = true;
mtx_unlock(&state->lock);
return (float) rand() / (float) RAND_MAX;
}
int main(void)
{
struct State state = { .running = true };
int result;
thrd_t thread;
GLFWwindow* window;
if (mtx_init(&state.lock, mtx_plain) != thrd_success)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
generate_color(&state);
srand((unsigned int) time(NULL));
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
GLFWwindow* window = glfwCreateWindow(640, 480, "Empty Event Test", NULL, NULL);
window = glfwCreateWindow(640, 480, "Empty Event Test", NULL, NULL);
if (!window)
{
glfwTerminate();
@@ -136,13 +95,8 @@ int main(void)
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSetKeyCallback(window, key_callback);
glfwSetWindowUserPointer(window, &state);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwGetFramebufferSize(window, &state.width, &state.height);
thrd_t color_thread;
if (thrd_create(&color_thread, thread_main, &state) != thrd_success)
if (thrd_create(&thread, thread_main, NULL) != thrd_success)
{
fprintf(stderr, "Failed to create secondary thread\n");
@@ -150,27 +104,28 @@ int main(void)
exit(EXIT_FAILURE);
}
while (!glfwWindowShouldClose(window))
while (running)
{
if (state.needs_update)
{
mtx_lock(&state.lock);
glViewport(0, 0, state.width, state.height);
glClearColor(state.r, state.g, state.b, 1.f);
state.needs_update = false;
mtx_unlock(&state.lock);
int width, height;
float r = nrand(), g = nrand(), b = nrand();
float l = (float) sqrt(r * r + g * g + b * b);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
}
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClearColor(r / l, g / l, b / l, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
if (glfwWindowShouldClose(window))
running = GLFW_FALSE;
}
glfwHideWindow(window);
state.running = false;
thrd_join(color_thread, NULL);
mtx_destroy(&state.lock);
thrd_join(thread, &result);
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);