mirror of
https://github.com/glfw/glfw.git
synced 2026-09-20 08:23:13 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4e1d7e9266 | |||
| 243db302bf | |||
| 5b1a187f71 | |||
| f4fb25b63d | |||
| e3be6b8ae0 | |||
| 3d110d2e1b | |||
| 0b5023bc62 | |||
| 9dbc935afb | |||
| f7dc6df02c | |||
| f30acd8f74 |
+23
-2
@@ -41,8 +41,9 @@ if (WIN32)
|
||||
endif()
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
|
||||
option(GLFW_USE_MIR "Use Mir 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_EGLDEVICE "Use EGLDevice for window creation" OFF)
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
@@ -163,6 +164,9 @@ elseif (GLFW_USE_MIR)
|
||||
elseif (GLFW_USE_OSMESA)
|
||||
set(_GLFW_OSMESA 1)
|
||||
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)
|
||||
set(_GLFW_WIN32 1)
|
||||
message(STATUS "Using Win32 for window creation")
|
||||
@@ -291,6 +295,23 @@ if (_GLFW_WAYLAND)
|
||||
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
|
||||
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
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
@@ -11,8 +11,9 @@ application development. It provides a simple, platform-independent API for
|
||||
creating windows, contexts and surfaces, reading input, handling events, etc.
|
||||
|
||||
GLFW natively supports Windows, macOS and Linux and other Unix-like systems.
|
||||
Experimental implementations for the Wayland protocol and the Mir display server
|
||||
are available but not yet officially supported.
|
||||
Experimental implementations for the Wayland protocol, the Mir display server
|
||||
and direct rendering via EGLDevice are available but not yet officially
|
||||
supported.
|
||||
|
||||
GLFW is licensed under the [zlib/libpng
|
||||
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
|
||||
|
||||
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
|
||||
rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them.
|
||||
does not need the headers for any context creation API (WGL, GLX, EGL, NSGL,
|
||||
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
|
||||
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`
|
||||
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
|
||||
located in the `deps/` directory.
|
||||
|
||||
@@ -205,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: Gamma ramp setting via RandR did not validate ramp size
|
||||
- [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] Bugfix: Event processing did not detect joystick disconnection (#932)
|
||||
- [Linux] Bugfix: The joystick device path could be truncated (#1025)
|
||||
@@ -279,6 +287,7 @@ skills.
|
||||
- David Carlier
|
||||
- Arturo Castro
|
||||
- Chi-kwan Chan
|
||||
- Kamal Chandra
|
||||
- Ian Clarkson
|
||||
- Michał Cichoń
|
||||
- Lambert Clara
|
||||
|
||||
@@ -257,6 +257,7 @@ ramps and clipboard. The options are:
|
||||
- @b _GLFW_WAYLAND to use the Wayland 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_EGLDEVICE to use the EGLDevice API (experimental and incomplete)
|
||||
|
||||
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.
|
||||
|
||||
+7
-1
@@ -47,6 +47,12 @@ elseif (_GLFW_WAYLAND)
|
||||
PROTOCOL
|
||||
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml"
|
||||
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)
|
||||
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.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
|
||||
_GLFW_USE_CONFIG_H
|
||||
$<$<BOOL:${UNIX}>:_XOPEN_SOURCE=600>)
|
||||
$<$<BOOL:${UNIX}>:_POSIX_C_SOURCE=200809L>)
|
||||
target_include_directories(glfw PUBLIC
|
||||
"$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>")
|
||||
|
||||
+5
-3
@@ -215,8 +215,9 @@ static GLFWbool updateUnicodeDataNS(void)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.ns.unicodeData = TISGetInputSourceProperty(_glfw.ns.inputSource,
|
||||
kTISPropertyUnicodeKeyLayoutData);
|
||||
_glfw.ns.unicodeData =
|
||||
TISGetInputSourceProperty(_glfw.ns.inputSource,
|
||||
kTISPropertyUnicodeKeyLayoutData);
|
||||
if (!_glfw.ns.unicodeData)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
@@ -232,7 +233,8 @@ static GLFWbool updateUnicodeDataNS(void)
|
||||
static GLFWbool initializeTIS(void)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
|
||||
@@ -73,7 +73,9 @@ static long getElementValue(_GLFWjoystick* js, _GLFWjoyelementNS* element)
|
||||
|
||||
// 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* se = sp;
|
||||
@@ -183,7 +185,8 @@ static void matchCallback(void* context,
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(elements); i++)
|
||||
{
|
||||
IOHIDElementRef native = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, i);
|
||||
IOHIDElementRef native = (IOHIDElementRef)
|
||||
CFArrayGetValueAtIndex(elements, i);
|
||||
if (CFGetTypeID(native) != IOHIDElementGetTypeID())
|
||||
continue;
|
||||
|
||||
|
||||
+14
-3
@@ -54,7 +54,8 @@ static char* getDisplayName(CGDirectDisplayID displayID)
|
||||
|
||||
while ((service = IOIteratorNext(it)) != 0)
|
||||
{
|
||||
info = IODisplayCreateInfoDictionary(service, kIODisplayOnlyPreferredName);
|
||||
info = IODisplayCreateInfoDictionary(service,
|
||||
kIODisplayOnlyPreferredName);
|
||||
|
||||
CFNumberRef vendorIDRef =
|
||||
CFDictionaryGetValue(info, CFSTR(kDisplayVendorID));
|
||||
@@ -185,7 +186,13 @@ static CGDisplayFadeReservationToken beginFadeReservation(void)
|
||||
CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken;
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -196,7 +203,11 @@ static void endFadeReservation(CGDisplayFadeReservationToken token)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,10 +116,18 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
||||
if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
|
||||
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
|
||||
if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
|
||||
continue;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(_GLFW_X11)
|
||||
// Only consider EGLConfigs with associated Visuals
|
||||
if (!getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
|
||||
@@ -376,6 +384,9 @@ GLFWbool _glfwInitEGL(void)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
// For EGLDevice backend the display gets initialized
|
||||
// in _glfwPlatformInit()
|
||||
#if !defined(_GLFW_EGLDEVICE)
|
||||
_glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
|
||||
if (_glfw.egl.display == EGL_NO_DISPLAY)
|
||||
{
|
||||
@@ -396,6 +407,7 @@ GLFWbool _glfwInitEGL(void)
|
||||
_glfwTerminateEGL();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
_glfw.egl.KHR_create_context =
|
||||
extensionSupportedEGL("EGL_KHR_create_context");
|
||||
@@ -581,6 +593,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
setAttrib(EGL_NONE, EGL_NONE);
|
||||
}
|
||||
|
||||
// The surface for EGLDevice backened is created in _glfwPlatformCreateWindow
|
||||
//
|
||||
#if !defined (_GLFW_EGLDEVICE)
|
||||
window->context.egl.surface =
|
||||
eglCreateWindowSurface(_glfw.egl.display,
|
||||
config,
|
||||
@@ -593,6 +608,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
getEGLErrorString(eglGetError()));
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
window->context.egl.config = config;
|
||||
|
||||
|
||||
@@ -47,6 +47,10 @@ typedef struct wl_egl_window* EGLNativeWindowType;
|
||||
#define EGLAPIENTRY
|
||||
typedef MirEGLNativeDisplayType EGLNativeDisplayType;
|
||||
typedef MirEGLNativeWindowType EGLNativeWindowType;
|
||||
#elif defined(_GLFW_EGLDEVICE)
|
||||
#define EGLAPIENTRY
|
||||
typedef void* EGLNativeDisplayType;
|
||||
typedef int EGLNativeWindowType;
|
||||
#else
|
||||
#error "No supported EGL platform selected"
|
||||
#endif
|
||||
@@ -84,6 +88,8 @@ typedef MirEGLNativeWindowType EGLNativeWindowType;
|
||||
#define EGL_OPENGL_ES_API 0x30a0
|
||||
#define EGL_OPENGL_API 0x30a2
|
||||
#define EGL_NONE 0x3038
|
||||
#define EGL_WIDTH 0x3057
|
||||
#define EGL_HEIGHT 0x3056
|
||||
#define EGL_EXTENSIONS 0x3055
|
||||
#define EGL_CONTEXT_CLIENT_VERSION 0x3098
|
||||
#define EGL_NATIVE_VISUAL_ID 0x302e
|
||||
@@ -118,6 +124,7 @@ typedef void* EGLConfig;
|
||||
typedef void* EGLContext;
|
||||
typedef void* EGLDisplay;
|
||||
typedef void* EGLSurface;
|
||||
typedef intptr_t EGLAttrib;
|
||||
|
||||
// EGL function pointer typedefs
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*);
|
||||
|
||||
@@ -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
|
||||
;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
#cmakedefine _GLFW_MIR
|
||||
// Define this to 1 if building GLFW for 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
|
||||
#cmakedefine _GLFW_BUILD_DLL
|
||||
|
||||
@@ -190,6 +190,8 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
||||
#include "mir_platform.h"
|
||||
#elif defined(_GLFW_OSMESA)
|
||||
#include "null_platform.h"
|
||||
#elif defined(_GLFW_EGLDEVICE)
|
||||
#include "egldevice_platform.h"
|
||||
#else
|
||||
#error "No supported window creation API selected"
|
||||
#endif
|
||||
|
||||
+2
-1
@@ -869,7 +869,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceMirPresentationSupportKHR vkGetPhysicalDeviceMirPresentationSupportKHR =
|
||||
PFN_vkGetPhysicalDeviceMirPresentationSupportKHR
|
||||
vkGetPhysicalDeviceMirPresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceMirPresentationSupportKHR)
|
||||
|
||||
+6
-3
@@ -30,7 +30,8 @@
|
||||
#include <stdlib.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
|
||||
|
||||
@@ -68,7 +69,8 @@ static GLFWbool loadLibraries(void)
|
||||
_glfw.win32.winmm.instance = LoadLibraryA("winmm.dll");
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -78,7 +80,8 @@ static GLFWbool loadLibraries(void)
|
||||
_glfw.win32.user32.instance = LoadLibraryA("user32.dll");
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
+26
-14
@@ -50,16 +50,26 @@ typedef struct _GLFWobjenumWin32
|
||||
|
||||
// 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_GUID_XAxis = {0xa36d02e0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_YAxis = {0xa36d02e1,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_ZAxis = {0xa36d02e2,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_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}};
|
||||
static const GUID _glfw_IID_IDirectInput8W =
|
||||
{0xbf798031,0x483a,0x4da2,{0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00}};
|
||||
static const GUID _glfw_GUID_XAxis =
|
||||
{0xa36d02e0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_YAxis =
|
||||
{0xa36d02e1,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_ZAxis =
|
||||
{0xa36d02e2,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_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 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++)
|
||||
{
|
||||
if (!_glfw.joysticks[jid].present)
|
||||
continue;
|
||||
if (memcmp(&_glfw.joysticks[jid].win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||
return DIENUM_CONTINUE;
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
if (js->present)
|
||||
{
|
||||
if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (supportsXInput(&di->guidProduct))
|
||||
|
||||
+2
-1
@@ -1798,7 +1798,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR =
|
||||
PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
|
||||
vkGetPhysicalDeviceWin32PresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceWin32PresentationSupportKHR)
|
||||
|
||||
+2
-1
@@ -1019,7 +1019,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR =
|
||||
PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
|
||||
vkGetPhysicalDeviceWaylandPresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceWaylandPresentationSupportKHR)
|
||||
|
||||
+7
-8
@@ -237,8 +237,8 @@ static void createKeyTables(void)
|
||||
|
||||
if (_glfw.x11.xkb.available)
|
||||
{
|
||||
// Use XKB to determine physical key locations independently of the current
|
||||
// keyboard layout
|
||||
// Use XKB to determine physical key locations independently of the
|
||||
// current keyboard layout
|
||||
|
||||
char name[XkbKeyNameLength + 1];
|
||||
XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd);
|
||||
@@ -661,10 +661,7 @@ static GLFWbool initExtensions(void)
|
||||
|
||||
// String format atoms
|
||||
_glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);
|
||||
_glfw.x11.UTF8_STRING =
|
||||
XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
|
||||
_glfw.x11.COMPOUND_STRING =
|
||||
XInternAtom(_glfw.x11.display, "COMPOUND_STRING", False);
|
||||
_glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
|
||||
_glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False);
|
||||
|
||||
// Custom selection property atom
|
||||
@@ -675,6 +672,7 @@ static GLFWbool initExtensions(void)
|
||||
_glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False);
|
||||
_glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", 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);
|
||||
|
||||
// Clipboard manager atoms
|
||||
@@ -862,12 +860,13 @@ int _glfwPlatformInit(void)
|
||||
_glfw.x11.screen = DefaultScreen(_glfw.x11.display);
|
||||
_glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen);
|
||||
_glfw.x11.context = XUniqueContext();
|
||||
_glfw.x11.helperWindowHandle = createHelperWindow();
|
||||
_glfw.x11.hiddenCursorHandle = createHiddenCursor();
|
||||
|
||||
if (!initExtensions())
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfw.x11.helperWindowHandle = createHelperWindow();
|
||||
_glfw.x11.hiddenCursorHandle = createHiddenCursor();
|
||||
|
||||
if (XSupportsLocale())
|
||||
{
|
||||
XSetLocaleModifiers("");
|
||||
|
||||
@@ -265,6 +265,7 @@ typedef struct _GLFWlibraryX11
|
||||
// Selection (clipboard) atoms
|
||||
Atom TARGETS;
|
||||
Atom MULTIPLE;
|
||||
Atom INCR;
|
||||
Atom CLIPBOARD;
|
||||
Atom PRIMARY;
|
||||
Atom CLIPBOARD_MANAGER;
|
||||
|
||||
+192
-93
@@ -164,6 +164,17 @@ static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointe
|
||||
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
|
||||
//
|
||||
static int translateCursorShape(int shape)
|
||||
@@ -449,6 +460,81 @@ static char** parseUriList(char* text, int* count)
|
||||
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
|
||||
//
|
||||
static void centerCursor(_GLFWwindow* window)
|
||||
@@ -672,9 +758,7 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
|
||||
{
|
||||
int i;
|
||||
char* selectionString = NULL;
|
||||
const Atom formats[] = { _glfw.x11.UTF8_STRING,
|
||||
_glfw.x11.COMPOUND_STRING,
|
||||
XA_STRING };
|
||||
const Atom formats[] = { _glfw.x11.UTF8_STRING, XA_STRING };
|
||||
const int formatCount = sizeof(formats) / sizeof(formats[0]);
|
||||
|
||||
if (request->selection == _glfw.x11.PRIMARY)
|
||||
@@ -696,7 +780,6 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
|
||||
const Atom targets[] = { _glfw.x11.TARGETS,
|
||||
_glfw.x11.MULTIPLE,
|
||||
_glfw.x11.UTF8_STRING,
|
||||
_glfw.x11.COMPOUND_STRING,
|
||||
XA_STRING };
|
||||
|
||||
XChangeProperty(_glfw.x11.display,
|
||||
@@ -841,10 +924,8 @@ static const char* getSelectionString(Atom selection)
|
||||
{
|
||||
size_t i;
|
||||
char** selectionString = NULL;
|
||||
const Atom formats[] = { _glfw.x11.UTF8_STRING,
|
||||
_glfw.x11.COMPOUND_STRING,
|
||||
XA_STRING };
|
||||
const size_t formatCount = sizeof(formats) / sizeof(formats[0]);
|
||||
const Atom targets[] = { _glfw.x11.UTF8_STRING, XA_STRING };
|
||||
const size_t targetCount = sizeof(targets) / sizeof(targets[0]);
|
||||
|
||||
if (selection == _glfw.x11.PRIMARY)
|
||||
selectionString = &_glfw.x11.primarySelectionString;
|
||||
@@ -862,14 +943,17 @@ static const char* getSelectionString(Atom selection)
|
||||
free(*selectionString);
|
||||
*selectionString = NULL;
|
||||
|
||||
for (i = 0; i < formatCount; i++)
|
||||
for (i = 0; i < targetCount; i++)
|
||||
{
|
||||
char* data;
|
||||
XEvent event;
|
||||
Atom actualType;
|
||||
int actualFormat;
|
||||
unsigned long itemCount, bytesAfter;
|
||||
XEvent notification, dummy;
|
||||
|
||||
XConvertSelection(_glfw.x11.display,
|
||||
selection,
|
||||
formats[i],
|
||||
targets[i],
|
||||
_glfw.x11.GLFW_SELECTION,
|
||||
_glfw.x11.helperWindowHandle,
|
||||
CurrentTime);
|
||||
@@ -877,28 +961,92 @@ static const char* getSelectionString(Atom selection)
|
||||
while (!XCheckTypedWindowEvent(_glfw.x11.display,
|
||||
_glfw.x11.helperWindowHandle,
|
||||
SelectionNotify,
|
||||
&event))
|
||||
¬ification))
|
||||
{
|
||||
waitForEvent(NULL);
|
||||
}
|
||||
|
||||
if (event.xselection.property == None)
|
||||
if (notification.xselection.property == None)
|
||||
continue;
|
||||
|
||||
if (_glfwGetWindowPropertyX11(event.xselection.requestor,
|
||||
event.xselection.property,
|
||||
event.xselection.target,
|
||||
(unsigned char**) &data))
|
||||
XCheckIfEvent(_glfw.x11.display,
|
||||
&dummy,
|
||||
isSelPropNewValueNotify,
|
||||
(XPointer) ¬ification);
|
||||
|
||||
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) ¬ification))
|
||||
{
|
||||
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);
|
||||
|
||||
XDeleteProperty(_glfw.x11.display,
|
||||
event.xselection.requestor,
|
||||
event.xselection.property);
|
||||
XFree(data);
|
||||
|
||||
if (*selectionString)
|
||||
break;
|
||||
@@ -907,7 +1055,7 @@ static const char* getSelectionString(Atom selection)
|
||||
if (!*selectionString)
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"X11: Failed to convert clipboard to string");
|
||||
"X11: Failed to convert selection to string");
|
||||
}
|
||||
|
||||
return *selectionString;
|
||||
@@ -978,62 +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*/
|
||||
|
||||
// Process the specified X event
|
||||
//
|
||||
static void processEvent(XEvent *event)
|
||||
@@ -1171,8 +1263,10 @@ static void processEvent(XEvent *event)
|
||||
|
||||
count = XwcLookupString(window->x11.ic,
|
||||
&event->xkey,
|
||||
buffer, sizeof(buffer) / sizeof(wchar_t),
|
||||
NULL, &status);
|
||||
buffer,
|
||||
sizeof(buffer) / sizeof(wchar_t),
|
||||
NULL,
|
||||
&status);
|
||||
|
||||
if (status == XBufferOverflow)
|
||||
{
|
||||
@@ -1345,7 +1439,8 @@ static void processEvent(XEvent *event)
|
||||
const int x = event->xmotion.x;
|
||||
const int y = event->xmotion.y;
|
||||
|
||||
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
|
||||
|
||||
@@ -1424,14 +1519,15 @@ static void processEvent(XEvent *event)
|
||||
|
||||
if (protocol == _glfw.x11.WM_DELETE_WINDOW)
|
||||
{
|
||||
// The window manager was asked to close the window, for example by
|
||||
// the user pressing a 'close' window decoration button
|
||||
// The window manager was asked to close the window, for
|
||||
// example by the user pressing a 'close' window decoration
|
||||
// button
|
||||
_glfwInputWindowCloseRequest(window);
|
||||
}
|
||||
else if (protocol == _glfw.x11.NET_WM_PING)
|
||||
{
|
||||
// The window manager is pinging the application to ensure it's
|
||||
// still responding to events
|
||||
// The window manager is pinging the application to ensure
|
||||
// it's still responding to events
|
||||
|
||||
XEvent reply = *event;
|
||||
reply.xclient.window = _glfw.x11.root;
|
||||
@@ -1773,9 +1869,10 @@ void _glfwPushSelectionToManagerX11(void)
|
||||
{
|
||||
if (event.xselection.target == _glfw.x11.SAVE_TARGETS)
|
||||
{
|
||||
// This means one of two things; either the selection was
|
||||
// not owned, which means there is no clipboard manager, or
|
||||
// the transfer to the clipboard manager has completed
|
||||
// This means one of two things; either the selection
|
||||
// was not owned, which means there is no clipboard
|
||||
// manager, or the transfer to the clipboard manager has
|
||||
// completed
|
||||
// In either case, it means we are done here
|
||||
return;
|
||||
}
|
||||
@@ -2695,7 +2792,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
|
||||
if (_glfw.vk.KHR_xcb_surface && _glfw.x11.x11xcb.handle)
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR =
|
||||
PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR
|
||||
vkGetPhysicalDeviceXcbPresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceXcbPresentationSupportKHR)
|
||||
@@ -2720,7 +2818,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
}
|
||||
else
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR =
|
||||
PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR
|
||||
vkGetPhysicalDeviceXlibPresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceXlibPresentationSupportKHR)
|
||||
|
||||
Reference in New Issue
Block a user