Compare commits

..

10 Commits

Author SHA1 Message Date
Camilla Löwy 4e1d7e9266 Cleanup
Related to #786.
2017-09-17 21:20:12 +02:00
Camilla Löwy 243db302bf EGLDevice: Fix build after rebase
Some minor bitrot had occurred since the patch was made.

Related to #786.
2017-09-17 21:17:42 +02:00
Kamal 5b1a187f71 Add EGLDevice backend to GLFW
This adds interface to graphics application to create EGLDisplay
directly over GPU device as enabled by EGLDevice extensions

Fixes #786.
2017-09-17 21:17:42 +02:00
Camilla Löwy f4fb25b63d X11: Fix init order breaking cursor hiding
The hidden cursor was created before Xcursor was loaded.
2017-09-17 16:06:02 +02:00
Camilla Löwy e3be6b8ae0 Cleanup
Break up some overly long lines.
2017-09-17 15:14:22 +02:00
Camilla Löwy 3d110d2e1b X11: Fix selection error nomenclature
[ci skip]
2017-09-17 13:54:17 +02:00
Camilla Löwy 0b5023bc62 X11: Fix Latin-1 text not being converted to UTF-8 2017-09-17 13:50:10 +02:00
Camilla Löwy 9dbc935afb X11: Stop reporting support for COMPOUND_TEXT 2017-09-17 13:50:10 +02:00
Camilla Löwy f7dc6df02c X11: Add support for reading clipboard via INCR
This allows glfwGetClipboardString to retrieve clipboard contents larger
than (typically) 2^18 bytes.

Related to #275.
2017-09-17 13:50:00 +02:00
Camilla Löwy f30acd8f74 Add OSMesa to context API list 2017-09-17 13:46:52 +02:00
33 changed files with 1375 additions and 302 deletions
+23 -2
View File
@@ -41,8 +41,9 @@ if (WIN32)
endif() endif()
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF) option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
option(GLFW_USE_MIR "Use Mir for window creation" OFF) option(GLFW_USE_MIR "Use Mir for window creation" OFF)
option(GLFW_USE_EGLDEVICE "Use EGLDevice for window creation" OFF)
endif() endif()
if (MSVC) if (MSVC)
@@ -163,6 +164,9 @@ elseif (GLFW_USE_MIR)
elseif (GLFW_USE_OSMESA) elseif (GLFW_USE_OSMESA)
set(_GLFW_OSMESA 1) set(_GLFW_OSMESA 1)
message(STATUS "Using OSMesa for headless context creation") message(STATUS "Using OSMesa for headless context creation")
elseif (GLFW_USE_EGLDEVICE)
set(_GLFW_EGLDEVICE 1)
message(STATUS "Using EGLDevice for window creation")
elseif (WIN32) elseif (WIN32)
set(_GLFW_WIN32 1) set(_GLFW_WIN32 1)
message(STATUS "Using Win32 for window creation") message(STATUS "Using Win32 for window creation")
@@ -291,6 +295,23 @@ if (_GLFW_WAYLAND)
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}") list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
endif() endif()
#--------------------------------------------------------------------
# Use EGLDevice for window creation
#--------------------------------------------------------------------
if (_GLFW_EGLDEVICE)
find_path(DRM_INCLUDE_DIR NAMES drm.h PATH_SUFFIXES drm libdrm)
if (NOT DRM_INCLUDE_DIR)
message(FATAL_ERROR "The libdrm headers were not found")
endif()
list(APPEND glfw_INCLUDE_DIRS "${DRM_INCLUDE_DIR}")
list(APPEND glfw_LIBRARIES "-ldrm")
list(APPEND glfw_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}")
endif()
#-------------------------------------------------------------------- #--------------------------------------------------------------------
# Use Mir for window creation # Use Mir for window creation
#-------------------------------------------------------------------- #--------------------------------------------------------------------
+13 -6
View File
@@ -11,8 +11,9 @@ application development. It provides a simple, platform-independent API for
creating windows, contexts and surfaces, reading input, handling events, etc. creating windows, contexts and surfaces, reading input, handling events, etc.
GLFW natively supports Windows, macOS and Linux and other Unix-like systems. GLFW natively supports Windows, macOS and Linux and other Unix-like systems.
Experimental implementations for the Wayland protocol and the Mir display server Experimental implementations for the Wayland protocol, the Mir display server
are available but not yet officially supported. and direct rendering via EGLDevice are available but not yet officially
supported.
GLFW is licensed under the [zlib/libpng GLFW is licensed under the [zlib/libpng
license](http://www.glfw.org/license.html). license](http://www.glfw.org/license.html).
@@ -45,8 +46,8 @@ guide](http://www.glfw.org/docs/latest/moving.html) for moving to the GLFW
## Compiling GLFW ## Compiling GLFW
GLFW itself requires only the headers and libraries for your window system. It GLFW itself requires only the headers and libraries for your window system. It
does not need the headers for any context creation API (WGL, GLX, EGL, NSGL) or does not need the headers for any context creation API (WGL, GLX, EGL, NSGL,
rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them. OSMesa) or rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them.
GLFW supports compilation on Windows with Visual C++ 2010 and later, MinGW and GLFW supports compilation on Windows with Visual C++ 2010 and later, MinGW and
MinGW-w64, on macOS with Clang and on Linux and other Unix-like systems with GCC MinGW-w64, on macOS with Clang and on Linux and other Unix-like systems with GCC
@@ -91,6 +92,9 @@ GLFW itself depends only on the headers and libraries for your window system.
The (experimental) Wayland backend also depends on the `extra-cmake-modules` The (experimental) Wayland backend also depends on the `extra-cmake-modules`
package, which is used to generated Wayland protocol headers. package, which is used to generated Wayland protocol headers.
The (experimental) EGLDevice backend also depends on the `libdrm-dev`
development package.
The examples and test programs depend on a number of tiny libraries. These are The examples and test programs depend on a number of tiny libraries. These are
located in the `deps/` directory. located in the `deps/` directory.
@@ -138,8 +142,6 @@ information on what to include when reporting a bug.
for retrieving gamepad input state (#900) for retrieving gamepad input state (#900)
- Added `glfwRequestWindowAttention` function for requesting attention from the - Added `glfwRequestWindowAttention` function for requesting attention from the
user (#732,#988) user (#732,#988)
- Added `glfwGetEventTime` function for querying the time of the last input
event (#1012)
- Added `glfwGetKeyScancode` function that allows retrieving platform dependent - Added `glfwGetKeyScancode` function that allows retrieving platform dependent
scancodes for keys (#830) scancodes for keys (#830)
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for - Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
@@ -207,6 +209,10 @@ information on what to include when reporting a bug.
- [X11] Bugfix: IM-duplicated key events would leak at low polling rates (#747) - [X11] Bugfix: IM-duplicated key events would leak at low polling rates (#747)
- [X11] Bugfix: Gamma ramp setting via RandR did not validate ramp size - [X11] Bugfix: Gamma ramp setting via RandR did not validate ramp size
- [X11] Bugfix: Key name string encoding depended on current locale (#981,#983) - [X11] Bugfix: Key name string encoding depended on current locale (#981,#983)
- [X11] Bugfix: Incremental reading of selections was not supported (#275)
- [X11] Bugfix: Selection I/O reported but did not support `COMPOUND_TEXT`
- [X11] Bugfix: Latin-1 text read from selections was not converted to UTF-8
- [Linux] Added experimental support for direct rendering via EGLDevice (#786)
- [Linux] Moved to evdev for joystick input (#906,#1005) - [Linux] Moved to evdev for joystick input (#906,#1005)
- [Linux] Bugfix: Event processing did not detect joystick disconnection (#932) - [Linux] Bugfix: Event processing did not detect joystick disconnection (#932)
- [Linux] Bugfix: The joystick device path could be truncated (#1025) - [Linux] Bugfix: The joystick device path could be truncated (#1025)
@@ -281,6 +287,7 @@ skills.
- David Carlier - David Carlier
- Arturo Castro - Arturo Castro
- Chi-kwan Chan - Chi-kwan Chan
- Kamal Chandra
- Ian Clarkson - Ian Clarkson
- Michał Cichoń - Michał Cichoń
- Lambert Clara - Lambert Clara
+1
View File
@@ -257,6 +257,7 @@ ramps and clipboard. The options are:
- @b _GLFW_WAYLAND to use the Wayland API (experimental and incomplete) - @b _GLFW_WAYLAND to use the Wayland API (experimental and incomplete)
- @b _GLFW_MIR to use the Mir API (experimental and incomplete) - @b _GLFW_MIR to use the Mir API (experimental and incomplete)
- @b _GLFW_OSMESA to use the OSMesa API (headless and non-interactive) - @b _GLFW_OSMESA to use the OSMesa API (headless and non-interactive)
- @b _GLFW_EGLDEVICE to use the EGLDevice API (experimental and incomplete)
If you are building GLFW as a shared library / dynamic library / DLL then you 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. must also define @b _GLFW_BUILD_DLL. Otherwise, you must not define it.
-25
View File
@@ -3366,31 +3366,6 @@ GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window,
*/ */
GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun cbfun); GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun cbfun);
/*! @brief Returns the time of the last input event.
*
* This function returns the time, in seconds, that the last input event
* occurred. The time is collected for key, mouse button, scrolling and cursor
* position events including enter and leave. The function is intended to be
* called from the relevant event callback.
*
* @return The time of the input event, in seconds, or zero if an
* [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @remarks The event timestamps provided by most platforms have much lower
* resolution than the GLFW timer.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref events
*
* @since Added in version 3.3.
*
* @ingroup window
*/
GLFWAPI double glfwGetEventTime(void);
/*! @brief Processes all pending events. /*! @brief Processes all pending events.
* *
* This function processes only those events that are already in the event * This function processes only those events that are already in the event
+7 -1
View File
@@ -47,6 +47,12 @@ elseif (_GLFW_WAYLAND)
PROTOCOL PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml" "${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml"
BASENAME pointer-constraints-unstable-v1) BASENAME pointer-constraints-unstable-v1)
elseif(_GLFW_EGLDEVICE)
set(glfw_HEADERS ${common_HEADERS} egldevice_platform.h linux_joystick.h
posix_time.h posix_thread.h xkb_unicode.h egl_context.h)
set(glfw_SOURCES ${common_SOURCES} egldevice_init.c egldevice_monitor.c egldevice_window.c
linux_joystick.c posix_time.c posix_thread.c xkb_unicode.c
egl_context.c)
elseif (_GLFW_MIR) elseif (_GLFW_MIR)
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
posix_time.h posix_thread.h xkb_unicode.h egl_context.h posix_time.h posix_thread.h xkb_unicode.h egl_context.h
@@ -88,7 +94,7 @@ set_target_properties(glfw PROPERTIES
target_compile_definitions(glfw PRIVATE target_compile_definitions(glfw PRIVATE
_GLFW_USE_CONFIG_H _GLFW_USE_CONFIG_H
$<$<BOOL:${UNIX}>:_XOPEN_SOURCE=600>) $<$<BOOL:${UNIX}>:_POSIX_C_SOURCE=200809L>)
target_include_directories(glfw PUBLIC target_include_directories(glfw PUBLIC
"$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>" "$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>") "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>")
+5 -3
View File
@@ -215,8 +215,9 @@ static GLFWbool updateUnicodeDataNS(void)
return GLFW_FALSE; return GLFW_FALSE;
} }
_glfw.ns.unicodeData = TISGetInputSourceProperty(_glfw.ns.inputSource, _glfw.ns.unicodeData =
kTISPropertyUnicodeKeyLayoutData); TISGetInputSourceProperty(_glfw.ns.inputSource,
kTISPropertyUnicodeKeyLayoutData);
if (!_glfw.ns.unicodeData) if (!_glfw.ns.unicodeData)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
@@ -232,7 +233,8 @@ static GLFWbool updateUnicodeDataNS(void)
static GLFWbool initializeTIS(void) static GLFWbool initializeTIS(void)
{ {
// This works only because Cocoa has already loaded it properly // This works only because Cocoa has already loaded it properly
_glfw.ns.tis.bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox")); _glfw.ns.tis.bundle =
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
if (!_glfw.ns.tis.bundle) if (!_glfw.ns.tis.bundle)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
+5 -2
View File
@@ -73,7 +73,9 @@ static long getElementValue(_GLFWjoystick* js, _GLFWjoyelementNS* element)
// Comparison function for matching the SDL element order // Comparison function for matching the SDL element order
// //
static CFComparisonResult compareElements(const void* fp, const void* sp, void* user) static CFComparisonResult compareElements(const void* fp,
const void* sp,
void* user)
{ {
const _GLFWjoyelementNS* fe = fp; const _GLFWjoyelementNS* fe = fp;
const _GLFWjoyelementNS* se = sp; const _GLFWjoyelementNS* se = sp;
@@ -183,7 +185,8 @@ static void matchCallback(void* context,
for (i = 0; i < CFArrayGetCount(elements); i++) for (i = 0; i < CFArrayGetCount(elements); i++)
{ {
IOHIDElementRef native = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, i); IOHIDElementRef native = (IOHIDElementRef)
CFArrayGetValueAtIndex(elements, i);
if (CFGetTypeID(native) != IOHIDElementGetTypeID()) if (CFGetTypeID(native) != IOHIDElementGetTypeID())
continue; continue;
+14 -3
View File
@@ -54,7 +54,8 @@ static char* getDisplayName(CGDirectDisplayID displayID)
while ((service = IOIteratorNext(it)) != 0) while ((service = IOIteratorNext(it)) != 0)
{ {
info = IODisplayCreateInfoDictionary(service, kIODisplayOnlyPreferredName); info = IODisplayCreateInfoDictionary(service,
kIODisplayOnlyPreferredName);
CFNumberRef vendorIDRef = CFNumberRef vendorIDRef =
CFDictionaryGetValue(info, CFSTR(kDisplayVendorID)); CFDictionaryGetValue(info, CFSTR(kDisplayVendorID));
@@ -185,7 +186,13 @@ static CGDisplayFadeReservationToken beginFadeReservation(void)
CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken; CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken;
if (CGAcquireDisplayFadeReservation(5, &token) == kCGErrorSuccess) if (CGAcquireDisplayFadeReservation(5, &token) == kCGErrorSuccess)
CGDisplayFade(token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE); {
CGDisplayFade(token, 0.3,
kCGDisplayBlendNormal,
kCGDisplayBlendSolidColor,
0.0, 0.0, 0.0,
TRUE);
}
return token; return token;
} }
@@ -196,7 +203,11 @@ static void endFadeReservation(CGDisplayFadeReservationToken token)
{ {
if (token != kCGDisplayFadeReservationInvalidToken) if (token != kCGDisplayFadeReservationInvalidToken)
{ {
CGDisplayFade(token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); CGDisplayFade(token, 0.5,
kCGDisplayBlendSolidColor,
kCGDisplayBlendNormal,
0.0, 0.0, 0.0,
FALSE);
CGReleaseDisplayFadeReservation(token); CGReleaseDisplayFadeReservation(token);
} }
} }
-3
View File
@@ -118,9 +118,6 @@ typedef struct _GLFWlibraryNS
// The window whose disabled cursor mode is active // The window whose disabled cursor mode is active
_GLFWwindow* disabledCursorWindow; _GLFWwindow* disabledCursorWindow;
// The time of the last event
double lastEventTime;
struct { struct {
CFBundleRef bundle; CFBundleRef bundle;
PFN_TISCopyCurrentKeyboardLayoutInputSource CopyCurrentKeyboardLayoutInputSource; PFN_TISCopyCurrentKeyboardLayoutInputSource CopyCurrentKeyboardLayoutInputSource;
-31
View File
@@ -446,8 +446,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)mouseDown:(NSEvent *)event - (void)mouseDown:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
_glfwInputMouseClick(window, _glfwInputMouseClick(window,
GLFW_MOUSE_BUTTON_LEFT, GLFW_MOUSE_BUTTON_LEFT,
GLFW_PRESS, GLFW_PRESS,
@@ -456,15 +454,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)mouseDragged:(NSEvent *)event - (void)mouseDragged:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
[self mouseMoved:event]; [self mouseMoved:event];
} }
- (void)mouseUp:(NSEvent *)event - (void)mouseUp:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
_glfwInputMouseClick(window, _glfwInputMouseClick(window,
GLFW_MOUSE_BUTTON_LEFT, GLFW_MOUSE_BUTTON_LEFT,
GLFW_RELEASE, GLFW_RELEASE,
@@ -473,8 +467,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)mouseMoved:(NSEvent *)event - (void)mouseMoved:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
{ {
const double dx = [event deltaX] - window->ns.cursorWarpDeltaX; const double dx = [event deltaX] - window->ns.cursorWarpDeltaX;
@@ -498,8 +490,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)rightMouseDown:(NSEvent *)event - (void)rightMouseDown:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
_glfwInputMouseClick(window, _glfwInputMouseClick(window,
GLFW_MOUSE_BUTTON_RIGHT, GLFW_MOUSE_BUTTON_RIGHT,
GLFW_PRESS, GLFW_PRESS,
@@ -508,15 +498,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)rightMouseDragged:(NSEvent *)event - (void)rightMouseDragged:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
[self mouseMoved:event]; [self mouseMoved:event];
} }
- (void)rightMouseUp:(NSEvent *)event - (void)rightMouseUp:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
_glfwInputMouseClick(window, _glfwInputMouseClick(window,
GLFW_MOUSE_BUTTON_RIGHT, GLFW_MOUSE_BUTTON_RIGHT,
GLFW_RELEASE, GLFW_RELEASE,
@@ -525,8 +511,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)otherMouseDown:(NSEvent *)event - (void)otherMouseDown:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
_glfwInputMouseClick(window, _glfwInputMouseClick(window,
(int) [event buttonNumber], (int) [event buttonNumber],
GLFW_PRESS, GLFW_PRESS,
@@ -535,15 +519,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)otherMouseDragged:(NSEvent *)event - (void)otherMouseDragged:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
[self mouseMoved:event]; [self mouseMoved:event];
} }
- (void)otherMouseUp:(NSEvent *)event - (void)otherMouseUp:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
_glfwInputMouseClick(window, _glfwInputMouseClick(window,
(int) [event buttonNumber], (int) [event buttonNumber],
GLFW_RELEASE, GLFW_RELEASE,
@@ -608,8 +588,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
const int key = translateKey([event keyCode]); const int key = translateKey([event keyCode]);
const int mods = translateFlags([event modifierFlags]); const int mods = translateFlags([event modifierFlags]);
_glfw.ns.lastEventTime = [event timestamp];
_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods); _glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
[self interpretKeyEvents:[NSArray arrayWithObject:event]]; [self interpretKeyEvents:[NSArray arrayWithObject:event]];
@@ -641,9 +619,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
{ {
const int key = translateKey([event keyCode]); const int key = translateKey([event keyCode]);
const int mods = translateFlags([event modifierFlags]); const int mods = translateFlags([event modifierFlags]);
_glfw.ns.lastEventTime = [event timestamp];
_glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods); _glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods);
} }
@@ -1487,12 +1462,6 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
[window->ns.object setLevel:NSNormalWindowLevel]; [window->ns.object setLevel:NSNormalWindowLevel];
} }
double _glfwPlatformGetEventTime(void)
{
/* Windows events are stored in seconds */
return _glfw.ns.lastEventTime;
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
for (;;) for (;;)
+16
View File
@@ -116,10 +116,18 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER) if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
continue; continue;
#if defined(_GLFW_EGLDEVICE)
// Only consider stream EGLConfigs
if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_STREAM_BIT_KHR))
continue;
#else
// Only consider window EGLConfigs // Only consider window EGLConfigs
if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT)) if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
continue; continue;
#endif
#if defined(_GLFW_X11) #if defined(_GLFW_X11)
// Only consider EGLConfigs with associated Visuals // Only consider EGLConfigs with associated Visuals
if (!getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID)) if (!getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
@@ -376,6 +384,9 @@ GLFWbool _glfwInitEGL(void)
return GLFW_FALSE; return GLFW_FALSE;
} }
// For EGLDevice backend the display gets initialized
// in _glfwPlatformInit()
#if !defined(_GLFW_EGLDEVICE)
_glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY); _glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
if (_glfw.egl.display == EGL_NO_DISPLAY) if (_glfw.egl.display == EGL_NO_DISPLAY)
{ {
@@ -396,6 +407,7 @@ GLFWbool _glfwInitEGL(void)
_glfwTerminateEGL(); _glfwTerminateEGL();
return GLFW_FALSE; return GLFW_FALSE;
} }
#endif
_glfw.egl.KHR_create_context = _glfw.egl.KHR_create_context =
extensionSupportedEGL("EGL_KHR_create_context"); extensionSupportedEGL("EGL_KHR_create_context");
@@ -581,6 +593,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
setAttrib(EGL_NONE, EGL_NONE); setAttrib(EGL_NONE, EGL_NONE);
} }
// The surface for EGLDevice backened is created in _glfwPlatformCreateWindow
//
#if !defined (_GLFW_EGLDEVICE)
window->context.egl.surface = window->context.egl.surface =
eglCreateWindowSurface(_glfw.egl.display, eglCreateWindowSurface(_glfw.egl.display,
config, config,
@@ -593,6 +608,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
getEGLErrorString(eglGetError())); getEGLErrorString(eglGetError()));
return GLFW_FALSE; return GLFW_FALSE;
} }
#endif
window->context.egl.config = config; window->context.egl.config = config;
+7
View File
@@ -47,6 +47,10 @@ typedef struct wl_egl_window* EGLNativeWindowType;
#define EGLAPIENTRY #define EGLAPIENTRY
typedef MirEGLNativeDisplayType EGLNativeDisplayType; typedef MirEGLNativeDisplayType EGLNativeDisplayType;
typedef MirEGLNativeWindowType EGLNativeWindowType; typedef MirEGLNativeWindowType EGLNativeWindowType;
#elif defined(_GLFW_EGLDEVICE)
#define EGLAPIENTRY
typedef void* EGLNativeDisplayType;
typedef int EGLNativeWindowType;
#else #else
#error "No supported EGL platform selected" #error "No supported EGL platform selected"
#endif #endif
@@ -84,6 +88,8 @@ typedef MirEGLNativeWindowType EGLNativeWindowType;
#define EGL_OPENGL_ES_API 0x30a0 #define EGL_OPENGL_ES_API 0x30a0
#define EGL_OPENGL_API 0x30a2 #define EGL_OPENGL_API 0x30a2
#define EGL_NONE 0x3038 #define EGL_NONE 0x3038
#define EGL_WIDTH 0x3057
#define EGL_HEIGHT 0x3056
#define EGL_EXTENSIONS 0x3055 #define EGL_EXTENSIONS 0x3055
#define EGL_CONTEXT_CLIENT_VERSION 0x3098 #define EGL_CONTEXT_CLIENT_VERSION 0x3098
#define EGL_NATIVE_VISUAL_ID 0x302e #define EGL_NATIVE_VISUAL_ID 0x302e
@@ -118,6 +124,7 @@ typedef void* EGLConfig;
typedef void* EGLContext; typedef void* EGLContext;
typedef void* EGLDisplay; typedef void* EGLDisplay;
typedef void* EGLSurface; typedef void* EGLSurface;
typedef intptr_t EGLAttrib;
// EGL function pointer typedefs // EGL function pointer typedefs
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*); typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*);
+284
View File
@@ -0,0 +1,284 @@
//========================================================================
// GLFW 3.3 EGLDevice - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
//
// 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 <linux/limits.h>
static GLFWbool initializeExtensions(void)
{
_glfw.egldevice.QueryDevicesEXT =
(PFNEGLQUERYDEVICESEXTPROC)
eglGetProcAddress("eglQueryDevicesEXT");
_glfw.egldevice.QueryDeviceStringEXT =
(PFNEGLQUERYDEVICESTRINGEXTPROC)
eglGetProcAddress("eglQueryDeviceStringEXT");
_glfw.egldevice.GetPlatformDisplayEXT =
(PFNEGLGETPLATFORMDISPLAYEXTPROC)
eglGetProcAddress("eglGetPlatformDisplayEXT");
_glfw.egldevice.GetOutputLayersEXT =
(PFNEGLGETOUTPUTLAYERSEXTPROC)
eglGetProcAddress("eglGetOutputLayersEXT");
_glfw.egldevice.CreateStreamKHR =
(PFNEGLCREATESTREAMKHRPROC)
eglGetProcAddress("eglCreateStreamKHR");
_glfw.egldevice.DestroyStreamKHR =
(PFNEGLDESTROYSTREAMKHRPROC)
eglGetProcAddress("eglDestroyStreamKHR");
_glfw.egldevice.StreamConsumerOutputEXT =
(PFNEGLSTREAMCONSUMEROUTPUTEXTPROC)
eglGetProcAddress("eglStreamConsumerOutputEXT");
_glfw.egldevice.CreateStreamProducerSurfaceKHR =
(PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC)
eglGetProcAddress("eglCreateStreamProducerSurfaceKHR");
if(!_glfw.egldevice.QueryDevicesEXT ||
!_glfw.egldevice.QueryDeviceStringEXT ||
!_glfw.egldevice.GetPlatformDisplayEXT ||
!_glfw.egldevice.GetOutputLayersEXT ||
!_glfw.egldevice.CreateStreamKHR ||
!_glfw.egldevice.DestroyStreamKHR ||
!_glfw.egldevice.StreamConsumerOutputEXT ||
!_glfw.egldevice.CreateStreamProducerSurfaceKHR)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Failed to find required EGL extension functions");
return GLFW_FALSE;
}
return GLFW_TRUE;
}
static EGLDeviceEXT getEGLDevice(void)
{
int i, num_devs;
EGLDeviceEXT* egl_devs, eglDevice;
const char *clientExtensionString;
eglDevice = EGL_NO_DEVICE_EXT;
clientExtensionString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
if (!_glfwStringInExtensionString("EGL_EXT_device_base",
clientExtensionString) &&
(!_glfwStringInExtensionString("EGL_EXT_device_enumeration",
clientExtensionString) ||
!_glfwStringInExtensionString("EGL_EXT_device_query",
clientExtensionString)))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: EGL_EXT_device base extensions not found");
}
if (!eglQueryDevicesEXT(0, NULL, &num_devs))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Falied to query EGLDevice");
}
if (num_devs < 1)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: No devices found");
}
egl_devs = calloc(sizeof(EGLDeviceEXT), num_devs);
if (egl_devs == NULL)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Unable to allocate memory for device storage");
}
// Select suitable device
if (!eglQueryDevicesEXT(num_devs, egl_devs, &num_devs))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Failed to query EGL devices");
}
for (i = 0; i <= num_devs; i++)
{
const char* deviceExtensionString;
deviceExtensionString = eglQueryDeviceStringEXT(egl_devs[i], EGL_EXTENSIONS);
if (_glfwStringInExtensionString("EGL_EXT_device_drm",
deviceExtensionString))
{
eglDevice = egl_devs[i];
break;
}
}
free(egl_devs);
if (eglDevice == EGL_NO_DEVICE_EXT)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Missing required extension EGL_EXT_device_drm");
}
return eglDevice;
}
static int getDRMFd(EGLDeviceEXT eglDevice)
{
int drm_fd;
const char* drmName;
drmName = eglQueryDeviceStringEXT(eglDevice, EGL_DRM_DEVICE_FILE_EXT);
if (!drmName || (strnlen(drmName, PATH_MAX) == 0))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Couldn't obtain device file from 0x%p",
(void*)(uintptr_t)eglDevice);
}
drm_fd = drmOpen(drmName, NULL);
if (drm_fd < 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Couldn't open device file '%s'", drmName);
}
return drm_fd;
}
static GLFWbool initEGLDisplay(EGLDeviceEXT egl_dev, int drm_fd)
{
const char* displayExtensionString;
EGLint displayAttribs[] = {
EGL_DRM_MASTER_FD_EXT,
drm_fd,
EGL_NONE
};
_glfw.egl.display = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT,
(void*)egl_dev,
displayAttribs);
if (_glfw.egl.display == EGL_NO_DISPLAY)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Couldn't obtain EGLDisplay for device");
return GLFW_FALSE;
}
if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor))
{
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to initialize EGL");
return GLFW_FALSE;
}
// Check for stream_consumer_egloutput + output_drm support
displayExtensionString = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
if (!_glfwStringInExtensionString("EGL_EXT_output_base",
displayExtensionString))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Missing required extension EGL_EXT_output_base");
return GLFW_FALSE;
}
if (!_glfwStringInExtensionString("EGL_EXT_output_drm",
displayExtensionString))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Missing required extension EGL_EXT_output_drm");
return GLFW_FALSE;
}
if (!_glfwStringInExtensionString("EGL_KHR_stream",
displayExtensionString))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Missing required extension EGL_KHR_stream");
return GLFW_FALSE;
}
if (!_glfwStringInExtensionString("EGL_KHR_stream_producer_eglsurface",
displayExtensionString))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Missing required extension EGL_KHR_stream_producer_eglsurface");
return GLFW_FALSE;
}
if (!_glfwStringInExtensionString("EGL_EXT_stream_consumer_egloutput",
displayExtensionString))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Missing required extension EGL_EXT_stream_consumer_egloutput");
return GLFW_FALSE;
}
return GLFW_TRUE;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformInit(void)
{
EGLDeviceEXT egl_dev;
int drm_fd;
// Initialize EGL
if (!_glfwInitEGL())
return GLFW_FALSE;
// Initialize global data and extension function pointers
if (!initializeExtensions())
return GLFW_FALSE;
// Query and Obtain EGLDevice
egl_dev = getEGLDevice();
// Obtain and open DRM device file
drm_fd = getDRMFd(egl_dev);
// Store for use later
_glfw.egldevice.drmFd = drm_fd;
// Obtain EGLDisplay
if (!initEGLDisplay(egl_dev, drm_fd))
return GLFW_FALSE;
_glfwInitTimerPOSIX();
_glfwPollMonitorsEGLDevice();
return GLFW_TRUE;
}
void _glfwPlatformTerminate(void)
{
_glfwTerminateEGL();
_glfwTerminateJoysticksLinux();
}
const char* _glfwPlatformGetVersionString(void)
{
return _GLFW_VERSION_NUMBER "EGLDevice EGL"
#if defined(_GLFW_BUILD_DLL)
" shared"
#endif
;
}
+165
View File
@@ -0,0 +1,165 @@
//========================================================================
// GLFW 3.3 EGLDevice - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
//
// 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"
static GLFWbool pickConnector(_GLFWmonitor* monitor, int drm_fd, drmModeRes* res_info)
{
int i, j;
// Getting suitable connector, encoder and crtc
for (i = 0; i < res_info->count_connectors; i++)
{
monitor->egldevice.connId = res_info->connectors[i];
drmModeConnector* conn_info;
conn_info =
drmModeGetConnector(drm_fd, monitor->egldevice.connId);
if (!conn_info)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Unable to obtain info for connector (%d)",
monitor->egldevice.connId);
return GLFW_FALSE;
}
if (conn_info->connection == DRM_MODE_CONNECTED &&
conn_info->count_modes > 0 &&
conn_info->count_encoders > 0)
{
monitor->egldevice.encId = conn_info->encoders[0];
drmModeEncoder* enc_info;
enc_info =
drmModeGetEncoder(drm_fd, monitor->egldevice.encId);
if (!enc_info) {
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Unable to query DRM-KMS information for connector index %d", i);
}
// Select the modesize
monitor->currentMode.width = (int)conn_info->modes[0].hdisplay;
monitor->currentMode.height = (int)conn_info->modes[0].vdisplay;
monitor->currentMode.refreshRate = (int)conn_info->modes[0].vrefresh;
monitor->modeCount = (int)conn_info->count_modes;
monitor->name = conn_info->modes[0].name;
for (j = 0; j < res_info->count_crtcs; j++)
{
if ((enc_info->possible_crtcs & (1 << j)) == 0)
continue;
monitor->egldevice.crtcId = res_info->crtcs[j];
monitor->egldevice.crtcIndex = j;
if (res_info->crtcs[i] == enc_info->crtc_id)
break;
}
if (monitor->egldevice.crtcId == 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Unable to select suitable CRTC");
return GLFW_FALSE;
}
drmModeFreeEncoder(enc_info);
}
drmModeFreeConnector(conn_info);
}
return GLFW_TRUE;
}
static GLFWbool initDRMResources(_GLFWmonitor* monitor, int drm_fd)
{
drmModeRes* res_info;
res_info = drmModeGetResources(drm_fd);
if (!res_info)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Couldn't obtain DRM-KMS resources");
return GLFW_FALSE;
}
if(!pickConnector(monitor, drm_fd, res_info))
return GLFW_FALSE;
drmModeFreeResources(res_info);
return GLFW_TRUE;
}
/////////////////////////////////////////////////////////////////////////////
/////////// GLFW platform API //////////////
/////////////////////////////////////////////////////////////////////////////
void _glfwPollMonitorsEGLDevice(void)
{
_GLFWmonitor* monitor = _glfwAllocMonitor("Monitor", 0, 0);
// Obtain DRM resource info
if (!initDRMResources(monitor, _glfw.egldevice.drmFd))
{
_glfwFreeMonitor(monitor);
return;
}
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_FIRST);
}
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetMonitorPos not implemented");
}
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetVideoModes not implemented");
*found = 0;
return NULL;
}
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetVideoMode not implemented");
}
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetGammaRamp not implemented");
}
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetGammaRamp not implemented");
}
+151
View File
@@ -0,0 +1,151 @@
//========================================================================
// GLFW 3.3 EGLDevice - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
//
// 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 <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <dlfcn.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <drm_fourcc.h>
#include "posix_time.h"
#include "linux_joystick.h"
#include "posix_thread.h"
#include "egl_context.h"
#include "osmesa_context.h"
#define EGL_NO_DEVICE_EXT ((EGLDeviceEXT) 0)
#define EGL_DRM_DEVICE_FILE_EXT 0x3233
#define EGL_PLATFORM_DEVICE_EXT 0x313f
#define EGL_DRM_MASTER_FD_EXT 0x333c
#define EGL_STREAM_FIFO_LENGTH_KHR 0x31fc
#define EGL_DRM_CRTC_EXT 0x3234
#define EGL_NO_STREAM_KHR ((EGLStreamKHR) 0)
#define EGL_STREAM_BIT_KHR 0x0800
typedef void* EGLOutputLayerEXT;
typedef void* EGLStreamKHR;
typedef void* EGLDeviceEXT;
typedef EGLBoolean (EGLAPIENTRY * PFNEGLQUERYDEVICESEXTPROC)(EGLint,EGLDeviceEXT*,EGLint*);
typedef const char *(EGLAPIENTRY * PFNEGLQUERYDEVICESTRINGEXTPROC)(EGLDeviceEXT,EGLint);
typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum,void*,const EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETOUTPUTLAYERSEXTPROC)(EGLDisplay,const EGLAttrib*,EGLOutputLayerEXT*,EGLint,EGLint*);
typedef EGLStreamKHR (EGLAPIENTRY * PFNEGLCREATESTREAMKHRPROC)(EGLDisplay,const EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYSTREAMKHRPROC)(EGLDisplay,EGLStreamKHR);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSTREAMCONSUMEROUTPUTEXTPROC)(EGLDisplay,EGLStreamKHR,EGLOutputLayerEXT);
typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC)(EGLDisplay,EGLConfig,EGLStreamKHR,const EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSTREAMATTRIBKHRPROC)(EGLDisplay,EGLStreamKHR,EGLenum,EGLint);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSTREAMCONSUMERACQUIREATTRIBKHRPROC)(EGLDisplay,EGLStreamKHR,const EGLAttrib*);
#define eglQueryDevicesEXT _glfw.egldevice.QueryDevicesEXT
#define eglQueryDeviceStringEXT _glfw.egldevice.QueryDeviceStringEXT
#define eglGetPlatformDisplayEXT _glfw.egldevice.GetPlatformDisplayEXT
#define eglGetOutputLayersEXT _glfw.egldevice.GetOutputLayersEXT
#define eglCreateStreamKHR _glfw.egldevice.CreateStreamKHR
#define eglDestroyStreamKHR _glfw.egldevice.DestroyStreamKHR
#define eglStreamConsumerOutputEXT _glfw.egldevice.StreamConsumerOutputEXT
#define eglCreateStreamProducerSurfaceKHR _glfw.egldevice.CreateStreamProducerSurfaceKHR
#define eglStreamAttribKHR _glfw.egldevice.StreamAttribKHR
#define eglStreamConsumerAcquireAttribKHR _glfw.egldevice.StreamConsumerAcquireAttribKHR
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle)
#define _glfw_dlsym(handle, name) dlsym(handle, name)
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType)window->egldevice.handle)
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowEGLDevice egldevice
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryEGLDevice egldevice
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorEGLDevice egldevice
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorEGLDevice egldevice
#define _GLFW_PLATFORM_CONTEXT_STATE
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
// EGLDevice-specific per-window data
//
typedef struct _GLFWwindowEGLDevice
{
int xsurfsize, ysurfsize;
int xoffset, yoffset;
int fifo;
uint32_t planeId;
EGLDisplay handle;
EGLOutputLayerEXT eglLayer;
EGLStreamKHR eglStream;
} _GLFWwindowEGLDevice;
// EGLDevice-specific global data
//
typedef struct _GLFWlibraryEGLDevice
{
int drmFd;
PFNEGLQUERYDEVICESEXTPROC QueryDevicesEXT;
PFNEGLQUERYDEVICESTRINGEXTPROC QueryDeviceStringEXT;
PFNEGLGETPLATFORMDISPLAYEXTPROC GetPlatformDisplayEXT;
PFNEGLGETOUTPUTLAYERSEXTPROC GetOutputLayersEXT;
PFNEGLCREATESTREAMKHRPROC CreateStreamKHR;
PFNEGLDESTROYSTREAMKHRPROC DestroyStreamKHR;
PFNEGLSTREAMCONSUMEROUTPUTEXTPROC StreamConsumerOutputEXT;
PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC CreateStreamProducerSurfaceKHR;
PFNEGLSTREAMATTRIBKHRPROC StreamAttribKHR;
PFNEGLSTREAMCONSUMERACQUIREATTRIBKHRPROC StreamConsumerAcquireAttribKHR;
} _GLFWlibraryEGLDevice;
// EGLDevice-specific per-monitor data
//
typedef struct _GLFWmonitorEGLDevice
{
int crtcIndex;
uint32_t connId, encId, crtcId;
} _GLFWmonitorEGLDevice;
// EGLDevice-specific per-cursor data
//
typedef struct _GLFWcursorEGLDevice
{
} _GLFWcursorEGLDevice;
void _glfwPollMonitorsEGLDevice(void);
+430
View File
@@ -0,0 +1,430 @@
//========================================================================
// GLFW 3.3 EGLDevice - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
//
// 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"
///////////////////////////////////////////////////////////////////////////
//////// GLFW platform API /////////////
///////////////////////////////////////////////////////////////////////////
int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
int n;
_GLFWmonitor* monitor;
EGLAttrib layerAttribs[] = { EGL_NONE, EGL_NONE, EGL_NONE };
EGLint streamAttribs[] = { EGL_STREAM_FIFO_LENGTH_KHR,
window->egldevice.fifo, EGL_NONE };
EGLint surfaceAttribs[] = { EGL_WIDTH, 0, EGL_HEIGHT, 0, EGL_NONE };
if (window->monitor)
monitor = window->monitor;
else
monitor = _glfw.monitors[0];
window->egldevice.xsurfsize = wndconfig->width;
window->egldevice.ysurfsize = wndconfig->height;
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
// Get the layer for this crtc/plane
layerAttribs[0] = EGL_DRM_CRTC_EXT;
layerAttribs[1] = (EGLAttrib)monitor->egldevice.crtcId;
if (!eglGetOutputLayersEXT(_glfw.egl.display, layerAttribs,
&window->egldevice.eglLayer,
1, &n) || !n)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Unable to obtain EGLOutputLayer");
return GLFW_FALSE;
}
// Create a stream and connect to the output
window->egldevice.eglStream =
eglCreateStreamKHR(_glfw.egl.display, streamAttribs);
if (window->egldevice.eglStream == EGL_NO_STREAM_KHR)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Unable to create stream (error 0x%x)",
eglGetError());
return GLFW_FALSE;
}
if (!eglStreamConsumerOutputEXT(_glfw.egl.display,
window->egldevice.eglStream,
window->egldevice.eglLayer))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Unable to connect stream (error 0x%x)",
eglGetError());
return GLFW_FALSE;
}
// Create a surface to feed the stream
surfaceAttribs[1] = window->egldevice.xsurfsize;
surfaceAttribs[3] = window->egldevice.ysurfsize;
window->context.egl.surface =
eglCreateStreamProducerSurfaceKHR(_glfw.egl.display,
window->context.egl.config,
window->egldevice.eglStream,
surfaceAttribs);
if (window->context.egl.surface == EGL_NO_SURFACE)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Unable to create rendering surface (error 0x%x)", eglGetError());
return GLFW_FALSE;
}
return GLFW_TRUE;
}
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
{
if (window->context.client != GLFW_NO_API)
window->context.destroy(window);
if (window->egldevice.eglStream != EGL_NO_STREAM_KHR)
eglDestroyStreamKHR(_glfw.egl.display, window->egldevice.eglStream);
}
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowTitle is not supported");
}
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
int count, const GLFWimage* images)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowIcon is not supported");
}
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
{
if (xpos)
*xpos = window->egldevice.xoffset;
if (ypos)
*ypos = window->egldevice.yoffset;
}
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
{
window->egldevice.xoffset = xpos;
window->egldevice.yoffset = ypos;
drmModeRes* res_info;
_GLFWmonitor* monitor;
if (window->monitor)
monitor = window->monitor;
else
monitor = _glfw.monitors[0];
res_info = drmModeGetResources(_glfw.egldevice.drmFd);
if (drmModeSetCrtc(_glfw.egldevice.drmFd,
res_info->crtcs[monitor->egldevice.crtcIndex],
-1, window->egldevice.xoffset, window->egldevice.yoffset,
&res_info->connectors[monitor->egldevice.crtcIndex], 1, NULL))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Setting window pos failed");
}
drmModeFreeResources(res_info);
}
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
{
if (width)
*width = window->egldevice.xsurfsize;
if (height)
*height = window->egldevice.ysurfsize;
}
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowSize not implemented");
}
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
int minwidth, int minheight,
int maxwidth, int maxheight)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowSizeLimits not implemented");
}
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowAspectRatio not implemented");
}
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
{
_glfwPlatformGetWindowSize(window, width, height);
}
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
int* left, int* top,
int* right, int* bottom)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetWindowFrameSize not implemented");
}
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformIconifyWindow not implemented");
}
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformRestoreWindow not implemented");
}
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformMaximizeWindow not implemented");
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowResizable not implemented");
}
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowDecorated not implemented");
}
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowFloating not implemented");
}
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformRequestWindowAttention not implemented");
}
void _glfwPlatformShowWindow(_GLFWwindow* window)
{
return;
}
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformUnhideWindow not implemented");
}
void _glfwPlatformHideWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformHideWindow not implemented");
}
void _glfwPlatformFocusWindow(_GLFWwindow* window)
{
return;
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowMonitor not implemented");
}
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformWindowFocused not implemented");
return GLFW_FALSE;
}
int _glfwPlatformWindowIconified(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformWindowIconified not implemented");
return GLFW_FALSE;
}
int _glfwPlatformWindowVisible(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformWindowVisible not implemented");
return GLFW_FALSE;
}
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformWindowMaximized not implemented");
return 0;
}
void _glfwPlatformPollEvents(void)
{
_glfwDetectJoystickConnectionLinux();
}
void _glfwPlatformWaitEvents(void)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformWaitEvents not supported");
}
void _glfwPlatformWaitEventsTimeout(double timeout)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformWaitEventsTimeout not supported");
}
void _glfwPlatformPostEmptyEvent(void)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformPostEmptyEvent not supported");
}
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetCursorPos not supported");
}
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetCursorPos not supported");
}
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetCursorMode not supported");
}
const char* _glfwPlatformGetKeyName(int key, int scancode)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetKeyName not supported");
return NULL;
}
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image,
int xhot, int yhot)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformCreateCursor not supported");
return GLFW_FALSE;
}
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformCreateStandardCursor not supported");
return GLFW_FALSE;
}
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
{
return;
}
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetCursor not supported");
}
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetClipboardString not supported");
}
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetClipboardString not supported");
return NULL;
}
const char* _glfwPlatformGetScancodeName(int scancode)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetScancodeName not supported");
return "";
}
int _glfwPlatformGetKeyScancode(int key)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetKeyScancode not supported");
return -1;
}
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetRequiredInstanceExtensions not supported");
}
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device,
uint32_t queuefamily)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetPhysicalDevicePresentationSupport not supported");
return GLFW_FALSE;
}
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
_GLFWwindow* window,
const VkAllocationCallbacks* allocator,
VkSurfaceKHR* surface)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformCreateWindowSurface not supported");
return VK_ERROR_INITIALIZATION_FAILED;
}
+2
View File
@@ -46,6 +46,8 @@
#cmakedefine _GLFW_MIR #cmakedefine _GLFW_MIR
// Define this to 1 if building GLFW for OSMesa // Define this to 1 if building GLFW for OSMesa
#cmakedefine _GLFW_OSMESA #cmakedefine _GLFW_OSMESA
// Define this to 1 if building GLFW for EGLDevice
#cmakedefine _GLFW_EGLDEVICE
// Define this to 1 if building as a shared library / dynamic library / DLL // Define this to 1 if building as a shared library / dynamic library / DLL
#cmakedefine _GLFW_BUILD_DLL #cmakedefine _GLFW_BUILD_DLL
+2 -1
View File
@@ -190,6 +190,8 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
#include "mir_platform.h" #include "mir_platform.h"
#elif defined(_GLFW_OSMESA) #elif defined(_GLFW_OSMESA)
#include "null_platform.h" #include "null_platform.h"
#elif defined(_GLFW_EGLDEVICE)
#include "egldevice_platform.h"
#else #else
#error "No supported window creation API selected" #error "No supported window creation API selected"
#endif #endif
@@ -685,7 +687,6 @@ void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
double _glfwPlatformGetEventTime(void);
void _glfwPlatformPollEvents(void); void _glfwPlatformPollEvents(void);
void _glfwPlatformWaitEvents(void); void _glfwPlatformWaitEvents(void);
void _glfwPlatformWaitEventsTimeout(double timeout); void _glfwPlatformWaitEventsTimeout(double timeout);
-3
View File
@@ -114,9 +114,6 @@ typedef struct _GLFWlibraryMir
// The window whose disabled cursor mode is active // The window whose disabled cursor mode is active
_GLFWwindow* disabledCursorWindow; _GLFWwindow* disabledCursorWindow;
// The time of the last event
int64_t lastEventTime;
} _GLFWlibraryMir; } _GLFWlibraryMir;
// Mir-specific per-cursor data // Mir-specific per-cursor data
+2 -13
View File
@@ -147,8 +147,6 @@ static void handleKeyEvent(const MirKeyboardEvent* key_event, _GLFWwindow* windo
const long text = _glfwKeySym2Unicode(key_code); const long text = _glfwKeySym2Unicode(key_code);
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
_glfw.mir.lastEventTime = mir_input_event_get_event_time((MirInputEvent *) key_event);
_glfwInputKey(window, toGLFWKeyCode(scan_code), scan_code, pressed, mods); _glfwInputKey(window, toGLFWKeyCode(scan_code), scan_code, pressed, mods);
if (text != -1) if (text != -1)
@@ -166,8 +164,6 @@ static void handlePointerButton(_GLFWwindow* window,
uint32_t newButtonStates = mir_pointer_event_buttons(pointer_event); uint32_t newButtonStates = mir_pointer_event_buttons(pointer_event);
int publicButton = GLFW_MOUSE_BUTTON_LEFT; int publicButton = GLFW_MOUSE_BUTTON_LEFT;
_glfw.mir.lastEventTime = mir_input_event_get_event_time((MirEvent *) pointer_event);
// XOR our old button states our new states to figure out what was added or removed // XOR our old button states our new states to figure out what was added or removed
button = newButtonStates ^ oldButtonStates; button = newButtonStates ^ oldButtonStates;
@@ -205,8 +201,6 @@ static void handlePointerMotion(_GLFWwindow* window,
const int hscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll); const int hscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll);
const int vscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll); const int vscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll);
_glfw.mir.lastEventTime = mir_input_event_get_event_time((MirEvent *) pointer_event);
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
{ {
if (_glfw.mir.disabledCursorWindow != window) if (_glfw.mir.disabledCursorWindow != window)
@@ -638,12 +632,6 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
"Mir: Unsupported function %s", __PRETTY_FUNCTION__); "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
} }
double _glfwPlatformGetEventTime(void)
{
/* Mir events are stored in nanoseconds */
return (double) _glfw.mir.lastEventTime / 1000000000.0;
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
EventNode* node = NULL; EventNode* node = NULL;
@@ -881,7 +869,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device, VkPhysicalDevice device,
uint32_t queuefamily) uint32_t queuefamily)
{ {
PFN_vkGetPhysicalDeviceMirPresentationSupportKHR vkGetPhysicalDeviceMirPresentationSupportKHR = PFN_vkGetPhysicalDeviceMirPresentationSupportKHR
vkGetPhysicalDeviceMirPresentationSupportKHR =
(PFN_vkGetPhysicalDeviceMirPresentationSupportKHR) (PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR"); vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
if (!vkGetPhysicalDeviceMirPresentationSupportKHR) if (!vkGetPhysicalDeviceMirPresentationSupportKHR)
-5
View File
@@ -204,11 +204,6 @@ int _glfwPlatformWindowVisible(_GLFWwindow* window)
return GLFW_FALSE; return GLFW_FALSE;
} }
double _glfwPlatformGetEventTime(void)
{
return 0.0;
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
} }
+6 -3
View File
@@ -30,7 +30,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <malloc.h> #include <malloc.h>
static const GUID _glfw_GUID_DEVINTERFACE_HID = {0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}}; static const GUID _glfw_GUID_DEVINTERFACE_HID =
{0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}};
#define GUID_DEVINTERFACE_HID _glfw_GUID_DEVINTERFACE_HID #define GUID_DEVINTERFACE_HID _glfw_GUID_DEVINTERFACE_HID
@@ -68,7 +69,8 @@ static GLFWbool loadLibraries(void)
_glfw.win32.winmm.instance = LoadLibraryA("winmm.dll"); _glfw.win32.winmm.instance = LoadLibraryA("winmm.dll");
if (!_glfw.win32.winmm.instance) if (!_glfw.win32.winmm.instance)
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to load winmm.dll"); _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to load winmm.dll");
return GLFW_FALSE; return GLFW_FALSE;
} }
@@ -78,7 +80,8 @@ static GLFWbool loadLibraries(void)
_glfw.win32.user32.instance = LoadLibraryA("user32.dll"); _glfw.win32.user32.instance = LoadLibraryA("user32.dll");
if (!_glfw.win32.user32.instance) if (!_glfw.win32.user32.instance)
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to load user32.dll"); _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to load user32.dll");
return GLFW_FALSE; return GLFW_FALSE;
} }
+26 -14
View File
@@ -50,16 +50,26 @@ typedef struct _GLFWobjenumWin32
// Define local copies of the necessary GUIDs // Define local copies of the necessary GUIDs
// //
static const GUID _glfw_IID_IDirectInput8W = {0xbf798031,0x483a,0x4da2,{0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00}}; static const GUID _glfw_IID_IDirectInput8W =
static const GUID _glfw_GUID_XAxis = {0xa36d02e0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}}; {0xbf798031,0x483a,0x4da2,{0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00}};
static const GUID _glfw_GUID_YAxis = {0xa36d02e1,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}}; static const GUID _glfw_GUID_XAxis =
static const GUID _glfw_GUID_ZAxis = {0xa36d02e2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}}; {0xa36d02e0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_RxAxis = {0xa36d02f4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}}; static const GUID _glfw_GUID_YAxis =
static const GUID _glfw_GUID_RyAxis = {0xa36d02f5,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}}; {0xa36d02e1,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_RzAxis = {0xa36d02e3,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}}; static const GUID _glfw_GUID_ZAxis =
static const GUID _glfw_GUID_Slider = {0xa36d02e4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}}; {0xa36d02e2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_Button = {0xa36d02f0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}}; static const GUID _glfw_GUID_RxAxis =
static const GUID _glfw_GUID_POV = {0xa36d02f2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}}; {0xa36d02f4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_RyAxis =
{0xa36d02f5,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_RzAxis =
{0xa36d02e3,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_Slider =
{0xa36d02e4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_Button =
{0xa36d02f0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
static const GUID _glfw_GUID_POV =
{0xa36d02f2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
#define IID_IDirectInput8W _glfw_IID_IDirectInput8W #define IID_IDirectInput8W _glfw_IID_IDirectInput8W
#define GUID_XAxis _glfw_GUID_XAxis #define GUID_XAxis _glfw_GUID_XAxis
@@ -345,10 +355,12 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{ {
if (!_glfw.joysticks[jid].present) _GLFWjoystick* js = _glfw.joysticks + jid;
continue; if (js->present)
if (memcmp(&_glfw.joysticks[jid].win32.guid, &di->guidInstance, sizeof(GUID)) == 0) {
return DIENUM_CONTINUE; if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
return DIENUM_CONTINUE;
}
} }
if (supportsXInput(&di->guidProduct)) if (supportsXInput(&di->guidProduct))
-4
View File
@@ -259,10 +259,6 @@ typedef struct _GLFWlibraryWin32
RAWINPUT* rawInput; RAWINPUT* rawInput;
int rawInputSize; int rawInputSize;
// State for accumulating a non-wrapping event time
uint32_t lastTimestamp;
uint64_t eventTime;
struct { struct {
HINSTANCE instance; HINSTANCE instance;
PFN_timeGetTime GetTime; PFN_timeGetTime GetTime;
+2 -21
View File
@@ -347,14 +347,6 @@ static int getKeyMods(void)
return mods; return mods;
} }
// Updates the event time with the specified timestamp
//
static void updateEventTime(LONG timestamp)
{
_glfw.win32.eventTime += (uint32_t) timestamp - _glfw.win32.lastTimestamp;
_glfw.win32.lastTimestamp = timestamp;
}
// Retrieves and translates modifier keys // Retrieves and translates modifier keys
// //
static int getAsyncKeyMods(void) static int getAsyncKeyMods(void)
@@ -603,7 +595,6 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_UNICHAR: case WM_UNICHAR:
{ {
const GLFWbool plain = (uMsg != WM_SYSCHAR); const GLFWbool plain = (uMsg != WM_SYSCHAR);
updateEventTime(GetMessageTime());
if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR) if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR)
{ {
@@ -626,7 +617,6 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
const int scancode = (lParam >> 16) & 0x1ff; const int scancode = (lParam >> 16) & 0x1ff;
const int action = ((lParam >> 31) & 1) ? GLFW_RELEASE : GLFW_PRESS; const int action = ((lParam >> 31) & 1) ? GLFW_RELEASE : GLFW_PRESS;
const int mods = getKeyMods(); const int mods = getKeyMods();
updateEventTime(GetMessageTime());
if (key == _GLFW_KEY_INVALID) if (key == _GLFW_KEY_INVALID)
break; break;
@@ -661,7 +651,6 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_XBUTTONUP: case WM_XBUTTONUP:
{ {
int i, button, action; int i, button, action;
updateEventTime(GetMessageTime());
if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP) if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
button = GLFW_MOUSE_BUTTON_LEFT; button = GLFW_MOUSE_BUTTON_LEFT;
@@ -712,7 +701,6 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
{ {
const int x = GET_X_LPARAM(lParam); const int x = GET_X_LPARAM(lParam);
const int y = GET_Y_LPARAM(lParam); const int y = GET_Y_LPARAM(lParam);
updateEventTime(GetMessageTime());
// Disabled cursor motion input is provided by WM_INPUT // Disabled cursor motion input is provided by WM_INPUT
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
@@ -791,7 +779,6 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_MOUSELEAVE: case WM_MOUSELEAVE:
{ {
updateEventTime(GetMessageTime());
window->win32.cursorTracked = GLFW_FALSE; window->win32.cursorTracked = GLFW_FALSE;
_glfwInputCursorEnter(window, GLFW_FALSE); _glfwInputCursorEnter(window, GLFW_FALSE);
return 0; return 0;
@@ -799,7 +786,6 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
{ {
updateEventTime(GetMessageTime());
_glfwInputScroll(window, 0.0, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA); _glfwInputScroll(window, 0.0, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA);
return 0; return 0;
} }
@@ -807,7 +793,6 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_MOUSEHWHEEL: case WM_MOUSEHWHEEL:
{ {
// This message is only sent on Windows Vista and later // This message is only sent on Windows Vista and later
updateEventTime(GetMessageTime());
// NOTE: The X-axis is inverted for consistency with macOS and X11 // NOTE: The X-axis is inverted for consistency with macOS and X11
_glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0); _glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);
return 0; return 0;
@@ -1513,11 +1498,6 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
} }
double _glfwPlatformGetEventTime(void)
{
return (double) _glfw.win32.eventTime / 1000.0;
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
MSG msg; MSG msg;
@@ -1818,7 +1798,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device, VkPhysicalDevice device,
uint32_t queuefamily) uint32_t queuefamily)
{ {
PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR = PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
vkGetPhysicalDeviceWin32PresentationSupportKHR =
(PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR) (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR"); vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
if (!vkGetPhysicalDeviceWin32PresentationSupportKHR) if (!vkGetPhysicalDeviceWin32PresentationSupportKHR)
-6
View File
@@ -956,12 +956,6 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle
return cbfun; return cbfun;
} }
GLFWAPI double glfwGetEventTime(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(0.0);
return _glfwPlatformGetEventTime();
}
GLFWAPI void glfwPollEvents(void) GLFWAPI void glfwPollEvents(void)
{ {
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
-4
View File
@@ -83,7 +83,6 @@ static void pointerHandleMotion(void* data,
if (!window) if (!window)
return; return;
_glfw.wl.lastEventTime = time;
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
return; return;
else else
@@ -110,7 +109,6 @@ static void pointerHandleButton(void* data,
if (!window) if (!window)
return; return;
_glfw.wl.lastEventTime = time;
_glfw.wl.pointerSerial = serial; _glfw.wl.pointerSerial = serial;
/* Makes left, right and middle 0, 1 and 2. Overall order follows evdev /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
@@ -138,7 +136,6 @@ static void pointerHandleAxis(void* data,
if (!window) if (!window)
return; return;
_glfw.wl.lastEventTime = time;
/* Wayland scroll events are in pointer motion coordinate space (think /* Wayland scroll events are in pointer motion coordinate space (think
* two finger scroll). The factor 10 is commonly used to convert to * two finger scroll). The factor 10 is commonly used to convert to
* "scroll step means 1.0. */ * "scroll step means 1.0. */
@@ -352,7 +349,6 @@ static void keyboardHandleKey(void* data,
if (!window) if (!window)
return; return;
_glfw.wl.lastEventTime = time;
keyCode = toGLFWKeyCode(key); keyCode = toGLFWKeyCode(key);
action = state == WL_KEYBOARD_KEY_STATE_PRESSED action = state == WL_KEYBOARD_KEY_STATE_PRESSED
? GLFW_PRESS : GLFW_RELEASE; ? GLFW_PRESS : GLFW_RELEASE;
-4
View File
@@ -97,7 +97,6 @@ typedef struct _GLFWwindowWayland
struct zwp_relative_pointer_v1* relativePointer; struct zwp_relative_pointer_v1* relativePointer;
struct zwp_locked_pointer_v1* lockedPointer; struct zwp_locked_pointer_v1* lockedPointer;
} pointerLock; } pointerLock;
} _GLFWwindowWayland; } _GLFWwindowWayland;
// Wayland-specific global data // Wayland-specific global data
@@ -139,9 +138,6 @@ typedef struct _GLFWlibraryWayland
_GLFWwindow* pointerFocus; _GLFWwindow* pointerFocus;
_GLFWwindow* keyboardFocus; _GLFWwindow* keyboardFocus;
// The time of the last event
unsigned int lastEventTime;
} _GLFWlibraryWayland; } _GLFWlibraryWayland;
// Wayland-specific per-monitor data // Wayland-specific per-monitor data
+2 -6
View File
@@ -675,11 +675,6 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
"Wayland: Window attribute setting not implemented yet"); "Wayland: Window attribute setting not implemented yet");
} }
double _glfwPlatformGetEventTime(void)
{
return (double) _glfw.wl.lastEventTime / 1000.0;
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
handleEvents(0); handleEvents(0);
@@ -1024,7 +1019,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device, VkPhysicalDevice device,
uint32_t queuefamily) uint32_t queuefamily)
{ {
PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR = PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
vkGetPhysicalDeviceWaylandPresentationSupportKHR =
(PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR) (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR"); vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
if (!vkGetPhysicalDeviceWaylandPresentationSupportKHR) if (!vkGetPhysicalDeviceWaylandPresentationSupportKHR)
+7 -8
View File
@@ -237,8 +237,8 @@ static void createKeyTables(void)
if (_glfw.x11.xkb.available) if (_glfw.x11.xkb.available)
{ {
// Use XKB to determine physical key locations independently of the current // Use XKB to determine physical key locations independently of the
// keyboard layout // current keyboard layout
char name[XkbKeyNameLength + 1]; char name[XkbKeyNameLength + 1];
XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd); XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd);
@@ -661,10 +661,7 @@ static GLFWbool initExtensions(void)
// String format atoms // String format atoms
_glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False); _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);
_glfw.x11.UTF8_STRING = _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
_glfw.x11.COMPOUND_STRING =
XInternAtom(_glfw.x11.display, "COMPOUND_STRING", False);
_glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False); _glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False);
// Custom selection property atom // Custom selection property atom
@@ -675,6 +672,7 @@ static GLFWbool initExtensions(void)
_glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False); _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False);
_glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False); _glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False);
_glfw.x11.PRIMARY = XInternAtom(_glfw.x11.display, "PRIMARY", False); _glfw.x11.PRIMARY = XInternAtom(_glfw.x11.display, "PRIMARY", False);
_glfw.x11.INCR = XInternAtom(_glfw.x11.display, "INCR", False);
_glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False); _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False);
// Clipboard manager atoms // Clipboard manager atoms
@@ -862,12 +860,13 @@ int _glfwPlatformInit(void)
_glfw.x11.screen = DefaultScreen(_glfw.x11.display); _glfw.x11.screen = DefaultScreen(_glfw.x11.display);
_glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen); _glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen);
_glfw.x11.context = XUniqueContext(); _glfw.x11.context = XUniqueContext();
_glfw.x11.helperWindowHandle = createHelperWindow();
_glfw.x11.hiddenCursorHandle = createHiddenCursor();
if (!initExtensions()) if (!initExtensions())
return GLFW_FALSE; return GLFW_FALSE;
_glfw.x11.helperWindowHandle = createHelperWindow();
_glfw.x11.hiddenCursorHandle = createHiddenCursor();
if (XSupportsLocale()) if (XSupportsLocale())
{ {
XSetLocaleModifiers(""); XSetLocaleModifiers("");
+1 -3
View File
@@ -225,9 +225,6 @@ typedef struct _GLFWlibraryX11
double restoreCursorPosX, restoreCursorPosY; double restoreCursorPosX, restoreCursorPosY;
// The window whose disabled cursor mode is active // The window whose disabled cursor mode is active
_GLFWwindow* disabledCursorWindow; _GLFWwindow* disabledCursorWindow;
// State for accumulating a non-wrapping event time
Time lastTimestamp;
uint64_t eventTime;
// Window manager atoms // Window manager atoms
Atom WM_PROTOCOLS; Atom WM_PROTOCOLS;
@@ -268,6 +265,7 @@ typedef struct _GLFWlibraryX11
// Selection (clipboard) atoms // Selection (clipboard) atoms
Atom TARGETS; Atom TARGETS;
Atom MULTIPLE; Atom MULTIPLE;
Atom INCR;
Atom CLIPBOARD; Atom CLIPBOARD;
Atom PRIMARY; Atom PRIMARY;
Atom CLIPBOARD_MANAGER; Atom CLIPBOARD_MANAGER;
+192 -115
View File
@@ -164,6 +164,17 @@ static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointe
event->xproperty.atom == _glfw.x11.NET_FRAME_EXTENTS; event->xproperty.atom == _glfw.x11.NET_FRAME_EXTENTS;
} }
// Returns whether it is a property event for the specified selection transfer
//
static Bool isSelPropNewValueNotify(Display* display, XEvent* event, XPointer pointer)
{
XEvent* notification = (XEvent*) pointer;
return event->type == PropertyNotify &&
event->xproperty.state == PropertyNewValue &&
event->xproperty.window == notification->xselection.requestor &&
event->xproperty.atom == notification->xselection.property;
}
// Translates a GLFW standard cursor to a font cursor shape // Translates a GLFW standard cursor to a font cursor shape
// //
static int translateCursorShape(int shape) static int translateCursorShape(int shape)
@@ -449,6 +460,81 @@ static char** parseUriList(char* text, int* count)
return paths; return paths;
} }
// Encode a Unicode code point to a UTF-8 stream
// Based on cutef8 by Jeff Bezanson (Public Domain)
//
static size_t encodeUTF8(char* s, unsigned int ch)
{
size_t count = 0;
if (ch < 0x80)
s[count++] = (char) ch;
else if (ch < 0x800)
{
s[count++] = (ch >> 6) | 0xc0;
s[count++] = (ch & 0x3f) | 0x80;
}
else if (ch < 0x10000)
{
s[count++] = (ch >> 12) | 0xe0;
s[count++] = ((ch >> 6) & 0x3f) | 0x80;
s[count++] = (ch & 0x3f) | 0x80;
}
else if (ch < 0x110000)
{
s[count++] = (ch >> 18) | 0xf0;
s[count++] = ((ch >> 12) & 0x3f) | 0x80;
s[count++] = ((ch >> 6) & 0x3f) | 0x80;
s[count++] = (ch & 0x3f) | 0x80;
}
return count;
}
// Decode a Unicode code point from a UTF-8 stream
// Based on cutef8 by Jeff Bezanson (Public Domain)
//
#if defined(X_HAVE_UTF8_STRING)
static unsigned int decodeUTF8(const char** s)
{
unsigned int ch = 0, count = 0;
static const unsigned int offsets[] =
{
0x00000000u, 0x00003080u, 0x000e2080u,
0x03c82080u, 0xfa082080u, 0x82082080u
};
do
{
ch = (ch << 6) + (unsigned char) **s;
(*s)++;
count++;
} while ((**s & 0xc0) == 0x80);
assert(count <= 6);
return ch - offsets[count - 1];
}
#endif /*X_HAVE_UTF8_STRING*/
// Convert the specified Latin-1 string to UTF-8
//
static char* convertLatin1toUTF8(const char* source)
{
size_t size = 1;
const char* sp;
for (sp = source; *sp; sp++)
size += (*sp & 0x80) ? 2 : 1;
char* target = calloc(size, 1);
char* tp = target;
for (sp = source; *sp; sp++)
tp += encodeUTF8(tp, *sp);
return target;
}
// Centers the cursor over the window client area // Centers the cursor over the window client area
// //
static void centerCursor(_GLFWwindow* window) static void centerCursor(_GLFWwindow* window)
@@ -672,9 +758,7 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
{ {
int i; int i;
char* selectionString = NULL; char* selectionString = NULL;
const Atom formats[] = { _glfw.x11.UTF8_STRING, const Atom formats[] = { _glfw.x11.UTF8_STRING, XA_STRING };
_glfw.x11.COMPOUND_STRING,
XA_STRING };
const int formatCount = sizeof(formats) / sizeof(formats[0]); const int formatCount = sizeof(formats) / sizeof(formats[0]);
if (request->selection == _glfw.x11.PRIMARY) if (request->selection == _glfw.x11.PRIMARY)
@@ -696,7 +780,6 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
const Atom targets[] = { _glfw.x11.TARGETS, const Atom targets[] = { _glfw.x11.TARGETS,
_glfw.x11.MULTIPLE, _glfw.x11.MULTIPLE,
_glfw.x11.UTF8_STRING, _glfw.x11.UTF8_STRING,
_glfw.x11.COMPOUND_STRING,
XA_STRING }; XA_STRING };
XChangeProperty(_glfw.x11.display, XChangeProperty(_glfw.x11.display,
@@ -841,10 +924,8 @@ static const char* getSelectionString(Atom selection)
{ {
size_t i; size_t i;
char** selectionString = NULL; char** selectionString = NULL;
const Atom formats[] = { _glfw.x11.UTF8_STRING, const Atom targets[] = { _glfw.x11.UTF8_STRING, XA_STRING };
_glfw.x11.COMPOUND_STRING, const size_t targetCount = sizeof(targets) / sizeof(targets[0]);
XA_STRING };
const size_t formatCount = sizeof(formats) / sizeof(formats[0]);
if (selection == _glfw.x11.PRIMARY) if (selection == _glfw.x11.PRIMARY)
selectionString = &_glfw.x11.primarySelectionString; selectionString = &_glfw.x11.primarySelectionString;
@@ -862,14 +943,17 @@ static const char* getSelectionString(Atom selection)
free(*selectionString); free(*selectionString);
*selectionString = NULL; *selectionString = NULL;
for (i = 0; i < formatCount; i++) for (i = 0; i < targetCount; i++)
{ {
char* data; char* data;
XEvent event; Atom actualType;
int actualFormat;
unsigned long itemCount, bytesAfter;
XEvent notification, dummy;
XConvertSelection(_glfw.x11.display, XConvertSelection(_glfw.x11.display,
selection, selection,
formats[i], targets[i],
_glfw.x11.GLFW_SELECTION, _glfw.x11.GLFW_SELECTION,
_glfw.x11.helperWindowHandle, _glfw.x11.helperWindowHandle,
CurrentTime); CurrentTime);
@@ -877,28 +961,92 @@ static const char* getSelectionString(Atom selection)
while (!XCheckTypedWindowEvent(_glfw.x11.display, while (!XCheckTypedWindowEvent(_glfw.x11.display,
_glfw.x11.helperWindowHandle, _glfw.x11.helperWindowHandle,
SelectionNotify, SelectionNotify,
&event)) &notification))
{ {
waitForEvent(NULL); waitForEvent(NULL);
} }
if (event.xselection.property == None) if (notification.xselection.property == None)
continue; continue;
if (_glfwGetWindowPropertyX11(event.xselection.requestor, XCheckIfEvent(_glfw.x11.display,
event.xselection.property, &dummy,
event.xselection.target, isSelPropNewValueNotify,
(unsigned char**) &data)) (XPointer) &notification);
XGetWindowProperty(_glfw.x11.display,
notification.xselection.requestor,
notification.xselection.property,
0,
LONG_MAX,
True,
AnyPropertyType,
&actualType,
&actualFormat,
&itemCount,
&bytesAfter,
(unsigned char**) &data);
if (actualType == _glfw.x11.INCR)
{ {
*selectionString = strdup(data); size_t size = 1;
char* string = NULL;
for (;;)
{
while (!XCheckIfEvent(_glfw.x11.display,
&dummy,
isSelPropNewValueNotify,
(XPointer) &notification))
{
waitForEvent(NULL);
}
XFree(data);
XGetWindowProperty(_glfw.x11.display,
notification.xselection.requestor,
notification.xselection.property,
0,
LONG_MAX,
True,
AnyPropertyType,
&actualType,
&actualFormat,
&itemCount,
&bytesAfter,
(unsigned char**) &data);
if (itemCount)
{
size += itemCount;
string = realloc(string, size);
string[size - itemCount - 1] = '\0';
strcat(string, data);
}
if (!itemCount)
{
if (targets[i] == XA_STRING)
{
*selectionString = convertLatin1toUTF8(string);
free(string);
}
else
*selectionString = string;
break;
}
}
}
else if (actualType == targets[i])
{
if (targets[i] == XA_STRING)
*selectionString = convertLatin1toUTF8(data);
else
*selectionString = strdup(data);
} }
if (data) XFree(data);
XFree(data);
XDeleteProperty(_glfw.x11.display,
event.xselection.requestor,
event.xselection.property);
if (*selectionString) if (*selectionString)
break; break;
@@ -907,7 +1055,7 @@ static const char* getSelectionString(Atom selection)
if (!*selectionString) if (!*selectionString)
{ {
_glfwInputError(GLFW_FORMAT_UNAVAILABLE, _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"X11: Failed to convert clipboard to string"); "X11: Failed to convert selection to string");
} }
return *selectionString; return *selectionString;
@@ -978,70 +1126,6 @@ static void releaseMonitor(_GLFWwindow* window)
} }
} }
// Encode a Unicode code point to a UTF-8 stream
// Based on cutef8 by Jeff Bezanson (Public Domain)
//
static size_t encodeUTF8(char* s, unsigned int ch)
{
size_t count = 0;
if (ch < 0x80)
s[count++] = (char) ch;
else if (ch < 0x800)
{
s[count++] = (ch >> 6) | 0xc0;
s[count++] = (ch & 0x3f) | 0x80;
}
else if (ch < 0x10000)
{
s[count++] = (ch >> 12) | 0xe0;
s[count++] = ((ch >> 6) & 0x3f) | 0x80;
s[count++] = (ch & 0x3f) | 0x80;
}
else if (ch < 0x110000)
{
s[count++] = (ch >> 18) | 0xf0;
s[count++] = ((ch >> 12) & 0x3f) | 0x80;
s[count++] = ((ch >> 6) & 0x3f) | 0x80;
s[count++] = (ch & 0x3f) | 0x80;
}
return count;
}
// Decode a Unicode code point from a UTF-8 stream
// Based on cutef8 by Jeff Bezanson (Public Domain)
//
#if defined(X_HAVE_UTF8_STRING)
static unsigned int decodeUTF8(const char** s)
{
unsigned int ch = 0, count = 0;
static const unsigned int offsets[] =
{
0x00000000u, 0x00003080u, 0x000e2080u,
0x03c82080u, 0xfa082080u, 0x82082080u
};
do
{
ch = (ch << 6) + (unsigned char) **s;
(*s)++;
count++;
} while ((**s & 0xc0) == 0x80);
assert(count <= 6);
return ch - offsets[count - 1];
}
#endif /*X_HAVE_UTF8_STRING*/
// Updates the event time with the specified timestamp
//
static void updateEventTime(Time timestamp)
{
_glfw.x11.eventTime += timestamp - _glfw.x11.lastTimestamp;
_glfw.x11.lastTimestamp = timestamp;
}
// Process the specified X event // Process the specified X event
// //
static void processEvent(XEvent *event) static void processEvent(XEvent *event)
@@ -1084,7 +1168,6 @@ static void processEvent(XEvent *event)
const double* values = re->raw_values; const double* values = re->raw_values;
double xpos = window->virtualCursorPosX; double xpos = window->virtualCursorPosX;
double ypos = window->virtualCursorPosY; double ypos = window->virtualCursorPosY;
updateEventTime(re->time);
if (XIMaskIsSet(re->valuators.mask, 0)) if (XIMaskIsSet(re->valuators.mask, 0))
{ {
@@ -1130,7 +1213,6 @@ static void processEvent(XEvent *event)
const int key = translateKey(keycode); const int key = translateKey(keycode);
const int mods = translateState(event->xkey.state); const int mods = translateState(event->xkey.state);
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
updateEventTime(event->xkey.time);
if (window->x11.ic) if (window->x11.ic)
{ {
@@ -1181,8 +1263,10 @@ static void processEvent(XEvent *event)
count = XwcLookupString(window->x11.ic, count = XwcLookupString(window->x11.ic,
&event->xkey, &event->xkey,
buffer, sizeof(buffer) / sizeof(wchar_t), buffer,
NULL, &status); sizeof(buffer) / sizeof(wchar_t),
NULL,
&status);
if (status == XBufferOverflow) if (status == XBufferOverflow)
{ {
@@ -1224,7 +1308,6 @@ static void processEvent(XEvent *event)
{ {
const int key = translateKey(keycode); const int key = translateKey(keycode);
const int mods = translateState(event->xkey.state); const int mods = translateState(event->xkey.state);
updateEventTime(event->xkey.time);
if (!_glfw.x11.xkb.detectable) if (!_glfw.x11.xkb.detectable)
{ {
@@ -1265,7 +1348,6 @@ static void processEvent(XEvent *event)
case ButtonPress: case ButtonPress:
{ {
const int mods = translateState(event->xbutton.state); const int mods = translateState(event->xbutton.state);
updateEventTime(event->xbutton.time);
if (event->xbutton.button == Button1) if (event->xbutton.button == Button1)
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods); _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods);
@@ -1300,7 +1382,6 @@ static void processEvent(XEvent *event)
case ButtonRelease: case ButtonRelease:
{ {
const int mods = translateState(event->xbutton.state); const int mods = translateState(event->xbutton.state);
updateEventTime(event->xbutton.time);
if (event->xbutton.button == Button1) if (event->xbutton.button == Button1)
{ {
@@ -1338,8 +1419,6 @@ static void processEvent(XEvent *event)
case EnterNotify: case EnterNotify:
{ {
updateEventTime(event->xcrossing.time);
// HACK: This is a workaround for WMs (KWM, Fluxbox) that otherwise // HACK: This is a workaround for WMs (KWM, Fluxbox) that otherwise
// ignore the defined cursor for hidden cursor mode // ignore the defined cursor for hidden cursor mode
if (window->cursorMode == GLFW_CURSOR_HIDDEN) if (window->cursorMode == GLFW_CURSOR_HIDDEN)
@@ -1351,7 +1430,6 @@ static void processEvent(XEvent *event)
case LeaveNotify: case LeaveNotify:
{ {
updateEventTime(event->xcrossing.time);
_glfwInputCursorEnter(window, GLFW_FALSE); _glfwInputCursorEnter(window, GLFW_FALSE);
return; return;
} }
@@ -1360,9 +1438,9 @@ static void processEvent(XEvent *event)
{ {
const int x = event->xmotion.x; const int x = event->xmotion.x;
const int y = event->xmotion.y; const int y = event->xmotion.y;
updateEventTime(event->xmotion.time);
if (x != window->x11.warpCursorPosX || y != window->x11.warpCursorPosY) if (x != window->x11.warpCursorPosX ||
y != window->x11.warpCursorPosY)
{ {
// The cursor was moved by something other than GLFW // The cursor was moved by something other than GLFW
@@ -1441,14 +1519,15 @@ static void processEvent(XEvent *event)
if (protocol == _glfw.x11.WM_DELETE_WINDOW) if (protocol == _glfw.x11.WM_DELETE_WINDOW)
{ {
// The window manager was asked to close the window, for example by // The window manager was asked to close the window, for
// the user pressing a 'close' window decoration button // example by the user pressing a 'close' window decoration
// button
_glfwInputWindowCloseRequest(window); _glfwInputWindowCloseRequest(window);
} }
else if (protocol == _glfw.x11.NET_WM_PING) else if (protocol == _glfw.x11.NET_WM_PING)
{ {
// The window manager is pinging the application to ensure it's // The window manager is pinging the application to ensure
// still responding to events // it's still responding to events
XEvent reply = *event; XEvent reply = *event;
reply.xclient.window = _glfw.x11.root; reply.xclient.window = _glfw.x11.root;
@@ -1790,9 +1869,10 @@ void _glfwPushSelectionToManagerX11(void)
{ {
if (event.xselection.target == _glfw.x11.SAVE_TARGETS) if (event.xselection.target == _glfw.x11.SAVE_TARGETS)
{ {
// This means one of two things; either the selection was // This means one of two things; either the selection
// not owned, which means there is no clipboard manager, or // was not owned, which means there is no clipboard
// the transfer to the clipboard manager has completed // manager, or the transfer to the clipboard manager has
// completed
// In either case, it means we are done here // In either case, it means we are done here
return; return;
} }
@@ -2445,11 +2525,6 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
XFlush(_glfw.x11.display); XFlush(_glfw.x11.display);
} }
double _glfwPlatformGetEventTime(void)
{
return (double) _glfw.x11.eventTime / 1000.0;
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
_GLFWwindow* window; _GLFWwindow* window;
@@ -2717,7 +2792,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
if (_glfw.vk.KHR_xcb_surface && _glfw.x11.x11xcb.handle) if (_glfw.vk.KHR_xcb_surface && _glfw.x11.x11xcb.handle)
{ {
PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR = PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR
vkGetPhysicalDeviceXcbPresentationSupportKHR =
(PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR) (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR"); vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
if (!vkGetPhysicalDeviceXcbPresentationSupportKHR) if (!vkGetPhysicalDeviceXcbPresentationSupportKHR)
@@ -2742,7 +2818,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
} }
else else
{ {
PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR = PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR
vkGetPhysicalDeviceXlibPresentationSupportKHR =
(PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR) (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR"); vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
if (!vkGetPhysicalDeviceXlibPresentationSupportKHR) if (!vkGetPhysicalDeviceXlibPresentationSupportKHR)
+12 -16
View File
@@ -336,35 +336,33 @@ static void window_maximize_callback(GLFWwindow* window, int maximized)
static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{ {
Slot* slot = glfwGetWindowUserPointer(window); Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Mouse button %i (%s) (with%s) was %s at %0.3f\n", printf("%08x to %i at %0.3f: Mouse button %i (%s) (with%s) was %s\n",
counter++, slot->number, glfwGetTime(), button, counter++, slot->number, glfwGetTime(), button,
get_button_name(button), get_button_name(button),
get_mods_name(mods), get_mods_name(mods),
get_action_name(action), get_action_name(action));
glfwGetEventTime());
} }
static void cursor_position_callback(GLFWwindow* window, double x, double y) static void cursor_position_callback(GLFWwindow* window, double x, double y)
{ {
Slot* slot = glfwGetWindowUserPointer(window); Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Cursor position: %f %f at %0.3f\n", printf("%08x to %i at %0.3f: Cursor position: %f %f\n",
counter++, slot->number, glfwGetTime(), x, y, glfwGetEventTime()); counter++, slot->number, glfwGetTime(), x, y);
} }
static void cursor_enter_callback(GLFWwindow* window, int entered) static void cursor_enter_callback(GLFWwindow* window, int entered)
{ {
Slot* slot = glfwGetWindowUserPointer(window); Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Cursor %s window at %0.3f\n", printf("%08x to %i at %0.3f: Cursor %s window\n",
counter++, slot->number, glfwGetTime(), counter++, slot->number, glfwGetTime(),
entered ? "entered" : "left", entered ? "entered" : "left");
glfwGetEventTime());
} }
static void scroll_callback(GLFWwindow* window, double x, double y) static void scroll_callback(GLFWwindow* window, double x, double y)
{ {
Slot* slot = glfwGetWindowUserPointer(window); Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Scroll: %0.3f %0.3f at %0.3f\n", printf("%08x to %i at %0.3f: Scroll: %0.3f %0.3f\n",
counter++, slot->number, glfwGetTime(), x, y, glfwGetEventTime()); counter++, slot->number, glfwGetTime(), x, y);
} }
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
@@ -374,22 +372,20 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
if (name) if (name)
{ {
printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x (%s) (%s) (with%s) was %s at %0.3f\n", printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x (%s) (%s) (with%s) was %s\n",
counter++, slot->number, glfwGetTime(), key, scancode, counter++, slot->number, glfwGetTime(), key, scancode,
get_key_name(key), get_key_name(key),
name, name,
get_mods_name(mods), get_mods_name(mods),
get_action_name(action), get_action_name(action));
glfwGetEventTime());
} }
else else
{ {
printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x (%s) (with%s) was %s at %0.3f\n", printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x (%s) (with%s) was %s\n",
counter++, slot->number, glfwGetTime(), key, scancode, counter++, slot->number, glfwGetTime(), key, scancode,
get_key_name(key), get_key_name(key),
get_mods_name(mods), get_mods_name(mods),
get_action_name(action), get_action_name(action));
glfwGetEventTime());
} }
if (action != GLFW_PRESS) if (action != GLFW_PRESS)