Compare commits

...

10 Commits

Author SHA1 Message Date
linkmauve
8d96eaae4a
Merge c27caa4b1d into 232164f62b 2026-02-06 07:19:59 +03:00
Camilla Löwy
232164f62b Wayland: Remove duplicate cursor state
The shared window struct already tracks the current cursor.
2026-02-05 17:28:32 +01:00
Camilla Löwy
abb9db0d75 Wayland: Fix fallback decoration button input
Fallback decoration mouse button actions were performed for both press
and release events.  The requests made using a mouse button release
serials were presumably (and correctly) discarded by the compositor.

This commit removes the generation of these nuisance requests.
2026-02-05 17:25:11 +01:00
Camilla Löwy
0aa77a9a3a Wayland: Release input devices where possible
On systems with wl_seat verison 3 or later, use release instead of
destroy on input devices when they are disconnected.
2026-02-04 18:08:37 +01:00
Camilla Löwy
7b370d8df0 Wayland: Simplify pointer surface state
Track which surface contains the pointer with one piece of state instead
of three partially overlapping ones.
2026-02-04 18:08:37 +01:00
Camilla Löwy
f871f14d5e Add update flag to timeout test
Redrawing the window contents for every possible event is not
a reasonable thing for an application to do.  The test should be whether
redrawing on demand plus periodic updates works with near-idle CPU use
and no extra input latency.

This change incidentally makes the test well-behaved on Wayland, where
it was previously broken due to every EGL buffer swap causing an event
to be received.
2026-02-04 18:07:19 +01:00
Camilla Löwy
bafb134769 Documentation work
Elaborate on what 'work' means in the context of joystick input.
2026-01-27 20:51:00 +01:00
Camilla Löwy
2d7ae8f2d0 Wayland: Cleanup
This is only a semantic change.  The values are the same.
2026-01-15 21:09:01 +01:00
Camilla Löwy
96e0f49395 X11: Place argument assertion after platform check
This lets automated testing check that GLFW_NOT_INITIALIZED is emitted
for every public function.
2026-01-14 21:03:13 +01:00
Emmanuel Gil Peyrot
c27caa4b1d Remove OSMesa support
Mesa removed that library in 027ccd963b1f8f288bef4224aedcddc1557e4f8a,
so this API can be removed from GLFW too.

Mesa has provided an alternative path for years, through the
EGL_MESA_platform_surfaceless EGL extension, and it also supports
selecting the software rasterizer through the EGL_EXT_platform_device
EGL extension, neither of which are supported by GLFW yet.

I kept the external API the same, notably the GLFW_OSMESA_CONTEXT_API
define is still present, but will error at runtime.
2025-09-08 13:53:50 +02:00
26 changed files with 136 additions and 687 deletions

View File

@ -16,7 +16,7 @@ include(GNUInstallDirs)
include(CMakeDependentOption)
if (GLFW_USE_OSMESA)
message(FATAL_ERROR "GLFW_USE_OSMESA has been removed; set the GLFW_PLATFORM init hint")
message(FATAL_ERROR "OSMesa support has been removed")
endif()
if (DEFINED GLFW_USE_WAYLAND AND UNIX AND NOT APPLE)

View File

@ -2312,7 +2312,6 @@ PREDEFINED = GLFWAPI= \
GLFW_EXPOSE_NATIVE_COCOA \
GLFW_EXPOSE_NATIVE_NSGL \
GLFW_EXPOSE_NATIVE_EGL \
GLFW_EXPOSE_NATIVE_OSMESA \
VK_VERSION_1_0
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this

View File

@ -359,10 +359,10 @@ attempts to detect the appropriate platform at initialization.
If you are building GLFW as a shared library / dynamic library / DLL then you
must also define @b _GLFW_BUILD_DLL. Otherwise, you must not define it.
If you are using a custom name for the Vulkan, EGL, GLX, OSMesa, OpenGL, GLESv1
If you are using a custom name for the Vulkan, EGL, GLX, OpenGL, GLESv1
or GLESv2 library, you can override the default names by defining those you need
of @b _GLFW_VULKAN_LIBRARY, @b _GLFW_EGL_LIBRARY, @b _GLFW_GLX_LIBRARY, @b
_GLFW_OSMESA_LIBRARY, @b _GLFW_OPENGL_LIBRARY, @b _GLFW_GLESV1_LIBRARY and @b
_GLFW_OPENGL_LIBRARY, @b _GLFW_GLESV1_LIBRARY and @b
_GLFW_GLESV2_LIBRARY. Otherwise, GLFW will use the built-in default names.
@note None of the @ref build_macros may be defined during the compilation of

View File

@ -618,20 +618,20 @@ The format of the string is as follows:
- For each supported platform:
- The name of the window system API
- The name of the window system specific context creation API, if applicable
- The names of the always supported context creation APIs EGL and OSMesa
- The names of the always supported context creation APIs and EGL
- Any additional compile-time options, APIs and (on Windows) what compiler was used
For example, compiling GLFW 3.5 with MinGW-64 as a DLL for Windows, may result
in a version string like this:
```c
3.5.0 Win32 WGL Null EGL OSMesa MinGW-w64 DLL
3.5.0 Win32 WGL Null EGL MinGW-w64 DLL
```
Compiling GLFW as a static library for Linux, with both Wayland and X11 enabled, may
result in a version string like this:
```c
3.5.0 Wayland X11 GLX Null EGL OSMesa monotonic
3.5.0 Wayland X11 GLX Null EGL monotonic
```

View File

@ -354,9 +354,9 @@ This is a hard constraint.
@anchor GLFW_CONTEXT_CREATION_API_hint
__GLFW_CONTEXT_CREATION_API__ specifies which context creation API to use to
create the context. Possible values are `GLFW_NATIVE_CONTEXT_API`,
`GLFW_EGL_CONTEXT_API` and `GLFW_OSMESA_CONTEXT_API`. This is a hard
constraint. If no client API is requested, this hint is ignored.
create the context. Possible values are `GLFW_NATIVE_CONTEXT_API` and
`GLFW_EGL_CONTEXT_API`. This is a hard constraint. If no client API is requested,
this hint is ignored.
An [extension loader library](@ref context_glext_auto) that assumes it knows
which API was used to create the current context may fail if you change this
@ -370,11 +370,6 @@ will have no effect.
APIs in a single process will cause the application to segfault. Stick to one
API or the other on Linux for now.
@note __OSMesa:__ As its name implies, an OpenGL context created with OSMesa
does not update the window contents when its buffers are swapped. Use OpenGL
functions or the OSMesa native access functions @ref glfwGetOSMesaColorBuffer
and @ref glfwGetOSMesaDepthBuffer to retrieve the framebuffer contents.
@anchor GLFW_CONTEXT_VERSION_MAJOR_hint
@anchor GLFW_CONTEXT_VERSION_MINOR_hint
__GLFW_CONTEXT_VERSION_MAJOR__ and __GLFW_CONTEXT_VERSION_MINOR__ specify the
@ -565,7 +560,7 @@ GLFW_STEREO | `GLFW_FALSE` | `GLFW_TRUE` or `GL
GLFW_SRGB_CAPABLE | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_DOUBLEBUFFER | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_CLIENT_API | `GLFW_OPENGL_API` | `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`
GLFW_CONTEXT_CREATION_API | `GLFW_NATIVE_CONTEXT_API` | `GLFW_NATIVE_CONTEXT_API`, `GLFW_EGL_CONTEXT_API` or `GLFW_OSMESA_CONTEXT_API`
GLFW_CONTEXT_CREATION_API | `GLFW_NATIVE_CONTEXT_API` | `GLFW_NATIVE_CONTEXT_API` or `GLFW_EGL_CONTEXT_API`
GLFW_CONTEXT_VERSION_MAJOR | 1 | Any valid major version number of the chosen client API
GLFW_CONTEXT_VERSION_MINOR | 0 | Any valid minor version number of the chosen client API
GLFW_CONTEXT_ROBUSTNESS | `GLFW_NO_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS`, `GLFW_NO_RESET_NOTIFICATION` or `GLFW_LOSE_CONTEXT_ON_RESET`
@ -1407,8 +1402,7 @@ either `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`.
@anchor GLFW_CONTEXT_CREATION_API_attrib
__GLFW_CONTEXT_CREATION_API__ indicates the context creation API used to create
the window's context; either `GLFW_NATIVE_CONTEXT_API`, `GLFW_EGL_CONTEXT_API`
or `GLFW_OSMESA_CONTEXT_API`.
the window's context; either `GLFW_NATIVE_CONTEXT_API` or `GLFW_EGL_CONTEXT_API`.
@anchor GLFW_CONTEXT_VERSION_MAJOR_attrib
@anchor GLFW_CONTEXT_VERSION_MINOR_attrib

View File

@ -4520,7 +4520,8 @@ GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow*
* GLFW will pass those events on to the application callbacks before
* returning.
*
* Event processing is not required for joystick input to work.
* Event processing is not required to receive joystick input. Joystick state
* is polled when a joystick input or gamepad input function is called.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
@ -4565,7 +4566,8 @@ GLFWAPI void glfwPollEvents(void);
* GLFW will pass those events on to the application callbacks before
* returning.
*
* Event processing is not required for joystick input to work.
* Event processing is not required to receive joystick input. Joystick state
* is polled when a joystick input or gamepad input function is called.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
@ -4612,7 +4614,8 @@ GLFWAPI void glfwWaitEvents(void);
* GLFW will pass those events on to the application callbacks before
* returning.
*
* Event processing is not required for joystick input to work.
* Event processing is not required to receive joystick input. Joystick state
* is polled when a joystick input or gamepad input function is called.
*
* @param[in] timeout The maximum amount of time, in seconds, to wait.
*

View File

@ -68,7 +68,6 @@ extern "C" {
* * `GLFW_EXPOSE_NATIVE_NSGL`
* * `GLFW_EXPOSE_NATIVE_GLX`
* * `GLFW_EXPOSE_NATIVE_EGL`
* * `GLFW_EXPOSE_NATIVE_OSMESA`
*
* These macros select which of the native access functions that are declared
* and which platform-specific headers to include. It is then up your (by
@ -143,17 +142,6 @@ extern "C" {
#if defined(GLFW_EXPOSE_NATIVE_EGL)
#include <EGL/egl.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
/* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by
* default it also acts as an OpenGL header
* However, osmesa.h will include gl.h, which will define it unconditionally
*/
#if defined(GLFW_GLAPIENTRY_DEFINED)
#undef GLAPIENTRY
#undef GLFW_GLAPIENTRY_DEFINED
#endif
#include <GL/osmesa.h>
#endif
#endif /*GLFW_NATIVE_INCLUDE_NONE*/
@ -634,73 +622,6 @@ GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
GLFWAPI int glfwGetEGLConfig(GLFWwindow* window, EGLConfig* config);
#endif
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
/*! @brief Retrieves the color buffer associated with the specified window.
*
* @param[in] window The window whose color buffer to retrieve.
* @param[out] width Where to store the width of the color buffer, or `NULL`.
* @param[out] height Where to store the height of the color buffer, or `NULL`.
* @param[out] format Where to store the OSMesa pixel format of the color
* buffer, or `NULL`.
* @param[out] buffer Where to store the address of the color buffer, or
* `NULL`.
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
* [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_NO_WINDOW_CONTEXT.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width, int* height, int* format, void** buffer);
/*! @brief Retrieves the depth buffer associated with the specified window.
*
* @param[in] window The window whose depth buffer to retrieve.
* @param[out] width Where to store the width of the depth buffer, or `NULL`.
* @param[out] height Where to store the height of the depth buffer, or `NULL`.
* @param[out] bytesPerValue Where to store the number of bytes per depth
* buffer element, or `NULL`.
* @param[out] buffer Where to store the address of the depth buffer, or
* `NULL`.
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
* [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_NO_WINDOW_CONTEXT.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width, int* height, int* bytesPerValue, void** buffer);
/*! @brief Returns the `OSMesaContext` of the specified window.
*
* @return The `OSMesaContext` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_NO_WINDOW_CONTEXT.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* window);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -4,7 +4,7 @@ add_library(glfw ${GLFW_LIBRARY_TYPE}
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h"
internal.h platform.h mappings.h
context.c init.c input.c monitor.c platform.c vulkan.c window.c
egl_context.c osmesa_context.c null_platform.h null_joystick.h
egl_context.c null_platform.h null_joystick.h
null_init.c null_monitor.c null_window.c null_joystick.c)
# The time, thread and module code is shared between all backends on a given OS,

View File

@ -686,7 +686,6 @@ void _glfwTerminateCocoa(void)
_glfwTerminateNSGL();
_glfwTerminateEGL();
_glfwTerminateOSMesa();
} // autoreleasepool
}

View File

@ -948,13 +948,6 @@ GLFWbool _glfwCreateWindowCocoa(_GLFWwindow* window,
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
{
if (!_glfwInitOSMesa())
return GLFW_FALSE;
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
if (!_glfwRefreshContextAttribs(window, ctxconfig))
return GLFW_FALSE;

View File

@ -46,9 +46,14 @@
//
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
{
if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa support has been removed");
return GLFW_FALSE;
}
if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
ctxconfig->source != GLFW_EGL_CONTEXT_API &&
ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
ctxconfig->source != GLFW_EGL_CONTEXT_API)
{
_glfwInputError(GLFW_INVALID_ENUM,
"Invalid context creation API 0x%08X",

View File

@ -240,35 +240,6 @@ typedef EGLSurface (APIENTRY * PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)(EGLDisp
#define eglGetPlatformDisplayEXT _glfw.egl.GetPlatformDisplayEXT
#define eglCreatePlatformWindowSurfaceEXT _glfw.egl.CreatePlatformWindowSurfaceEXT
#define OSMESA_RGBA 0x1908
#define OSMESA_FORMAT 0x22
#define OSMESA_DEPTH_BITS 0x30
#define OSMESA_STENCIL_BITS 0x31
#define OSMESA_ACCUM_BITS 0x32
#define OSMESA_PROFILE 0x33
#define OSMESA_CORE_PROFILE 0x34
#define OSMESA_COMPAT_PROFILE 0x35
#define OSMESA_CONTEXT_MAJOR_VERSION 0x36
#define OSMESA_CONTEXT_MINOR_VERSION 0x37
typedef void* OSMesaContext;
typedef void (*OSMESAproc)(void);
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextExt)(GLenum,GLint,GLint,GLint,OSMesaContext);
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextAttribs)(const int*,OSMesaContext);
typedef void (GLAPIENTRY * PFN_OSMesaDestroyContext)(OSMesaContext);
typedef int (GLAPIENTRY * PFN_OSMesaMakeCurrent)(OSMesaContext,void*,int,int,int);
typedef int (GLAPIENTRY * PFN_OSMesaGetColorBuffer)(OSMesaContext,int*,int*,int*,void**);
typedef int (GLAPIENTRY * PFN_OSMesaGetDepthBuffer)(OSMesaContext,int*,int*,int*,void**);
typedef GLFWglproc (GLAPIENTRY * PFN_OSMesaGetProcAddress)(const char*);
#define OSMesaCreateContextExt _glfw.osmesa.CreateContextExt
#define OSMesaCreateContextAttribs _glfw.osmesa.CreateContextAttribs
#define OSMesaDestroyContext _glfw.osmesa.DestroyContext
#define OSMesaMakeCurrent _glfw.osmesa.MakeCurrent
#define OSMesaGetColorBuffer _glfw.osmesa.GetColorBuffer
#define OSMesaGetDepthBuffer _glfw.osmesa.GetDepthBuffer
#define OSMesaGetProcAddress _glfw.osmesa.GetProcAddress
#define VK_NULL_HANDLE 0
typedef void* VkInstance;
@ -513,13 +484,6 @@ struct _GLFWcontext
void* client;
} egl;
struct {
OSMesaContext handle;
int width;
int height;
void* buffer;
} osmesa;
// This is defined in platform.h
GLFW_PLATFORM_CONTEXT_STATE
};
@ -846,19 +810,6 @@ struct _GLFWlibrary
PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC CreatePlatformWindowSurfaceEXT;
} egl;
struct {
void* handle;
PFN_OSMesaCreateContextExt CreateContextExt;
PFN_OSMesaCreateContextAttribs CreateContextAttribs;
PFN_OSMesaDestroyContext DestroyContext;
PFN_OSMesaMakeCurrent MakeCurrent;
PFN_OSMesaGetColorBuffer GetColorBuffer;
PFN_OSMesaGetDepthBuffer GetDepthBuffer;
PFN_OSMesaGetProcAddress GetProcAddress;
} osmesa;
struct {
GLFWbool available;
void* handle;
@ -998,12 +949,6 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
Visual** visual, int* depth);
#endif /*_GLFW_X11*/
GLFWbool _glfwInitOSMesa(void);
void _glfwTerminateOSMesa(void);
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig);
GLFWbool _glfwInitVulkan(int mode);
void _glfwTerminateVulkan(void);
const char* _glfwGetVulkanResultString(VkResult result);

View File

@ -258,7 +258,6 @@ int _glfwInitNull(void)
void _glfwTerminateNull(void)
{
free(_glfw.null.clipboardString);
_glfwTerminateOSMesa();
_glfwTerminateEGL();
}

View File

@ -120,23 +120,11 @@ GLFWbool _glfwCreateWindowNull(_GLFWwindow* window,
return GLFW_FALSE;
if (ctxconfig->client != GLFW_NO_API)
{
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API ||
ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
{
if (!_glfwInitOSMesa())
return GLFW_FALSE;
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
{
if (!_glfwInitEGL())
return GLFW_FALSE;
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
if (!_glfwRefreshContextAttribs(window, ctxconfig))
return GLFW_FALSE;
}

View File

@ -1,387 +0,0 @@
//========================================================================
// GLFW 3.5 OSMesa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2017 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.
//
//========================================================================
#include "internal.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
static void makeContextCurrentOSMesa(_GLFWwindow* window)
{
if (window)
{
int width, height;
_glfw.platform.getFramebufferSize(window, &width, &height);
// Check to see if we need to allocate a new buffer
if ((window->context.osmesa.buffer == NULL) ||
(width != window->context.osmesa.width) ||
(height != window->context.osmesa.height))
{
_glfw_free(window->context.osmesa.buffer);
// Allocate the new buffer (width * height * 8-bit RGBA)
window->context.osmesa.buffer = _glfw_calloc(4, (size_t) width * height);
window->context.osmesa.width = width;
window->context.osmesa.height = height;
}
if (!OSMesaMakeCurrent(window->context.osmesa.handle,
window->context.osmesa.buffer,
GL_UNSIGNED_BYTE,
width, height))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"OSMesa: Failed to make context current");
return;
}
}
_glfwPlatformSetTls(&_glfw.contextSlot, window);
}
static GLFWglproc getProcAddressOSMesa(const char* procname)
{
return (GLFWglproc) OSMesaGetProcAddress(procname);
}
static void destroyContextOSMesa(_GLFWwindow* window)
{
if (window->context.osmesa.handle)
{
OSMesaDestroyContext(window->context.osmesa.handle);
window->context.osmesa.handle = NULL;
}
if (window->context.osmesa.buffer)
{
_glfw_free(window->context.osmesa.buffer);
window->context.osmesa.width = 0;
window->context.osmesa.height = 0;
}
}
static void swapBuffersOSMesa(_GLFWwindow* window)
{
// No double buffering on OSMesa
}
static void swapIntervalOSMesa(int interval)
{
// No swap interval on OSMesa
}
static int extensionSupportedOSMesa(const char* extension)
{
// OSMesa does not have extensions
return GLFW_FALSE;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwInitOSMesa(void)
{
int i;
const char* sonames[] =
{
#if defined(_GLFW_OSMESA_LIBRARY)
_GLFW_OSMESA_LIBRARY,
#elif defined(_WIN32)
"libOSMesa.dll",
"OSMesa.dll",
#elif defined(__APPLE__)
"libOSMesa.8.dylib",
#elif defined(__CYGWIN__)
"libOSMesa-8.so",
#elif defined(__OpenBSD__) || defined(__NetBSD__)
"libOSMesa.so",
#else
"libOSMesa.so.8",
"libOSMesa.so.6",
#endif
NULL
};
if (_glfw.osmesa.handle)
return GLFW_TRUE;
for (i = 0; sonames[i]; i++)
{
_glfw.osmesa.handle = _glfwPlatformLoadModule(sonames[i]);
if (_glfw.osmesa.handle)
break;
}
if (!_glfw.osmesa.handle)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found");
return GLFW_FALSE;
}
_glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt)
_glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaCreateContextExt");
_glfw.osmesa.CreateContextAttribs = (PFN_OSMesaCreateContextAttribs)
_glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaCreateContextAttribs");
_glfw.osmesa.DestroyContext = (PFN_OSMesaDestroyContext)
_glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaDestroyContext");
_glfw.osmesa.MakeCurrent = (PFN_OSMesaMakeCurrent)
_glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaMakeCurrent");
_glfw.osmesa.GetColorBuffer = (PFN_OSMesaGetColorBuffer)
_glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaGetColorBuffer");
_glfw.osmesa.GetDepthBuffer = (PFN_OSMesaGetDepthBuffer)
_glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaGetDepthBuffer");
_glfw.osmesa.GetProcAddress = (PFN_OSMesaGetProcAddress)
_glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaGetProcAddress");
if (!_glfw.osmesa.CreateContextExt ||
!_glfw.osmesa.DestroyContext ||
!_glfw.osmesa.MakeCurrent ||
!_glfw.osmesa.GetColorBuffer ||
!_glfw.osmesa.GetDepthBuffer ||
!_glfw.osmesa.GetProcAddress)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"OSMesa: Failed to load required entry points");
_glfwTerminateOSMesa();
return GLFW_FALSE;
}
return GLFW_TRUE;
}
void _glfwTerminateOSMesa(void)
{
if (_glfw.osmesa.handle)
{
_glfwPlatformFreeModule(_glfw.osmesa.handle);
_glfw.osmesa.handle = NULL;
}
}
#define SET_ATTRIB(a, v) \
{ \
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \
attribs[index++] = v; \
}
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
OSMesaContext share = NULL;
const int accumBits = fbconfig->accumRedBits +
fbconfig->accumGreenBits +
fbconfig->accumBlueBits +
fbconfig->accumAlphaBits;
if (ctxconfig->client == GLFW_OPENGL_ES_API)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"OSMesa: OpenGL ES is not available on OSMesa");
return GLFW_FALSE;
}
if (ctxconfig->share)
share = ctxconfig->share->context.osmesa.handle;
if (OSMesaCreateContextAttribs)
{
int index = 0, attribs[40];
SET_ATTRIB(OSMESA_FORMAT, OSMESA_RGBA);
SET_ATTRIB(OSMESA_DEPTH_BITS, fbconfig->depthBits);
SET_ATTRIB(OSMESA_STENCIL_BITS, fbconfig->stencilBits);
SET_ATTRIB(OSMESA_ACCUM_BITS, accumBits);
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
{
SET_ATTRIB(OSMESA_PROFILE, OSMESA_CORE_PROFILE);
}
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
{
SET_ATTRIB(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE);
}
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
SET_ATTRIB(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major);
SET_ATTRIB(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor);
}
if (ctxconfig->forward)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"OSMesa: Forward-compatible contexts not supported");
return GLFW_FALSE;
}
SET_ATTRIB(0, 0);
window->context.osmesa.handle =
OSMesaCreateContextAttribs(attribs, share);
}
else
{
if (ctxconfig->profile)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"OSMesa: OpenGL profiles unavailable");
return GLFW_FALSE;
}
window->context.osmesa.handle =
OSMesaCreateContextExt(OSMESA_RGBA,
fbconfig->depthBits,
fbconfig->stencilBits,
accumBits,
share);
}
if (window->context.osmesa.handle == NULL)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"OSMesa: Failed to create context");
return GLFW_FALSE;
}
window->context.makeCurrent = makeContextCurrentOSMesa;
window->context.swapBuffers = swapBuffersOSMesa;
window->context.swapInterval = swapIntervalOSMesa;
window->context.extensionSupported = extensionSupportedOSMesa;
window->context.getProcAddress = getProcAddressOSMesa;
window->context.destroy = destroyContextOSMesa;
return GLFW_TRUE;
}
#undef SET_ATTRIB
//////////////////////////////////////////////////////////////////////////
////// GLFW native API //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
int* height, int* format, void** buffer)
{
void* mesaBuffer;
GLint mesaWidth, mesaHeight, mesaFormat;
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (window->context.source != GLFW_OSMESA_CONTEXT_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return GLFW_FALSE;
}
if (!OSMesaGetColorBuffer(window->context.osmesa.handle,
&mesaWidth, &mesaHeight,
&mesaFormat, &mesaBuffer))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"OSMesa: Failed to retrieve color buffer");
return GLFW_FALSE;
}
if (width)
*width = mesaWidth;
if (height)
*height = mesaHeight;
if (format)
*format = mesaFormat;
if (buffer)
*buffer = mesaBuffer;
return GLFW_TRUE;
}
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
int* width, int* height,
int* bytesPerValue,
void** buffer)
{
void* mesaBuffer;
GLint mesaWidth, mesaHeight, mesaBytes;
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (window->context.source != GLFW_OSMESA_CONTEXT_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return GLFW_FALSE;
}
if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,
&mesaWidth, &mesaHeight,
&mesaBytes, &mesaBuffer))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"OSMesa: Failed to retrieve depth buffer");
return GLFW_FALSE;
}
if (width)
*width = mesaWidth;
if (height)
*height = mesaHeight;
if (bytesPerValue)
*bytesPerValue = mesaBytes;
if (buffer)
*buffer = mesaBuffer;
return GLFW_TRUE;
}
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (window->context.source != GLFW_OSMESA_CONTEXT_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL;
}
return window->context.osmesa.handle;
}

View File

@ -184,7 +184,6 @@ GLFWAPI const char* glfwGetVersionString(void)
#endif
" Null"
" EGL"
" OSMesa"
#if defined(__MINGW64_VERSION_MAJOR)
" MinGW-w64"
#elif defined(_MSC_VER)

View File

@ -39,7 +39,6 @@
#include "null_platform.h"
#define GLFW_EXPOSE_NATIVE_EGL
#define GLFW_EXPOSE_NATIVE_OSMESA
#if defined(_GLFW_WIN32)
#include "win32_platform.h"

View File

@ -719,7 +719,6 @@ void _glfwTerminateWin32(void)
_glfwTerminateWGL();
_glfwTerminateEGL();
_glfwTerminateOSMesa();
freeLibraries();
}

View File

@ -1506,13 +1506,6 @@ GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window,
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
{
if (!_glfwInitOSMesa())
return GLFW_FALSE;
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
if (!_glfwRefreshContextAttribs(window, ctxconfig))
return GLFW_FALSE;

View File

@ -834,7 +834,7 @@ int _glfwInitWayland(void)
createKeyTables();
_glfw.wl.xkb.context = xkb_context_new(0);
_glfw.wl.xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!_glfw.wl.xkb.context)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
@ -895,7 +895,6 @@ int _glfwInitWayland(void)
void _glfwTerminateWayland(void)
{
_glfwTerminateEGL();
_glfwTerminateOSMesa();
if (_glfw.wl.libdecor.context)
{

View File

@ -360,7 +360,6 @@ typedef struct _GLFWwindowWayland
GLFWbool maximized;
GLFWbool activated;
GLFWbool fullscreen;
GLFWbool hovered;
GLFWbool transparent;
GLFWbool scaleFramebuffer;
struct wl_surface* surface;
@ -389,7 +388,6 @@ typedef struct _GLFWwindowWayland
struct libdecor_frame* frame;
} libdecor;
_GLFWcursor* currentCursor;
double cursorPosX, cursorPosY;
char* appId;
@ -416,7 +414,6 @@ typedef struct _GLFWwindowWayland
GLFWbool decorations;
struct wl_buffer* buffer;
_GLFWfallbackEdgeWayland top, left, right, bottom;
struct wl_surface* focus;
wl_fixed_t pointerX, pointerY;
const char* cursorName;
} fallback;
@ -457,6 +454,7 @@ typedef struct _GLFWlibraryWayland
const char* tag;
struct wl_surface* pointerSurface;
struct wl_cursor_theme* cursorTheme;
struct wl_cursor_theme* cursorThemeHiDPI;
struct wl_surface* cursorSurface;
@ -515,7 +513,6 @@ typedef struct _GLFWlibraryWayland
PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
} xkb;
_GLFWwindow* pointerFocus;
_GLFWwindow* keyboardFocus;
struct {

View File

@ -253,6 +253,9 @@ static void createFallbackDecorations(_GLFWwindow* window)
static void destroyFallbackEdge(_GLFWfallbackEdgeWayland* edge)
{
if (edge->surface == _glfw.wl.pointerSurface)
_glfw.wl.pointerSurface = NULL;
if (edge->subsurface)
wl_subsurface_destroy(edge->subsurface);
if (edge->surface)
@ -288,26 +291,26 @@ static void updateFallbackDecorationCursor(_GLFWwindow* window,
if (window->resizable)
{
if (window->wl.fallback.focus == window->wl.fallback.top.surface)
if (_glfw.wl.pointerSurface == window->wl.fallback.top.surface)
{
if (ypos < GLFW_BORDER_SIZE)
cursorName = "n-resize";
}
else if (window->wl.fallback.focus == window->wl.fallback.left.surface)
else if (_glfw.wl.pointerSurface == window->wl.fallback.left.surface)
{
if (ypos < GLFW_BORDER_SIZE)
cursorName = "nw-resize";
else
cursorName = "w-resize";
}
else if (window->wl.fallback.focus == window->wl.fallback.right.surface)
else if (_glfw.wl.pointerSurface == window->wl.fallback.right.surface)
{
if (ypos < GLFW_BORDER_SIZE)
cursorName = "ne-resize";
else
cursorName = "e-resize";
}
else if (window->wl.fallback.focus == window->wl.fallback.bottom.surface)
else if (_glfw.wl.pointerSurface == window->wl.fallback.bottom.surface)
{
if (xpos < GLFW_BORDER_SIZE)
cursorName = "sw-resize";
@ -360,8 +363,12 @@ static void updateFallbackDecorationCursor(_GLFWwindow* window,
static void handleFallbackDecorationButton(_GLFWwindow* window,
uint32_t serial,
uint32_t button)
uint32_t button,
uint32_t state)
{
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
return;
const double xpos = wl_fixed_to_double(window->wl.fallback.pointerX);
const double ypos = wl_fixed_to_double(window->wl.fallback.pointerY);
@ -369,28 +376,28 @@ static void handleFallbackDecorationButton(_GLFWwindow* window,
{
uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
if (window->wl.fallback.focus == window->wl.fallback.top.surface)
if (_glfw.wl.pointerSurface == window->wl.fallback.top.surface)
{
if (ypos < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
else
xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
}
else if (window->wl.fallback.focus == window->wl.fallback.left.surface)
else if (_glfw.wl.pointerSurface == window->wl.fallback.left.surface)
{
if (ypos < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
else
edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
}
else if (window->wl.fallback.focus == window->wl.fallback.right.surface)
else if (_glfw.wl.pointerSurface == window->wl.fallback.right.surface)
{
if (ypos < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
else
edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
}
else if (window->wl.fallback.focus == window->wl.fallback.bottom.surface)
else if (_glfw.wl.pointerSurface == window->wl.fallback.bottom.surface)
{
if (xpos < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
@ -408,7 +415,7 @@ static void handleFallbackDecorationButton(_GLFWwindow* window,
if (!window->wl.xdg.toplevel)
return;
if (window->wl.fallback.focus != window->wl.fallback.top.surface)
if (_glfw.wl.pointerSurface != window->wl.fallback.top.surface)
return;
if (ypos < GLFW_BORDER_SIZE)
@ -1267,14 +1274,16 @@ static void setCursorImage(_GLFWwindow* window,
wl_surface_commit(surface);
}
static void incrementCursorImage(_GLFWwindow* window)
static void incrementCursorImage(void)
{
_GLFWcursor* cursor;
if (!window || !window->wl.hovered)
if (!_glfw.wl.pointerSurface)
return;
cursor = window->wl.currentCursor;
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
if (window->wl.surface != _glfw.wl.pointerSurface)
return;
_GLFWcursor* cursor = window->cursor;
if (cursor && cursor->wl.cursor)
{
cursor->wl.currentImage += 1;
@ -1436,7 +1445,7 @@ static void handleEvents(double* timeout)
uint64_t repeats;
if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8)
incrementCursorImage(_glfw.wl.pointerFocus);
incrementCursorImage();
}
if (fds[LIBDECOR_FD].revents & POLLIN)
@ -1527,16 +1536,14 @@ static void pointerHandleEnter(void* userData,
if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
return;
_GLFWwindow* window = wl_surface_get_user_data(surface);
_glfw.wl.serial = serial;
_glfw.wl.pointerEnterSerial = serial;
_glfw.wl.pointerFocus = window;
_glfw.wl.pointerSurface = surface;
if (surface == window->wl.surface)
_GLFWwindow* window = wl_surface_get_user_data(surface);
if (window->wl.surface == surface)
{
window->wl.hovered = GLFW_TRUE;
_glfwSetCursorWayland(window, window->wl.currentCursor);
_glfwSetCursorWayland(window, window->cursor);
_glfwInputCursorEnter(window, GLFW_TRUE);
if (window->cursorMode != GLFW_CURSOR_DISABLED)
@ -1549,11 +1556,8 @@ static void pointerHandleEnter(void* userData,
else
{
if (window->wl.fallback.decorations)
{
window->wl.fallback.focus = surface;
updateFallbackDecorationCursor(window, sx, sy);
}
}
}
static void pointerHandleLeave(void* userData,
@ -1567,26 +1571,17 @@ static void pointerHandleLeave(void* userData,
if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
return;
_GLFWwindow* window = _glfw.wl.pointerFocus;
if (!window)
return;
_glfw.wl.serial = serial;
_glfw.wl.pointerFocus = NULL;
_glfw.wl.pointerSurface = NULL;
if (window->wl.hovered)
{
window->wl.hovered = GLFW_FALSE;
_GLFWwindow* window = wl_surface_get_user_data(surface);
if (window->wl.surface == surface)
_glfwInputCursorEnter(window, GLFW_FALSE);
}
else
{
if (window->wl.fallback.decorations)
{
window->wl.fallback.focus = NULL;
window->wl.fallback.cursorName = NULL;
}
}
}
static void pointerHandleMotion(void* userData,
@ -1595,14 +1590,15 @@ static void pointerHandleMotion(void* userData,
wl_fixed_t sx,
wl_fixed_t sy)
{
_GLFWwindow* window = _glfw.wl.pointerFocus;
if (!window)
if (!_glfw.wl.pointerSurface)
return;
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
if (window->cursorMode == GLFW_CURSOR_DISABLED)
return;
if (window->wl.hovered)
if (window->wl.surface == _glfw.wl.pointerSurface)
{
window->wl.cursorPosX = wl_fixed_to_double(sx);
window->wl.cursorPosY = wl_fixed_to_double(sy);
@ -1622,11 +1618,12 @@ static void pointerHandleButton(void* userData,
uint32_t button,
uint32_t state)
{
_GLFWwindow* window = _glfw.wl.pointerFocus;
if (!window)
if (!_glfw.wl.pointerSurface)
return;
if (window->wl.hovered)
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
if (window->wl.surface == _glfw.wl.pointerSurface)
{
_glfw.wl.serial = serial;
@ -1638,7 +1635,7 @@ static void pointerHandleButton(void* userData,
else
{
if (window->wl.fallback.decorations)
handleFallbackDecorationButton(window, serial, button);
handleFallbackDecorationButton(window, serial, button, state);
}
}
@ -1648,11 +1645,12 @@ static void pointerHandleAxis(void* userData,
uint32_t axis,
wl_fixed_t value)
{
_GLFWwindow* window = _glfw.wl.pointerFocus;
if (!window)
if (!_glfw.wl.pointerSurface)
return;
if (window->wl.hovered)
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
if (window->wl.surface == _glfw.wl.pointerSurface)
{
// NOTE: 10 units of motion per mouse wheel step seems to be a common ratio
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
@ -1701,7 +1699,7 @@ static void keyboardHandleKeymap(void* userData,
keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context,
mapStr,
XKB_KEYMAP_FORMAT_TEXT_V1,
0);
XKB_KEYMAP_COMPILE_NO_FLAGS);
munmap(mapStr, size);
close(fd);
@ -1932,7 +1930,11 @@ static void seatHandleCapabilities(void* userData,
}
else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer)
{
if (wl_pointer_get_version(_glfw.wl.pointer) >= WL_POINTER_RELEASE_SINCE_VERSION)
wl_pointer_release(_glfw.wl.pointer);
else
wl_pointer_destroy(_glfw.wl.pointer);
_glfw.wl.pointer = NULL;
}
@ -1943,7 +1945,11 @@ static void seatHandleCapabilities(void* userData,
}
else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard)
{
if (wl_keyboard_get_version(_glfw.wl.keyboard) >= WL_KEYBOARD_RELEASE_SINCE_VERSION)
wl_keyboard_release(_glfw.wl.keyboard);
else
wl_keyboard_destroy(_glfw.wl.keyboard);
_glfw.wl.keyboard = NULL;
}
}
@ -2178,9 +2184,6 @@ GLFWbool _glfwCreateWindowWayland(_GLFWwindow* window,
return GLFW_FALSE;
if (ctxconfig->client != GLFW_NO_API)
{
if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||
ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
{
window->wl.egl.window = wl_egl_window_create(window->wl.surface,
window->wl.fbWidth,
@ -2196,15 +2199,6 @@ GLFWbool _glfwCreateWindowWayland(_GLFWwindow* window,
return GLFW_FALSE;
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
{
if (!_glfwInitOSMesa())
return GLFW_FALSE;
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
if (!_glfwRefreshContextAttribs(window, ctxconfig))
return GLFW_FALSE;
}
@ -2223,8 +2217,8 @@ GLFWbool _glfwCreateWindowWayland(_GLFWwindow* window,
void _glfwDestroyWindowWayland(_GLFWwindow* window)
{
if (window == _glfw.wl.pointerFocus)
_glfw.wl.pointerFocus = NULL;
if (window->wl.surface == _glfw.wl.pointerSurface)
_glfw.wl.pointerSurface = NULL;
if (window == _glfw.wl.keyboardFocus)
{
@ -2600,7 +2594,7 @@ GLFWbool _glfwWindowMaximizedWayland(_GLFWwindow* window)
GLFWbool _glfwWindowHoveredWayland(_GLFWwindow* window)
{
return window->wl.hovered;
return window->wl.surface == _glfw.wl.pointerSurface;
}
GLFWbool _glfwFramebufferTransparentWayland(_GLFWwindow* window)
@ -2730,7 +2724,7 @@ void _glfwSetCursorPosWayland(_GLFWwindow* window, double x, double y)
void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode)
{
_glfwSetCursorWayland(window, window->wl.currentCursor);
_glfwSetCursorWayland(window, window->cursor);
}
const char* _glfwGetScancodeNameWayland(int scancode)
@ -3064,11 +3058,7 @@ void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* cursor)
if (!_glfw.wl.pointer)
return;
window->wl.currentCursor = cursor;
// If we're not in the correct window just save the cursor
// the next time the pointer enters the window the cursor will change
if (!window->wl.hovered)
if (window->wl.surface != _glfw.wl.pointerSurface)
return;
// Update pointer lock to match cursor mode

View File

@ -1634,7 +1634,6 @@ void _glfwTerminateX11(void)
_glfw.x11.xi.handle = NULL;
}
_glfwTerminateOSMesa();
// NOTE: These need to be unloaded after XCloseDisplay, as they register
// cleanup callbacks that get called by that function
_glfwTerminateEGL();

View File

@ -1984,11 +1984,6 @@ GLFWbool _glfwCreateWindowX11(_GLFWwindow* window,
if (!_glfwChooseVisualEGL(wndconfig, ctxconfig, fbconfig, &visual, &depth))
return GLFW_FALSE;
}
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
{
if (!_glfwInitOSMesa())
return GLFW_FALSE;
}
}
if (!visual)
@ -2012,11 +2007,6 @@ GLFWbool _glfwCreateWindowX11(_GLFWwindow* window,
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
{
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
if (!_glfwRefreshContextAttribs(window, ctxconfig))
return GLFW_FALSE;
@ -3344,8 +3334,6 @@ GLFWAPI Window glfwGetX11Window(GLFWwindow* handle)
GLFWAPI void glfwSetX11SelectionString(const char* string)
{
assert(string != NULL);
_GLFW_REQUIRE_INIT();
if (_glfw.platform.platformID != GLFW_PLATFORM_X11)
@ -3354,6 +3342,8 @@ GLFWAPI void glfwSetX11SelectionString(const char* string)
return;
}
assert(string != NULL);
_glfw_free(_glfw.x11.primarySelectionString);
_glfw.x11.primarySelectionString = _glfw_strdup(string);

View File

@ -46,7 +46,6 @@
#define API_NAME_NATIVE "native"
#define API_NAME_EGL "egl"
#define API_NAME_OSMESA "osmesa"
#define PROFILE_NAME_CORE "core"
#define PROFILE_NAME_COMPAT "compat"
@ -90,8 +89,7 @@ static void usage(void)
BEHAVIOR_NAME_FLUSH ")\n");
printf(" -c, --context-api=API the context creation API to use ("
API_NAME_NATIVE " or "
API_NAME_EGL " or "
API_NAME_OSMESA ")\n");
API_NAME_EGL ")\n");
printf(" -d, --debug request a debug context\n");
printf(" -f, --forward require a forward-compatible context\n");
printf(" -h, --help show this help\n");
@ -482,8 +480,6 @@ int main(int argc, char** argv)
context_creation_api = GLFW_NATIVE_CONTEXT_API;
else if (strcasecmp(optarg, API_NAME_EGL) == 0)
context_creation_api = GLFW_EGL_CONTEXT_API;
else if (strcasecmp(optarg, API_NAME_OSMESA) == 0)
context_creation_api = GLFW_OSMESA_CONTEXT_API;
else
{
usage();

View File

@ -36,6 +36,14 @@
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
static bool needs_update;
static void window_close_callback(GLFWwindow* window)
{
needs_update = true;
}
static void error_callback(int error, const char* description)
{
@ -45,7 +53,15 @@ static void error_callback(int error, const char* description)
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, GLFW_TRUE);
needs_update = true;
}
}
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
needs_update = true;
}
static float nrand(void)
@ -72,8 +88,11 @@ int main(void)
}
glfwMakeContextCurrent(window);
glfwSwapInterval(0);
gladLoadGL(glfwGetProcAddress);
glfwSetWindowCloseCallback(window, window_close_callback);
glfwSetKeyCallback(window, key_callback);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
while (!glfwWindowShouldClose(window))
{
@ -87,8 +106,18 @@ int main(void)
glClearColor(r / l, g / l, b / l, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
needs_update = false;
glfwWaitEventsTimeout(1.0);
const double start = glfwGetTime();
while (!needs_update)
{
const double elapsed = glfwGetTime() - start;
if (elapsed >= 1.0)
needs_update = true;
else
glfwWaitEventsTimeout(1.0 - elapsed);
}
}
glfwDestroyWindow(window);