Replace Linux windows with GLFW for cross-platform
This commit is contained in:
parent
9fbd7938d0
commit
086c3b5475
|
@ -0,0 +1,8 @@
|
||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
project(glad)
|
||||||
|
|
||||||
|
|
||||||
|
add_library(glad)
|
||||||
|
target_sources(glad PRIVATE src/glad.c)
|
||||||
|
target_include_directories(glad PUBLIC include)
|
||||||
|
|
|
@ -0,0 +1,290 @@
|
||||||
|
#ifndef __khrplatform_h_
|
||||||
|
#define __khrplatform_h_
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Copyright (c) 2008-2018 The Khronos Group Inc.
|
||||||
|
**
|
||||||
|
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
** copy of this software and/or associated documentation files (the
|
||||||
|
** "Materials"), to deal in the Materials without restriction, including
|
||||||
|
** without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||||
|
** permit persons to whom the Materials are furnished to do so, subject to
|
||||||
|
** the following conditions:
|
||||||
|
**
|
||||||
|
** The above copyright notice and this permission notice shall be included
|
||||||
|
** in all copies or substantial portions of the Materials.
|
||||||
|
**
|
||||||
|
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Khronos platform-specific types and definitions.
|
||||||
|
*
|
||||||
|
* The master copy of khrplatform.h is maintained in the Khronos EGL
|
||||||
|
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
|
||||||
|
* The last semantic modification to khrplatform.h was at commit ID:
|
||||||
|
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
|
||||||
|
*
|
||||||
|
* Adopters may modify this file to suit their platform. Adopters are
|
||||||
|
* encouraged to submit platform specific modifications to the Khronos
|
||||||
|
* group so that they can be included in future versions of this file.
|
||||||
|
* Please submit changes by filing pull requests or issues on
|
||||||
|
* the EGL Registry repository linked above.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* See the Implementer's Guidelines for information about where this file
|
||||||
|
* should be located on your system and for more details of its use:
|
||||||
|
* http://www.khronos.org/registry/implementers_guide.pdf
|
||||||
|
*
|
||||||
|
* This file should be included as
|
||||||
|
* #include <KHR/khrplatform.h>
|
||||||
|
* by Khronos client API header files that use its types and defines.
|
||||||
|
*
|
||||||
|
* The types in khrplatform.h should only be used to define API-specific types.
|
||||||
|
*
|
||||||
|
* Types defined in khrplatform.h:
|
||||||
|
* khronos_int8_t signed 8 bit
|
||||||
|
* khronos_uint8_t unsigned 8 bit
|
||||||
|
* khronos_int16_t signed 16 bit
|
||||||
|
* khronos_uint16_t unsigned 16 bit
|
||||||
|
* khronos_int32_t signed 32 bit
|
||||||
|
* khronos_uint32_t unsigned 32 bit
|
||||||
|
* khronos_int64_t signed 64 bit
|
||||||
|
* khronos_uint64_t unsigned 64 bit
|
||||||
|
* khronos_intptr_t signed same number of bits as a pointer
|
||||||
|
* khronos_uintptr_t unsigned same number of bits as a pointer
|
||||||
|
* khronos_ssize_t signed size
|
||||||
|
* khronos_usize_t unsigned size
|
||||||
|
* khronos_float_t signed 32 bit floating point
|
||||||
|
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
|
||||||
|
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
|
||||||
|
* nanoseconds
|
||||||
|
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
|
||||||
|
* khronos_boolean_enum_t enumerated boolean type. This should
|
||||||
|
* only be used as a base type when a client API's boolean type is
|
||||||
|
* an enum. Client APIs which use an integer or other type for
|
||||||
|
* booleans cannot use this as the base type for their boolean.
|
||||||
|
*
|
||||||
|
* Tokens defined in khrplatform.h:
|
||||||
|
*
|
||||||
|
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
|
||||||
|
*
|
||||||
|
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
|
||||||
|
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
|
||||||
|
*
|
||||||
|
* Calling convention macros defined in this file:
|
||||||
|
* KHRONOS_APICALL
|
||||||
|
* KHRONOS_APIENTRY
|
||||||
|
* KHRONOS_APIATTRIBUTES
|
||||||
|
*
|
||||||
|
* These may be used in function prototypes as:
|
||||||
|
*
|
||||||
|
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
|
||||||
|
* int arg1,
|
||||||
|
* int arg2) KHRONOS_APIATTRIBUTES;
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
|
||||||
|
# define KHRONOS_STATIC 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APICALL
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This precedes the return type of the function in the function prototype.
|
||||||
|
*/
|
||||||
|
#if defined(KHRONOS_STATIC)
|
||||||
|
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
|
||||||
|
* header compatible with static linking. */
|
||||||
|
# define KHRONOS_APICALL
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
# define KHRONOS_APICALL __declspec(dllimport)
|
||||||
|
#elif defined (__SYMBIAN32__)
|
||||||
|
# define KHRONOS_APICALL IMPORT_C
|
||||||
|
#elif defined(__ANDROID__)
|
||||||
|
# define KHRONOS_APICALL __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
# define KHRONOS_APICALL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APIENTRY
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This follows the return type of the function and precedes the function
|
||||||
|
* name in the function prototype.
|
||||||
|
*/
|
||||||
|
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
|
||||||
|
/* Win32 but not WinCE */
|
||||||
|
# define KHRONOS_APIENTRY __stdcall
|
||||||
|
#else
|
||||||
|
# define KHRONOS_APIENTRY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APIATTRIBUTES
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This follows the closing parenthesis of the function prototype arguments.
|
||||||
|
*/
|
||||||
|
#if defined (__ARMCC_2__)
|
||||||
|
#define KHRONOS_APIATTRIBUTES __softfp
|
||||||
|
#else
|
||||||
|
#define KHRONOS_APIATTRIBUTES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* basic type definitions
|
||||||
|
*-----------------------------------------------------------------------*/
|
||||||
|
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Using <stdint.h>
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif defined(__VMS ) || defined(__sgi)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Using <inttypes.h>
|
||||||
|
*/
|
||||||
|
#include <inttypes.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Win32
|
||||||
|
*/
|
||||||
|
typedef __int32 khronos_int32_t;
|
||||||
|
typedef unsigned __int32 khronos_uint32_t;
|
||||||
|
typedef __int64 khronos_int64_t;
|
||||||
|
typedef unsigned __int64 khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif defined(__sun__) || defined(__digital__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sun or Digital
|
||||||
|
*/
|
||||||
|
typedef int khronos_int32_t;
|
||||||
|
typedef unsigned int khronos_uint32_t;
|
||||||
|
#if defined(__arch64__) || defined(_LP64)
|
||||||
|
typedef long int khronos_int64_t;
|
||||||
|
typedef unsigned long int khronos_uint64_t;
|
||||||
|
#else
|
||||||
|
typedef long long int khronos_int64_t;
|
||||||
|
typedef unsigned long long int khronos_uint64_t;
|
||||||
|
#endif /* __arch64__ */
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hypothetical platform with no float or int64 support
|
||||||
|
*/
|
||||||
|
typedef int khronos_int32_t;
|
||||||
|
typedef unsigned int khronos_uint32_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 0
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 0
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generic fallback
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types that are (so far) the same on all platforms
|
||||||
|
*/
|
||||||
|
typedef signed char khronos_int8_t;
|
||||||
|
typedef unsigned char khronos_uint8_t;
|
||||||
|
typedef signed short int khronos_int16_t;
|
||||||
|
typedef unsigned short int khronos_uint16_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types that differ between LLP64 and LP64 architectures - in LLP64,
|
||||||
|
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
|
||||||
|
* to be the only LLP64 architecture in current use.
|
||||||
|
*/
|
||||||
|
#ifdef _WIN64
|
||||||
|
typedef signed long long int khronos_intptr_t;
|
||||||
|
typedef unsigned long long int khronos_uintptr_t;
|
||||||
|
typedef signed long long int khronos_ssize_t;
|
||||||
|
typedef unsigned long long int khronos_usize_t;
|
||||||
|
#else
|
||||||
|
typedef signed long int khronos_intptr_t;
|
||||||
|
typedef unsigned long int khronos_uintptr_t;
|
||||||
|
typedef signed long int khronos_ssize_t;
|
||||||
|
typedef unsigned long int khronos_usize_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if KHRONOS_SUPPORT_FLOAT
|
||||||
|
/*
|
||||||
|
* Float type
|
||||||
|
*/
|
||||||
|
typedef float khronos_float_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if KHRONOS_SUPPORT_INT64
|
||||||
|
/* Time types
|
||||||
|
*
|
||||||
|
* These types can be used to represent a time interval in nanoseconds or
|
||||||
|
* an absolute Unadjusted System Time. Unadjusted System Time is the number
|
||||||
|
* of nanoseconds since some arbitrary system event (e.g. since the last
|
||||||
|
* time the system booted). The Unadjusted System Time is an unsigned
|
||||||
|
* 64 bit value that wraps back to 0 every 584 years. Time intervals
|
||||||
|
* may be either signed or unsigned.
|
||||||
|
*/
|
||||||
|
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
|
||||||
|
typedef khronos_int64_t khronos_stime_nanoseconds_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dummy value used to pad enum types to 32 bits.
|
||||||
|
*/
|
||||||
|
#ifndef KHRONOS_MAX_ENUM
|
||||||
|
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enumerated boolean type
|
||||||
|
*
|
||||||
|
* Values other than zero should be considered to be true. Therefore
|
||||||
|
* comparisons should not be made against KHRONOS_TRUE.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
KHRONOS_FALSE = 0,
|
||||||
|
KHRONOS_TRUE = 1,
|
||||||
|
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
|
||||||
|
} khronos_boolean_enum_t;
|
||||||
|
|
||||||
|
#endif /* __khrplatform_h_ */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,381 @@
|
||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
|
||||||
|
project(GLFW VERSION 3.3.3 LANGUAGES C)
|
||||||
|
|
||||||
|
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
|
||||||
|
|
||||||
|
if (POLICY CMP0054)
|
||||||
|
cmake_policy(SET CMP0054 NEW)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (POLICY CMP0069)
|
||||||
|
cmake_policy(SET CMP0069 NEW)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (POLICY CMP0077)
|
||||||
|
cmake_policy(SET CMP0077 NEW)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
|
||||||
|
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
|
||||||
|
option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" ON)
|
||||||
|
option(GLFW_BUILD_TESTS "Build the GLFW test programs" ON)
|
||||||
|
option(GLFW_BUILD_DOCS "Build the GLFW documentation" ON)
|
||||||
|
option(GLFW_INSTALL "Generate installation target" ON)
|
||||||
|
option(GLFW_VULKAN_STATIC "Assume the Vulkan loader is linked with the application" OFF)
|
||||||
|
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
include(CMakeDependentOption)
|
||||||
|
|
||||||
|
cmake_dependent_option(GLFW_USE_OSMESA "Use OSMesa for offscreen context creation" OFF
|
||||||
|
"UNIX" OFF)
|
||||||
|
cmake_dependent_option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF
|
||||||
|
"WIN32" OFF)
|
||||||
|
cmake_dependent_option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF
|
||||||
|
"UNIX;NOT APPLE" OFF)
|
||||||
|
cmake_dependent_option(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC runtime library DLL" ON
|
||||||
|
"MSVC" OFF)
|
||||||
|
|
||||||
|
if (BUILD_SHARED_LIBS)
|
||||||
|
set(_GLFW_BUILD_DLL 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (BUILD_SHARED_LIBS AND UNIX)
|
||||||
|
# On Unix-like systems, shared libraries can use the soname system.
|
||||||
|
set(GLFW_LIB_NAME glfw)
|
||||||
|
else()
|
||||||
|
set(GLFW_LIB_NAME glfw3)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (GLFW_VULKAN_STATIC)
|
||||||
|
if (BUILD_SHARED_LIBS)
|
||||||
|
# If you absolutely must do this, remove this line and add the Vulkan
|
||||||
|
# loader static library via the CMAKE_SHARED_LINKER_FLAGS
|
||||||
|
message(FATAL_ERROR "You are trying to link the Vulkan loader static library into the GLFW shared library")
|
||||||
|
endif()
|
||||||
|
set(_GLFW_VULKAN_STATIC 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(APPEND CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules")
|
||||||
|
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
|
if (GLFW_BUILD_DOCS)
|
||||||
|
set(DOXYGEN_SKIP_DOT TRUE)
|
||||||
|
find_package(Doxygen)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# Set compiler specific flags
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
if (MSVC)
|
||||||
|
if (MSVC90)
|
||||||
|
# Workaround for VS 2008 not shipping with the DirectX 9 SDK
|
||||||
|
include(CheckIncludeFile)
|
||||||
|
check_include_file(dinput.h DINPUT_H_FOUND)
|
||||||
|
if (NOT DINPUT_H_FOUND)
|
||||||
|
message(FATAL_ERROR "DirectX 9 headers not found; install DirectX 9 SDK")
|
||||||
|
endif()
|
||||||
|
# Workaround for VS 2008 not shipping with stdint.h
|
||||||
|
list(APPEND glfw_INCLUDE_DIRS "${GLFW_SOURCE_DIR}/deps/vs2008")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT USE_MSVC_RUNTIME_LIBRARY_DLL)
|
||||||
|
foreach (flag CMAKE_C_FLAGS
|
||||||
|
CMAKE_C_FLAGS_DEBUG
|
||||||
|
CMAKE_C_FLAGS_RELEASE
|
||||||
|
CMAKE_C_FLAGS_MINSIZEREL
|
||||||
|
CMAKE_C_FLAGS_RELWITHDEBINFO)
|
||||||
|
|
||||||
|
if (${flag} MATCHES "/MD")
|
||||||
|
string(REGEX REPLACE "/MD" "/MT" ${flag} "${${flag}}")
|
||||||
|
endif()
|
||||||
|
if (${flag} MATCHES "/MDd")
|
||||||
|
string(REGEX REPLACE "/MDd" "/MTd" ${flag} "${${flag}}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (MINGW)
|
||||||
|
# Workaround for legacy MinGW not providing XInput and DirectInput
|
||||||
|
include(CheckIncludeFile)
|
||||||
|
|
||||||
|
check_include_file(dinput.h DINPUT_H_FOUND)
|
||||||
|
check_include_file(xinput.h XINPUT_H_FOUND)
|
||||||
|
if (NOT DINPUT_H_FOUND OR NOT XINPUT_H_FOUND)
|
||||||
|
list(APPEND glfw_INCLUDE_DIRS "${GLFW_SOURCE_DIR}/deps/mingw")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Enable link-time exploit mitigation features enabled by default on MSVC
|
||||||
|
include(CheckCCompilerFlag)
|
||||||
|
|
||||||
|
# Compatibility with data execution prevention (DEP)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "-Wl,--nxcompat")
|
||||||
|
check_c_compiler_flag("" _GLFW_HAS_DEP)
|
||||||
|
if (_GLFW_HAS_DEP)
|
||||||
|
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--nxcompat ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Compatibility with address space layout randomization (ASLR)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "-Wl,--dynamicbase")
|
||||||
|
check_c_compiler_flag("" _GLFW_HAS_ASLR)
|
||||||
|
if (_GLFW_HAS_ASLR)
|
||||||
|
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--dynamicbase ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Compatibility with 64-bit address space layout randomization (ASLR)
|
||||||
|
set(CMAKE_REQUIRED_FLAGS "-Wl,--high-entropy-va")
|
||||||
|
check_c_compiler_flag("" _GLFW_HAS_64ASLR)
|
||||||
|
if (_GLFW_HAS_64ASLR)
|
||||||
|
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--high-entropy-va ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Clear flags again to avoid breaking later tests
|
||||||
|
set(CMAKE_REQUIRED_FLAGS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# Detect and select backend APIs
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
if (GLFW_USE_WAYLAND)
|
||||||
|
set(_GLFW_WAYLAND 1)
|
||||||
|
message(STATUS "Using Wayland for window creation")
|
||||||
|
elseif (GLFW_USE_OSMESA)
|
||||||
|
set(_GLFW_OSMESA 1)
|
||||||
|
message(STATUS "Using OSMesa for headless context creation")
|
||||||
|
elseif (WIN32)
|
||||||
|
set(_GLFW_WIN32 1)
|
||||||
|
message(STATUS "Using Win32 for window creation")
|
||||||
|
elseif (APPLE)
|
||||||
|
set(_GLFW_COCOA 1)
|
||||||
|
message(STATUS "Using Cocoa for window creation")
|
||||||
|
elseif (UNIX)
|
||||||
|
set(_GLFW_X11 1)
|
||||||
|
message(STATUS "Using X11 for window creation")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "No supported platform was detected")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# Find and add Unix math and time libraries
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
if (UNIX AND NOT APPLE)
|
||||||
|
find_library(RT_LIBRARY rt)
|
||||||
|
mark_as_advanced(RT_LIBRARY)
|
||||||
|
if (RT_LIBRARY)
|
||||||
|
list(APPEND glfw_LIBRARIES "${RT_LIBRARY}")
|
||||||
|
list(APPEND glfw_PKG_LIBS "-lrt")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_library(MATH_LIBRARY m)
|
||||||
|
mark_as_advanced(MATH_LIBRARY)
|
||||||
|
if (MATH_LIBRARY)
|
||||||
|
list(APPEND glfw_LIBRARIES "${MATH_LIBRARY}")
|
||||||
|
list(APPEND glfw_PKG_LIBS "-lm")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (CMAKE_DL_LIBS)
|
||||||
|
list(APPEND glfw_LIBRARIES "${CMAKE_DL_LIBS}")
|
||||||
|
list(APPEND glfw_PKG_LIBS "-l${CMAKE_DL_LIBS}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# Use Win32 for window creation
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
if (_GLFW_WIN32)
|
||||||
|
|
||||||
|
list(APPEND glfw_PKG_LIBS "-lgdi32")
|
||||||
|
|
||||||
|
if (GLFW_USE_HYBRID_HPG)
|
||||||
|
set(_GLFW_USE_HYBRID_HPG 1)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# Use X11 for window creation
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
if (_GLFW_X11)
|
||||||
|
|
||||||
|
find_package(X11 REQUIRED)
|
||||||
|
|
||||||
|
list(APPEND glfw_PKG_DEPS "x11")
|
||||||
|
|
||||||
|
# Set up library and include paths
|
||||||
|
list(APPEND glfw_INCLUDE_DIRS "${X11_X11_INCLUDE_PATH}")
|
||||||
|
list(APPEND glfw_LIBRARIES "${X11_X11_LIB}" "${CMAKE_THREAD_LIBS_INIT}")
|
||||||
|
|
||||||
|
# Check for XRandR (modern resolution switching and gamma control)
|
||||||
|
if (NOT X11_Xrandr_INCLUDE_PATH)
|
||||||
|
message(FATAL_ERROR "RandR headers not found; install libxrandr development package")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check for Xinerama (legacy multi-monitor support)
|
||||||
|
if (NOT X11_Xinerama_INCLUDE_PATH)
|
||||||
|
message(FATAL_ERROR "Xinerama headers not found; install libxinerama development package")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check for Xkb (X keyboard extension)
|
||||||
|
if (NOT X11_Xkb_INCLUDE_PATH)
|
||||||
|
message(FATAL_ERROR "XKB headers not found; install X11 development package")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check for Xcursor (cursor creation from RGBA images)
|
||||||
|
if (NOT X11_Xcursor_INCLUDE_PATH)
|
||||||
|
message(FATAL_ERROR "Xcursor headers not found; install libxcursor development package")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check for XInput (modern HID input)
|
||||||
|
if (NOT X11_Xi_INCLUDE_PATH)
|
||||||
|
message(FATAL_ERROR "XInput headers not found; install libxi development package")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(APPEND glfw_INCLUDE_DIRS "${X11_Xrandr_INCLUDE_PATH}"
|
||||||
|
"${X11_Xinerama_INCLUDE_PATH}"
|
||||||
|
"${X11_Xkb_INCLUDE_PATH}"
|
||||||
|
"${X11_Xcursor_INCLUDE_PATH}"
|
||||||
|
"${X11_Xi_INCLUDE_PATH}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# Use Wayland for window creation
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
if (_GLFW_WAYLAND)
|
||||||
|
find_package(ECM REQUIRED NO_MODULE)
|
||||||
|
list(APPEND CMAKE_MODULE_PATH "${ECM_MODULE_PATH}")
|
||||||
|
|
||||||
|
find_package(Wayland REQUIRED Client Cursor Egl)
|
||||||
|
find_package(WaylandScanner REQUIRED)
|
||||||
|
find_package(WaylandProtocols 1.15 REQUIRED)
|
||||||
|
|
||||||
|
list(APPEND glfw_PKG_DEPS "wayland-client")
|
||||||
|
|
||||||
|
list(APPEND glfw_INCLUDE_DIRS "${Wayland_INCLUDE_DIRS}")
|
||||||
|
list(APPEND glfw_LIBRARIES "${Wayland_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}")
|
||||||
|
|
||||||
|
find_package(XKBCommon REQUIRED)
|
||||||
|
list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
|
||||||
|
|
||||||
|
include(CheckIncludeFiles)
|
||||||
|
include(CheckFunctionExists)
|
||||||
|
check_include_files(xkbcommon/xkbcommon-compose.h HAVE_XKBCOMMON_COMPOSE_H)
|
||||||
|
check_function_exists(memfd_create HAVE_MEMFD_CREATE)
|
||||||
|
|
||||||
|
if (NOT ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux"))
|
||||||
|
find_package(EpollShim)
|
||||||
|
if (EPOLLSHIM_FOUND)
|
||||||
|
list(APPEND glfw_INCLUDE_DIRS "${EPOLLSHIM_INCLUDE_DIRS}")
|
||||||
|
list(APPEND glfw_LIBRARIES "${EPOLLSHIM_LIBRARIES}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# Use OSMesa for offscreen context creation
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
if (_GLFW_OSMESA)
|
||||||
|
find_package(OSMesa REQUIRED)
|
||||||
|
list(APPEND glfw_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# Use Cocoa for window creation and NSOpenGL for context creation
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
if (_GLFW_COCOA)
|
||||||
|
|
||||||
|
list(APPEND glfw_LIBRARIES
|
||||||
|
"-framework Cocoa"
|
||||||
|
"-framework IOKit"
|
||||||
|
"-framework CoreFoundation")
|
||||||
|
|
||||||
|
set(glfw_PKG_DEPS "")
|
||||||
|
set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# Add the Vulkan loader as a dependency if necessary
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
if (GLFW_VULKAN_STATIC)
|
||||||
|
list(APPEND glfw_PKG_DEPS "vulkan")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# Export GLFW library dependencies
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
foreach(arg ${glfw_PKG_DEPS})
|
||||||
|
set(GLFW_PKG_DEPS "${GLFW_PKG_DEPS} ${arg}")
|
||||||
|
endforeach()
|
||||||
|
foreach(arg ${glfw_PKG_LIBS})
|
||||||
|
set(GLFW_PKG_LIBS "${GLFW_PKG_LIBS} ${arg}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# Create generated files
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
|
|
||||||
|
set(GLFW_CONFIG_PATH "${CMAKE_INSTALL_LIBDIR}/cmake/glfw3")
|
||||||
|
|
||||||
|
configure_package_config_file(src/glfw3Config.cmake.in
|
||||||
|
src/glfw3Config.cmake
|
||||||
|
INSTALL_DESTINATION "${GLFW_CONFIG_PATH}"
|
||||||
|
NO_CHECK_REQUIRED_COMPONENTS_MACRO)
|
||||||
|
|
||||||
|
write_basic_package_version_file(src/glfw3ConfigVersion.cmake
|
||||||
|
VERSION ${GLFW_VERSION}
|
||||||
|
COMPATIBILITY SameMajorVersion)
|
||||||
|
|
||||||
|
configure_file(src/glfw_config.h.in src/glfw_config.h @ONLY)
|
||||||
|
|
||||||
|
configure_file(src/glfw3.pc.in src/glfw3.pc @ONLY)
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# Add subdirectories
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
add_subdirectory(src)
|
||||||
|
|
||||||
|
if (GLFW_BUILD_EXAMPLES)
|
||||||
|
add_subdirectory(examples)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (GLFW_BUILD_TESTS)
|
||||||
|
add_subdirectory(tests)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (DOXYGEN_FOUND AND GLFW_BUILD_DOCS)
|
||||||
|
add_subdirectory(docs)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# Install files other than the library
|
||||||
|
# The library is installed by src/CMakeLists.txt
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
if (GLFW_INSTALL)
|
||||||
|
install(DIRECTORY include/GLFW DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
FILES_MATCHING PATTERN glfw3.h PATTERN glfw3native.h)
|
||||||
|
|
||||||
|
install(FILES "${GLFW_BINARY_DIR}/src/glfw3Config.cmake"
|
||||||
|
"${GLFW_BINARY_DIR}/src/glfw3ConfigVersion.cmake"
|
||||||
|
DESTINATION "${GLFW_CONFIG_PATH}")
|
||||||
|
|
||||||
|
install(EXPORT glfwTargets FILE glfw3Targets.cmake
|
||||||
|
EXPORT_LINK_INTERFACE_LIBRARIES
|
||||||
|
DESTINATION "${GLFW_CONFIG_PATH}")
|
||||||
|
install(FILES "${GLFW_BINARY_DIR}/src/glfw3.pc"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||||
|
|
||||||
|
# Only generate this target if no higher-level project already has
|
||||||
|
if (NOT TARGET uninstall)
|
||||||
|
configure_file(cmake_uninstall.cmake.in
|
||||||
|
cmake_uninstall.cmake IMMEDIATE @ONLY)
|
||||||
|
|
||||||
|
add_custom_target(uninstall
|
||||||
|
"${CMAKE_COMMAND}" -P
|
||||||
|
"${GLFW_BINARY_DIR}/cmake_uninstall.cmake")
|
||||||
|
set_target_properties(uninstall PROPERTIES FOLDER "GLFW3")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
|
||||||
|
Copyright (c) 2006-2019 Camilla Löwy
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,525 @@
|
||||||
|
/*************************************************************************
|
||||||
|
* GLFW 3.3 - www.glfw.org
|
||||||
|
* A library for OpenGL, window and input
|
||||||
|
*------------------------------------------------------------------------
|
||||||
|
* Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
* Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express or implied
|
||||||
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
|
* arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose,
|
||||||
|
* including commercial applications, and to alter it and redistribute it
|
||||||
|
* freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
* claim that you wrote the original software. If you use this software
|
||||||
|
* in a product, an acknowledgment in the product documentation would
|
||||||
|
* be appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
* be misrepresented as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _glfw3_native_h_
|
||||||
|
#define _glfw3_native_h_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Doxygen documentation
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
/*! @file glfw3native.h
|
||||||
|
* @brief The header of the native access functions.
|
||||||
|
*
|
||||||
|
* This is the header file of the native access functions. See @ref native for
|
||||||
|
* more information.
|
||||||
|
*/
|
||||||
|
/*! @defgroup native Native access
|
||||||
|
* @brief Functions related to accessing native handles.
|
||||||
|
*
|
||||||
|
* **By using the native access functions you assert that you know what you're
|
||||||
|
* doing and how to fix problems caused by using them. If you don't, you
|
||||||
|
* shouldn't be using them.**
|
||||||
|
*
|
||||||
|
* Before the inclusion of @ref glfw3native.h, you may define zero or more
|
||||||
|
* window system API macro and zero or more context creation API macros.
|
||||||
|
*
|
||||||
|
* The chosen backends must match those the library was compiled for. Failure
|
||||||
|
* to do this will cause a link-time error.
|
||||||
|
*
|
||||||
|
* The available window API macros are:
|
||||||
|
* * `GLFW_EXPOSE_NATIVE_WIN32`
|
||||||
|
* * `GLFW_EXPOSE_NATIVE_COCOA`
|
||||||
|
* * `GLFW_EXPOSE_NATIVE_X11`
|
||||||
|
* * `GLFW_EXPOSE_NATIVE_WAYLAND`
|
||||||
|
*
|
||||||
|
* The available context API macros are:
|
||||||
|
* * `GLFW_EXPOSE_NATIVE_WGL`
|
||||||
|
* * `GLFW_EXPOSE_NATIVE_NSGL`
|
||||||
|
* * `GLFW_EXPOSE_NATIVE_GLX`
|
||||||
|
* * `GLFW_EXPOSE_NATIVE_EGL`
|
||||||
|
* * `GLFW_EXPOSE_NATIVE_OSMESA`
|
||||||
|
*
|
||||||
|
* These macros select which of the native access functions that are declared
|
||||||
|
* and which platform-specific headers to include. It is then up your (by
|
||||||
|
* definition platform-specific) code to handle which of these should be
|
||||||
|
* defined.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* System headers and types
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL)
|
||||||
|
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
|
||||||
|
// example to allow applications to correctly declare a GL_ARB_debug_output
|
||||||
|
// callback) but windows.h assumes no one will define APIENTRY before it does
|
||||||
|
#if defined(GLFW_APIENTRY_DEFINED)
|
||||||
|
#undef APIENTRY
|
||||||
|
#undef GLFW_APIENTRY_DEFINED
|
||||||
|
#endif
|
||||||
|
#include <windows.h>
|
||||||
|
#elif defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL)
|
||||||
|
#if defined(__OBJC__)
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#else
|
||||||
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
|
typedef void* id;
|
||||||
|
#endif
|
||||||
|
#elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/extensions/Xrandr.h>
|
||||||
|
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_WGL)
|
||||||
|
/* WGL is declared by windows.h */
|
||||||
|
#endif
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_NSGL)
|
||||||
|
/* NSGL is declared by Cocoa.h */
|
||||||
|
#endif
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||||
|
#include <GL/glx.h>
|
||||||
|
#endif
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_EGL)
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#endif
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
|
||||||
|
#include <GL/osmesa.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Functions
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_WIN32)
|
||||||
|
/*! @brief Returns the adapter device name of the specified monitor.
|
||||||
|
*
|
||||||
|
* @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`)
|
||||||
|
* of the specified monitor, or `NULL` if an [error](@ref error_handling)
|
||||||
|
* occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.1.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor);
|
||||||
|
|
||||||
|
/*! @brief Returns the display device name of the specified monitor.
|
||||||
|
*
|
||||||
|
* @return The UTF-8 encoded display device name (for example
|
||||||
|
* `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.1.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor);
|
||||||
|
|
||||||
|
/*! @brief Returns the `HWND` of the specified window.
|
||||||
|
*
|
||||||
|
* @return The `HWND` of the specified window, or `NULL` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.0.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_WGL)
|
||||||
|
/*! @brief Returns the `HGLRC` of the specified window.
|
||||||
|
*
|
||||||
|
* @return The `HGLRC` of the specified window, or `NULL` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.0.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_COCOA)
|
||||||
|
/*! @brief Returns the `CGDirectDisplayID` of the specified monitor.
|
||||||
|
*
|
||||||
|
* @return The `CGDirectDisplayID` of the specified monitor, or
|
||||||
|
* `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.1.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
|
||||||
|
|
||||||
|
/*! @brief Returns the `NSWindow` of the specified window.
|
||||||
|
*
|
||||||
|
* @return The `NSWindow` of the specified window, or `nil` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.0.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_NSGL)
|
||||||
|
/*! @brief Returns the `NSOpenGLContext` of the specified window.
|
||||||
|
*
|
||||||
|
* @return The `NSOpenGLContext` of the specified window, or `nil` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.0.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI id glfwGetNSGLContext(GLFWwindow* window);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_X11)
|
||||||
|
/*! @brief Returns the `Display` used by GLFW.
|
||||||
|
*
|
||||||
|
* @return The `Display` used by GLFW, or `NULL` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.0.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI Display* glfwGetX11Display(void);
|
||||||
|
|
||||||
|
/*! @brief Returns the `RRCrtc` of the specified monitor.
|
||||||
|
*
|
||||||
|
* @return The `RRCrtc` of the specified monitor, or `None` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.1.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
|
||||||
|
|
||||||
|
/*! @brief Returns the `RROutput` of the specified monitor.
|
||||||
|
*
|
||||||
|
* @return The `RROutput` of the specified monitor, or `None` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.1.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
|
||||||
|
|
||||||
|
/*! @brief Returns the `Window` of the specified window.
|
||||||
|
*
|
||||||
|
* @return The `Window` of the specified window, or `None` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.0.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
|
||||||
|
|
||||||
|
/*! @brief Sets the current primary selection to the specified string.
|
||||||
|
*
|
||||||
|
* @param[in] string A UTF-8 encoded string.
|
||||||
|
*
|
||||||
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
|
* GLFW_PLATFORM_ERROR.
|
||||||
|
*
|
||||||
|
* @pointer_lifetime The specified string is copied before this function
|
||||||
|
* returns.
|
||||||
|
*
|
||||||
|
* @thread_safety This function must only be called from the main thread.
|
||||||
|
*
|
||||||
|
* @sa @ref clipboard
|
||||||
|
* @sa glfwGetX11SelectionString
|
||||||
|
* @sa glfwSetClipboardString
|
||||||
|
*
|
||||||
|
* @since Added in version 3.3.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI void glfwSetX11SelectionString(const char* string);
|
||||||
|
|
||||||
|
/*! @brief Returns the contents of the current primary selection as a string.
|
||||||
|
*
|
||||||
|
* If the selection is empty or if its contents cannot be converted, `NULL`
|
||||||
|
* is returned and a @ref GLFW_FORMAT_UNAVAILABLE error is generated.
|
||||||
|
*
|
||||||
|
* @return The contents of the selection as a UTF-8 encoded string, or `NULL`
|
||||||
|
* if an [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
|
* GLFW_PLATFORM_ERROR.
|
||||||
|
*
|
||||||
|
* @pointer_lifetime The returned string is allocated and freed by GLFW. You
|
||||||
|
* should not free it yourself. It is valid until the next call to @ref
|
||||||
|
* glfwGetX11SelectionString or @ref glfwSetX11SelectionString, or until the
|
||||||
|
* library is terminated.
|
||||||
|
*
|
||||||
|
* @thread_safety This function must only be called from the main thread.
|
||||||
|
*
|
||||||
|
* @sa @ref clipboard
|
||||||
|
* @sa glfwSetX11SelectionString
|
||||||
|
* @sa glfwGetClipboardString
|
||||||
|
*
|
||||||
|
* @since Added in version 3.3.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI const char* glfwGetX11SelectionString(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_GLX)
|
||||||
|
/*! @brief Returns the `GLXContext` of the specified window.
|
||||||
|
*
|
||||||
|
* @return The `GLXContext` of the specified window, or `NULL` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.0.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
|
||||||
|
|
||||||
|
/*! @brief Returns the `GLXWindow` of the specified window.
|
||||||
|
*
|
||||||
|
* @return The `GLXWindow` of the specified window, or `None` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.2.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
|
||||||
|
/*! @brief Returns the `struct wl_display*` used by GLFW.
|
||||||
|
*
|
||||||
|
* @return The `struct wl_display*` used by GLFW, or `NULL` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.2.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI struct wl_display* glfwGetWaylandDisplay(void);
|
||||||
|
|
||||||
|
/*! @brief Returns the `struct wl_output*` of the specified monitor.
|
||||||
|
*
|
||||||
|
* @return The `struct wl_output*` of the specified monitor, or `NULL` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.2.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
|
||||||
|
|
||||||
|
/*! @brief Returns the main `struct wl_surface*` of the specified window.
|
||||||
|
*
|
||||||
|
* @return The main `struct wl_surface*` of the specified window, or `NULL` if
|
||||||
|
* an [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.2.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_EGL)
|
||||||
|
/*! @brief Returns the `EGLDisplay` used by GLFW.
|
||||||
|
*
|
||||||
|
* @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.0.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI EGLDisplay glfwGetEGLDisplay(void);
|
||||||
|
|
||||||
|
/*! @brief Returns the `EGLContext` of the specified window.
|
||||||
|
*
|
||||||
|
* @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.0.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
|
||||||
|
|
||||||
|
/*! @brief Returns the `EGLSurface` of the specified window.
|
||||||
|
*
|
||||||
|
* @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.0.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
|
||||||
|
/*! @brief Retrieves the color buffer associated with the specified window.
|
||||||
|
*
|
||||||
|
* @param[in] window The window whose color buffer to retrieve.
|
||||||
|
* @param[out] width Where to store the width of the color buffer, or `NULL`.
|
||||||
|
* @param[out] height Where to store the height of the color buffer, or `NULL`.
|
||||||
|
* @param[out] format Where to store the OSMesa pixel format of the color
|
||||||
|
* buffer, or `NULL`.
|
||||||
|
* @param[out] buffer Where to store the address of the color buffer, or
|
||||||
|
* `NULL`.
|
||||||
|
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.3.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width, int* height, int* format, void** buffer);
|
||||||
|
|
||||||
|
/*! @brief Retrieves the depth buffer associated with the specified window.
|
||||||
|
*
|
||||||
|
* @param[in] window The window whose depth buffer to retrieve.
|
||||||
|
* @param[out] width Where to store the width of the depth buffer, or `NULL`.
|
||||||
|
* @param[out] height Where to store the height of the depth buffer, or `NULL`.
|
||||||
|
* @param[out] bytesPerValue Where to store the number of bytes per depth
|
||||||
|
* buffer element, or `NULL`.
|
||||||
|
* @param[out] buffer Where to store the address of the depth buffer, or
|
||||||
|
* `NULL`.
|
||||||
|
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.3.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width, int* height, int* bytesPerValue, void** buffer);
|
||||||
|
|
||||||
|
/*! @brief Returns the `OSMesaContext` of the specified window.
|
||||||
|
*
|
||||||
|
* @return The `OSMesaContext` of the specified window, or `NULL` if an
|
||||||
|
* [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
|
* synchronized.
|
||||||
|
*
|
||||||
|
* @since Added in version 3.3.
|
||||||
|
*
|
||||||
|
* @ingroup native
|
||||||
|
*/
|
||||||
|
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* window);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _glfw3_native_h_ */
|
||||||
|
|
|
@ -0,0 +1,190 @@
|
||||||
|
|
||||||
|
set(common_HEADERS internal.h mappings.h
|
||||||
|
"${GLFW_BINARY_DIR}/src/glfw_config.h"
|
||||||
|
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h"
|
||||||
|
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h")
|
||||||
|
set(common_SOURCES context.c init.c input.c monitor.c vulkan.c window.c)
|
||||||
|
|
||||||
|
if (_GLFW_COCOA)
|
||||||
|
set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h cocoa_joystick.h
|
||||||
|
posix_thread.h nsgl_context.h egl_context.h osmesa_context.h)
|
||||||
|
set(glfw_SOURCES ${common_SOURCES} cocoa_init.m cocoa_joystick.m
|
||||||
|
cocoa_monitor.m cocoa_window.m cocoa_time.c posix_thread.c
|
||||||
|
nsgl_context.m egl_context.c osmesa_context.c)
|
||||||
|
elseif (_GLFW_WIN32)
|
||||||
|
set(glfw_HEADERS ${common_HEADERS} win32_platform.h win32_joystick.h
|
||||||
|
wgl_context.h egl_context.h osmesa_context.h)
|
||||||
|
set(glfw_SOURCES ${common_SOURCES} win32_init.c win32_joystick.c
|
||||||
|
win32_monitor.c win32_time.c win32_thread.c win32_window.c
|
||||||
|
wgl_context.c egl_context.c osmesa_context.c)
|
||||||
|
elseif (_GLFW_X11)
|
||||||
|
set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h posix_time.h
|
||||||
|
posix_thread.h glx_context.h egl_context.h osmesa_context.h)
|
||||||
|
set(glfw_SOURCES ${common_SOURCES} x11_init.c x11_monitor.c x11_window.c
|
||||||
|
xkb_unicode.c posix_time.c posix_thread.c glx_context.c
|
||||||
|
egl_context.c osmesa_context.c)
|
||||||
|
elseif (_GLFW_WAYLAND)
|
||||||
|
set(glfw_HEADERS ${common_HEADERS} wl_platform.h
|
||||||
|
posix_time.h posix_thread.h xkb_unicode.h egl_context.h
|
||||||
|
osmesa_context.h)
|
||||||
|
set(glfw_SOURCES ${common_SOURCES} wl_init.c wl_monitor.c wl_window.c
|
||||||
|
posix_time.c posix_thread.c xkb_unicode.c
|
||||||
|
egl_context.c osmesa_context.c)
|
||||||
|
|
||||||
|
ecm_add_wayland_client_protocol(glfw_SOURCES
|
||||||
|
PROTOCOL
|
||||||
|
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/xdg-shell/xdg-shell.xml"
|
||||||
|
BASENAME xdg-shell)
|
||||||
|
ecm_add_wayland_client_protocol(glfw_SOURCES
|
||||||
|
PROTOCOL
|
||||||
|
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
|
||||||
|
BASENAME xdg-decoration)
|
||||||
|
ecm_add_wayland_client_protocol(glfw_SOURCES
|
||||||
|
PROTOCOL
|
||||||
|
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/viewporter/viewporter.xml"
|
||||||
|
BASENAME viewporter)
|
||||||
|
ecm_add_wayland_client_protocol(glfw_SOURCES
|
||||||
|
PROTOCOL
|
||||||
|
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml"
|
||||||
|
BASENAME relative-pointer-unstable-v1)
|
||||||
|
ecm_add_wayland_client_protocol(glfw_SOURCES
|
||||||
|
PROTOCOL
|
||||||
|
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml"
|
||||||
|
BASENAME pointer-constraints-unstable-v1)
|
||||||
|
ecm_add_wayland_client_protocol(glfw_SOURCES
|
||||||
|
PROTOCOL
|
||||||
|
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml"
|
||||||
|
BASENAME idle-inhibit-unstable-v1)
|
||||||
|
elseif (_GLFW_OSMESA)
|
||||||
|
set(glfw_HEADERS ${common_HEADERS} null_platform.h null_joystick.h
|
||||||
|
posix_time.h posix_thread.h osmesa_context.h)
|
||||||
|
set(glfw_SOURCES ${common_SOURCES} null_init.c null_monitor.c null_window.c
|
||||||
|
null_joystick.c posix_time.c posix_thread.c osmesa_context.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (_GLFW_X11 OR _GLFW_WAYLAND)
|
||||||
|
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
set(glfw_HEADERS ${glfw_HEADERS} linux_joystick.h)
|
||||||
|
set(glfw_SOURCES ${glfw_SOURCES} linux_joystick.c)
|
||||||
|
else()
|
||||||
|
set(glfw_HEADERS ${glfw_HEADERS} null_joystick.h)
|
||||||
|
set(glfw_SOURCES ${glfw_SOURCES} null_joystick.c)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Workaround for CMake not knowing about .m files before version 3.16
|
||||||
|
if (CMAKE_VERSION VERSION_LESS "3.16" AND APPLE)
|
||||||
|
set_source_files_properties(cocoa_init.m cocoa_joystick.m cocoa_monitor.m
|
||||||
|
cocoa_window.m nsgl_context.m PROPERTIES
|
||||||
|
LANGUAGE C)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(glfw ${glfw_SOURCES} ${glfw_HEADERS})
|
||||||
|
set_target_properties(glfw PROPERTIES
|
||||||
|
OUTPUT_NAME ${GLFW_LIB_NAME}
|
||||||
|
VERSION ${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}
|
||||||
|
SOVERSION ${GLFW_VERSION_MAJOR}
|
||||||
|
POSITION_INDEPENDENT_CODE ON
|
||||||
|
FOLDER "GLFW3")
|
||||||
|
|
||||||
|
if (CMAKE_VERSION VERSION_EQUAL "3.1.0" OR
|
||||||
|
CMAKE_VERSION VERSION_GREATER "3.1.0")
|
||||||
|
|
||||||
|
set_target_properties(glfw PROPERTIES C_STANDARD 99)
|
||||||
|
else()
|
||||||
|
# Remove this fallback when removing support for CMake version less than 3.1
|
||||||
|
target_compile_options(glfw PRIVATE
|
||||||
|
"$<$<C_COMPILER_ID:AppleClang>:-std=c99>"
|
||||||
|
"$<$<C_COMPILER_ID:Clang>:-std=c99>"
|
||||||
|
"$<$<C_COMPILER_ID:GNU>:-std=c99>")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_compile_definitions(glfw PRIVATE _GLFW_USE_CONFIG_H)
|
||||||
|
target_include_directories(glfw PUBLIC
|
||||||
|
"$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>"
|
||||||
|
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||||
|
target_include_directories(glfw PRIVATE
|
||||||
|
"${GLFW_SOURCE_DIR}/src"
|
||||||
|
"${GLFW_BINARY_DIR}/src"
|
||||||
|
${glfw_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(glfw PRIVATE ${glfw_LIBRARIES})
|
||||||
|
|
||||||
|
# Make GCC warn about declarations that VS 2010 and 2012 won't accept for all
|
||||||
|
# source files that VS will build (Clang ignores this because we set -std=c99)
|
||||||
|
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||||
|
set_source_files_properties(context.c init.c input.c monitor.c vulkan.c
|
||||||
|
window.c win32_init.c win32_joystick.c
|
||||||
|
win32_monitor.c win32_time.c win32_thread.c
|
||||||
|
win32_window.c wgl_context.c egl_context.c
|
||||||
|
osmesa_context.c PROPERTIES
|
||||||
|
COMPILE_FLAGS -Wdeclaration-after-statement)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Enable a reasonable set of warnings
|
||||||
|
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR
|
||||||
|
CMAKE_C_COMPILER_ID STREQUAL "Clang" OR
|
||||||
|
CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
|
||||||
|
|
||||||
|
if (CMAKE_C_SIMULATE_ID STREQUAL "MSVC")
|
||||||
|
# Tell Clang-CL that this is a Clang flag
|
||||||
|
target_compile_options(glfw PRIVATE "/clang:-Wall")
|
||||||
|
else()
|
||||||
|
target_compile_options(glfw PRIVATE "-Wall")
|
||||||
|
endif()
|
||||||
|
elseif (MSVC)
|
||||||
|
target_compile_options(glfw PRIVATE "/W3")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
target_compile_definitions(glfw PRIVATE _UNICODE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# HACK: When building on MinGW, WINVER and UNICODE need to be defined before
|
||||||
|
# the inclusion of stddef.h (by glfw3.h), which is itself included before
|
||||||
|
# win32_platform.h. We define them here until a saner solution can be found
|
||||||
|
# NOTE: MinGW-w64 and Visual C++ do /not/ need this hack.
|
||||||
|
if (MINGW)
|
||||||
|
target_compile_definitions(glfw PRIVATE UNICODE WINVER=0x0501)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (BUILD_SHARED_LIBS)
|
||||||
|
if (WIN32)
|
||||||
|
if (MINGW)
|
||||||
|
# Remove the dependency on the shared version of libgcc
|
||||||
|
# NOTE: MinGW-w64 has the correct default but MinGW needs this
|
||||||
|
target_link_libraries(glfw PRIVATE "-static-libgcc")
|
||||||
|
|
||||||
|
# Remove the lib prefix on the DLL (but not the import library)
|
||||||
|
set_target_properties(glfw PROPERTIES PREFIX "")
|
||||||
|
|
||||||
|
# Add a suffix to the import library to avoid naming conflicts
|
||||||
|
set_target_properties(glfw PROPERTIES IMPORT_SUFFIX "dll.a")
|
||||||
|
else()
|
||||||
|
# Add a suffix to the import library to avoid naming conflicts
|
||||||
|
set_target_properties(glfw PROPERTIES IMPORT_SUFFIX "dll.lib")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_compile_definitions(glfw INTERFACE GLFW_DLL)
|
||||||
|
elseif (APPLE)
|
||||||
|
# Add -fno-common to work around a bug in Apple's GCC
|
||||||
|
target_compile_options(glfw PRIVATE "-fno-common")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (UNIX)
|
||||||
|
# Hide symbols not explicitly tagged for export from the shared library
|
||||||
|
target_compile_options(glfw PRIVATE "-fvisibility=hidden")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
target_compile_definitions(glfw PRIVATE _CRT_SECURE_NO_WARNINGS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (GLFW_INSTALL)
|
||||||
|
install(TARGETS glfw
|
||||||
|
EXPORT glfwTargets
|
||||||
|
RUNTIME DESTINATION "bin"
|
||||||
|
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||||
|
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||||
|
endif()
|
||||||
|
|
|
@ -0,0 +1,623 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 macOS - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
#include <sys/param.h> // For MAXPATHLEN
|
||||||
|
|
||||||
|
// Needed for _NSGetProgname
|
||||||
|
#include <crt_externs.h>
|
||||||
|
|
||||||
|
// Change to our application bundle's resources directory, if present
|
||||||
|
//
|
||||||
|
static void changeToResourcesDirectory(void)
|
||||||
|
{
|
||||||
|
char resourcesPath[MAXPATHLEN];
|
||||||
|
|
||||||
|
CFBundleRef bundle = CFBundleGetMainBundle();
|
||||||
|
if (!bundle)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
|
||||||
|
|
||||||
|
CFStringRef last = CFURLCopyLastPathComponent(resourcesURL);
|
||||||
|
if (CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo)
|
||||||
|
{
|
||||||
|
CFRelease(last);
|
||||||
|
CFRelease(resourcesURL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(last);
|
||||||
|
|
||||||
|
if (!CFURLGetFileSystemRepresentation(resourcesURL,
|
||||||
|
true,
|
||||||
|
(UInt8*) resourcesPath,
|
||||||
|
MAXPATHLEN))
|
||||||
|
{
|
||||||
|
CFRelease(resourcesURL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(resourcesURL);
|
||||||
|
|
||||||
|
chdir(resourcesPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the menu bar (manually)
|
||||||
|
// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
|
||||||
|
// could go away at any moment, lots of stuff that really should be
|
||||||
|
// localize(d|able), etc. Add a nib to save us this horror.
|
||||||
|
//
|
||||||
|
static void createMenuBar(void)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
NSString* appName = nil;
|
||||||
|
NSDictionary* bundleInfo = [[NSBundle mainBundle] infoDictionary];
|
||||||
|
NSString* nameKeys[] =
|
||||||
|
{
|
||||||
|
@"CFBundleDisplayName",
|
||||||
|
@"CFBundleName",
|
||||||
|
@"CFBundleExecutable",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Try to figure out what the calling application is called
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(nameKeys) / sizeof(nameKeys[0]); i++)
|
||||||
|
{
|
||||||
|
id name = bundleInfo[nameKeys[i]];
|
||||||
|
if (name &&
|
||||||
|
[name isKindOfClass:[NSString class]] &&
|
||||||
|
![name isEqualToString:@""])
|
||||||
|
{
|
||||||
|
appName = name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!appName)
|
||||||
|
{
|
||||||
|
char** progname = _NSGetProgname();
|
||||||
|
if (progname && *progname)
|
||||||
|
appName = @(*progname);
|
||||||
|
else
|
||||||
|
appName = @"GLFW Application";
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMenu* bar = [[NSMenu alloc] init];
|
||||||
|
[NSApp setMainMenu:bar];
|
||||||
|
|
||||||
|
NSMenuItem* appMenuItem =
|
||||||
|
[bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
|
||||||
|
NSMenu* appMenu = [[NSMenu alloc] init];
|
||||||
|
[appMenuItem setSubmenu:appMenu];
|
||||||
|
|
||||||
|
[appMenu addItemWithTitle:[NSString stringWithFormat:@"About %@", appName]
|
||||||
|
action:@selector(orderFrontStandardAboutPanel:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
[appMenu addItem:[NSMenuItem separatorItem]];
|
||||||
|
NSMenu* servicesMenu = [[NSMenu alloc] init];
|
||||||
|
[NSApp setServicesMenu:servicesMenu];
|
||||||
|
[[appMenu addItemWithTitle:@"Services"
|
||||||
|
action:NULL
|
||||||
|
keyEquivalent:@""] setSubmenu:servicesMenu];
|
||||||
|
[servicesMenu release];
|
||||||
|
[appMenu addItem:[NSMenuItem separatorItem]];
|
||||||
|
[appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName]
|
||||||
|
action:@selector(hide:)
|
||||||
|
keyEquivalent:@"h"];
|
||||||
|
[[appMenu addItemWithTitle:@"Hide Others"
|
||||||
|
action:@selector(hideOtherApplications:)
|
||||||
|
keyEquivalent:@"h"]
|
||||||
|
setKeyEquivalentModifierMask:NSEventModifierFlagOption | NSEventModifierFlagCommand];
|
||||||
|
[appMenu addItemWithTitle:@"Show All"
|
||||||
|
action:@selector(unhideAllApplications:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
[appMenu addItem:[NSMenuItem separatorItem]];
|
||||||
|
[appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", appName]
|
||||||
|
action:@selector(terminate:)
|
||||||
|
keyEquivalent:@"q"];
|
||||||
|
|
||||||
|
NSMenuItem* windowMenuItem =
|
||||||
|
[bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
|
||||||
|
[bar release];
|
||||||
|
NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
|
||||||
|
[NSApp setWindowsMenu:windowMenu];
|
||||||
|
[windowMenuItem setSubmenu:windowMenu];
|
||||||
|
|
||||||
|
[windowMenu addItemWithTitle:@"Minimize"
|
||||||
|
action:@selector(performMiniaturize:)
|
||||||
|
keyEquivalent:@"m"];
|
||||||
|
[windowMenu addItemWithTitle:@"Zoom"
|
||||||
|
action:@selector(performZoom:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
[windowMenu addItem:[NSMenuItem separatorItem]];
|
||||||
|
[windowMenu addItemWithTitle:@"Bring All to Front"
|
||||||
|
action:@selector(arrangeInFront:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
|
||||||
|
// TODO: Make this appear at the bottom of the menu (for consistency)
|
||||||
|
[windowMenu addItem:[NSMenuItem separatorItem]];
|
||||||
|
[[windowMenu addItemWithTitle:@"Enter Full Screen"
|
||||||
|
action:@selector(toggleFullScreen:)
|
||||||
|
keyEquivalent:@"f"]
|
||||||
|
setKeyEquivalentModifierMask:NSEventModifierFlagControl | NSEventModifierFlagCommand];
|
||||||
|
|
||||||
|
// Prior to Snow Leopard, we need to use this oddly-named semi-private API
|
||||||
|
// to get the application menu working properly.
|
||||||
|
SEL setAppleMenuSelector = NSSelectorFromString(@"setAppleMenu:");
|
||||||
|
[NSApp performSelector:setAppleMenuSelector withObject:appMenu];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create key code translation tables
|
||||||
|
//
|
||||||
|
static void createKeyTables(void)
|
||||||
|
{
|
||||||
|
int scancode;
|
||||||
|
|
||||||
|
memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes));
|
||||||
|
memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes));
|
||||||
|
|
||||||
|
_glfw.ns.keycodes[0x1D] = GLFW_KEY_0;
|
||||||
|
_glfw.ns.keycodes[0x12] = GLFW_KEY_1;
|
||||||
|
_glfw.ns.keycodes[0x13] = GLFW_KEY_2;
|
||||||
|
_glfw.ns.keycodes[0x14] = GLFW_KEY_3;
|
||||||
|
_glfw.ns.keycodes[0x15] = GLFW_KEY_4;
|
||||||
|
_glfw.ns.keycodes[0x17] = GLFW_KEY_5;
|
||||||
|
_glfw.ns.keycodes[0x16] = GLFW_KEY_6;
|
||||||
|
_glfw.ns.keycodes[0x1A] = GLFW_KEY_7;
|
||||||
|
_glfw.ns.keycodes[0x1C] = GLFW_KEY_8;
|
||||||
|
_glfw.ns.keycodes[0x19] = GLFW_KEY_9;
|
||||||
|
_glfw.ns.keycodes[0x00] = GLFW_KEY_A;
|
||||||
|
_glfw.ns.keycodes[0x0B] = GLFW_KEY_B;
|
||||||
|
_glfw.ns.keycodes[0x08] = GLFW_KEY_C;
|
||||||
|
_glfw.ns.keycodes[0x02] = GLFW_KEY_D;
|
||||||
|
_glfw.ns.keycodes[0x0E] = GLFW_KEY_E;
|
||||||
|
_glfw.ns.keycodes[0x03] = GLFW_KEY_F;
|
||||||
|
_glfw.ns.keycodes[0x05] = GLFW_KEY_G;
|
||||||
|
_glfw.ns.keycodes[0x04] = GLFW_KEY_H;
|
||||||
|
_glfw.ns.keycodes[0x22] = GLFW_KEY_I;
|
||||||
|
_glfw.ns.keycodes[0x26] = GLFW_KEY_J;
|
||||||
|
_glfw.ns.keycodes[0x28] = GLFW_KEY_K;
|
||||||
|
_glfw.ns.keycodes[0x25] = GLFW_KEY_L;
|
||||||
|
_glfw.ns.keycodes[0x2E] = GLFW_KEY_M;
|
||||||
|
_glfw.ns.keycodes[0x2D] = GLFW_KEY_N;
|
||||||
|
_glfw.ns.keycodes[0x1F] = GLFW_KEY_O;
|
||||||
|
_glfw.ns.keycodes[0x23] = GLFW_KEY_P;
|
||||||
|
_glfw.ns.keycodes[0x0C] = GLFW_KEY_Q;
|
||||||
|
_glfw.ns.keycodes[0x0F] = GLFW_KEY_R;
|
||||||
|
_glfw.ns.keycodes[0x01] = GLFW_KEY_S;
|
||||||
|
_glfw.ns.keycodes[0x11] = GLFW_KEY_T;
|
||||||
|
_glfw.ns.keycodes[0x20] = GLFW_KEY_U;
|
||||||
|
_glfw.ns.keycodes[0x09] = GLFW_KEY_V;
|
||||||
|
_glfw.ns.keycodes[0x0D] = GLFW_KEY_W;
|
||||||
|
_glfw.ns.keycodes[0x07] = GLFW_KEY_X;
|
||||||
|
_glfw.ns.keycodes[0x10] = GLFW_KEY_Y;
|
||||||
|
_glfw.ns.keycodes[0x06] = GLFW_KEY_Z;
|
||||||
|
|
||||||
|
_glfw.ns.keycodes[0x27] = GLFW_KEY_APOSTROPHE;
|
||||||
|
_glfw.ns.keycodes[0x2A] = GLFW_KEY_BACKSLASH;
|
||||||
|
_glfw.ns.keycodes[0x2B] = GLFW_KEY_COMMA;
|
||||||
|
_glfw.ns.keycodes[0x18] = GLFW_KEY_EQUAL;
|
||||||
|
_glfw.ns.keycodes[0x32] = GLFW_KEY_GRAVE_ACCENT;
|
||||||
|
_glfw.ns.keycodes[0x21] = GLFW_KEY_LEFT_BRACKET;
|
||||||
|
_glfw.ns.keycodes[0x1B] = GLFW_KEY_MINUS;
|
||||||
|
_glfw.ns.keycodes[0x2F] = GLFW_KEY_PERIOD;
|
||||||
|
_glfw.ns.keycodes[0x1E] = GLFW_KEY_RIGHT_BRACKET;
|
||||||
|
_glfw.ns.keycodes[0x29] = GLFW_KEY_SEMICOLON;
|
||||||
|
_glfw.ns.keycodes[0x2C] = GLFW_KEY_SLASH;
|
||||||
|
_glfw.ns.keycodes[0x0A] = GLFW_KEY_WORLD_1;
|
||||||
|
|
||||||
|
_glfw.ns.keycodes[0x33] = GLFW_KEY_BACKSPACE;
|
||||||
|
_glfw.ns.keycodes[0x39] = GLFW_KEY_CAPS_LOCK;
|
||||||
|
_glfw.ns.keycodes[0x75] = GLFW_KEY_DELETE;
|
||||||
|
_glfw.ns.keycodes[0x7D] = GLFW_KEY_DOWN;
|
||||||
|
_glfw.ns.keycodes[0x77] = GLFW_KEY_END;
|
||||||
|
_glfw.ns.keycodes[0x24] = GLFW_KEY_ENTER;
|
||||||
|
_glfw.ns.keycodes[0x35] = GLFW_KEY_ESCAPE;
|
||||||
|
_glfw.ns.keycodes[0x7A] = GLFW_KEY_F1;
|
||||||
|
_glfw.ns.keycodes[0x78] = GLFW_KEY_F2;
|
||||||
|
_glfw.ns.keycodes[0x63] = GLFW_KEY_F3;
|
||||||
|
_glfw.ns.keycodes[0x76] = GLFW_KEY_F4;
|
||||||
|
_glfw.ns.keycodes[0x60] = GLFW_KEY_F5;
|
||||||
|
_glfw.ns.keycodes[0x61] = GLFW_KEY_F6;
|
||||||
|
_glfw.ns.keycodes[0x62] = GLFW_KEY_F7;
|
||||||
|
_glfw.ns.keycodes[0x64] = GLFW_KEY_F8;
|
||||||
|
_glfw.ns.keycodes[0x65] = GLFW_KEY_F9;
|
||||||
|
_glfw.ns.keycodes[0x6D] = GLFW_KEY_F10;
|
||||||
|
_glfw.ns.keycodes[0x67] = GLFW_KEY_F11;
|
||||||
|
_glfw.ns.keycodes[0x6F] = GLFW_KEY_F12;
|
||||||
|
_glfw.ns.keycodes[0x69] = GLFW_KEY_F13;
|
||||||
|
_glfw.ns.keycodes[0x6B] = GLFW_KEY_F14;
|
||||||
|
_glfw.ns.keycodes[0x71] = GLFW_KEY_F15;
|
||||||
|
_glfw.ns.keycodes[0x6A] = GLFW_KEY_F16;
|
||||||
|
_glfw.ns.keycodes[0x40] = GLFW_KEY_F17;
|
||||||
|
_glfw.ns.keycodes[0x4F] = GLFW_KEY_F18;
|
||||||
|
_glfw.ns.keycodes[0x50] = GLFW_KEY_F19;
|
||||||
|
_glfw.ns.keycodes[0x5A] = GLFW_KEY_F20;
|
||||||
|
_glfw.ns.keycodes[0x73] = GLFW_KEY_HOME;
|
||||||
|
_glfw.ns.keycodes[0x72] = GLFW_KEY_INSERT;
|
||||||
|
_glfw.ns.keycodes[0x7B] = GLFW_KEY_LEFT;
|
||||||
|
_glfw.ns.keycodes[0x3A] = GLFW_KEY_LEFT_ALT;
|
||||||
|
_glfw.ns.keycodes[0x3B] = GLFW_KEY_LEFT_CONTROL;
|
||||||
|
_glfw.ns.keycodes[0x38] = GLFW_KEY_LEFT_SHIFT;
|
||||||
|
_glfw.ns.keycodes[0x37] = GLFW_KEY_LEFT_SUPER;
|
||||||
|
_glfw.ns.keycodes[0x6E] = GLFW_KEY_MENU;
|
||||||
|
_glfw.ns.keycodes[0x47] = GLFW_KEY_NUM_LOCK;
|
||||||
|
_glfw.ns.keycodes[0x79] = GLFW_KEY_PAGE_DOWN;
|
||||||
|
_glfw.ns.keycodes[0x74] = GLFW_KEY_PAGE_UP;
|
||||||
|
_glfw.ns.keycodes[0x7C] = GLFW_KEY_RIGHT;
|
||||||
|
_glfw.ns.keycodes[0x3D] = GLFW_KEY_RIGHT_ALT;
|
||||||
|
_glfw.ns.keycodes[0x3E] = GLFW_KEY_RIGHT_CONTROL;
|
||||||
|
_glfw.ns.keycodes[0x3C] = GLFW_KEY_RIGHT_SHIFT;
|
||||||
|
_glfw.ns.keycodes[0x36] = GLFW_KEY_RIGHT_SUPER;
|
||||||
|
_glfw.ns.keycodes[0x31] = GLFW_KEY_SPACE;
|
||||||
|
_glfw.ns.keycodes[0x30] = GLFW_KEY_TAB;
|
||||||
|
_glfw.ns.keycodes[0x7E] = GLFW_KEY_UP;
|
||||||
|
|
||||||
|
_glfw.ns.keycodes[0x52] = GLFW_KEY_KP_0;
|
||||||
|
_glfw.ns.keycodes[0x53] = GLFW_KEY_KP_1;
|
||||||
|
_glfw.ns.keycodes[0x54] = GLFW_KEY_KP_2;
|
||||||
|
_glfw.ns.keycodes[0x55] = GLFW_KEY_KP_3;
|
||||||
|
_glfw.ns.keycodes[0x56] = GLFW_KEY_KP_4;
|
||||||
|
_glfw.ns.keycodes[0x57] = GLFW_KEY_KP_5;
|
||||||
|
_glfw.ns.keycodes[0x58] = GLFW_KEY_KP_6;
|
||||||
|
_glfw.ns.keycodes[0x59] = GLFW_KEY_KP_7;
|
||||||
|
_glfw.ns.keycodes[0x5B] = GLFW_KEY_KP_8;
|
||||||
|
_glfw.ns.keycodes[0x5C] = GLFW_KEY_KP_9;
|
||||||
|
_glfw.ns.keycodes[0x45] = GLFW_KEY_KP_ADD;
|
||||||
|
_glfw.ns.keycodes[0x41] = GLFW_KEY_KP_DECIMAL;
|
||||||
|
_glfw.ns.keycodes[0x4B] = GLFW_KEY_KP_DIVIDE;
|
||||||
|
_glfw.ns.keycodes[0x4C] = GLFW_KEY_KP_ENTER;
|
||||||
|
_glfw.ns.keycodes[0x51] = GLFW_KEY_KP_EQUAL;
|
||||||
|
_glfw.ns.keycodes[0x43] = GLFW_KEY_KP_MULTIPLY;
|
||||||
|
_glfw.ns.keycodes[0x4E] = GLFW_KEY_KP_SUBTRACT;
|
||||||
|
|
||||||
|
for (scancode = 0; scancode < 256; scancode++)
|
||||||
|
{
|
||||||
|
// Store the reverse translation for faster key name lookup
|
||||||
|
if (_glfw.ns.keycodes[scancode] >= 0)
|
||||||
|
_glfw.ns.scancodes[_glfw.ns.keycodes[scancode]] = scancode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve Unicode data for the current keyboard layout
|
||||||
|
//
|
||||||
|
static GLFWbool updateUnicodeDataNS(void)
|
||||||
|
{
|
||||||
|
if (_glfw.ns.inputSource)
|
||||||
|
{
|
||||||
|
CFRelease(_glfw.ns.inputSource);
|
||||||
|
_glfw.ns.inputSource = NULL;
|
||||||
|
_glfw.ns.unicodeData = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.ns.inputSource = TISCopyCurrentKeyboardLayoutInputSource();
|
||||||
|
if (!_glfw.ns.inputSource)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Cocoa: Failed to retrieve keyboard layout input source");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.ns.unicodeData =
|
||||||
|
TISGetInputSourceProperty(_glfw.ns.inputSource,
|
||||||
|
kTISPropertyUnicodeKeyLayoutData);
|
||||||
|
if (!_glfw.ns.unicodeData)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Cocoa: Failed to retrieve keyboard layout Unicode data");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load HIToolbox.framework and the TIS symbols we need from it
|
||||||
|
//
|
||||||
|
static GLFWbool initializeTIS(void)
|
||||||
|
{
|
||||||
|
// This works only because Cocoa has already loaded it properly
|
||||||
|
_glfw.ns.tis.bundle =
|
||||||
|
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
|
||||||
|
if (!_glfw.ns.tis.bundle)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Cocoa: Failed to load HIToolbox.framework");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFStringRef* kPropertyUnicodeKeyLayoutData =
|
||||||
|
CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,
|
||||||
|
CFSTR("kTISPropertyUnicodeKeyLayoutData"));
|
||||||
|
_glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource =
|
||||||
|
CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
|
||||||
|
CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));
|
||||||
|
_glfw.ns.tis.GetInputSourceProperty =
|
||||||
|
CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
|
||||||
|
CFSTR("TISGetInputSourceProperty"));
|
||||||
|
_glfw.ns.tis.GetKbdType =
|
||||||
|
CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
|
||||||
|
CFSTR("LMGetKbdType"));
|
||||||
|
|
||||||
|
if (!kPropertyUnicodeKeyLayoutData ||
|
||||||
|
!TISCopyCurrentKeyboardLayoutInputSource ||
|
||||||
|
!TISGetInputSourceProperty ||
|
||||||
|
!LMGetKbdType)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Cocoa: Failed to load TIS API symbols");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.ns.tis.kPropertyUnicodeKeyLayoutData =
|
||||||
|
*kPropertyUnicodeKeyLayoutData;
|
||||||
|
|
||||||
|
return updateUnicodeDataNS();
|
||||||
|
}
|
||||||
|
|
||||||
|
@interface GLFWHelper : NSObject
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation GLFWHelper
|
||||||
|
|
||||||
|
- (void)selectedKeyboardInputSourceChanged:(NSObject* )object
|
||||||
|
{
|
||||||
|
updateUnicodeDataNS();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)doNothing:(id)object
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@end // GLFWHelper
|
||||||
|
|
||||||
|
@interface GLFWApplicationDelegate : NSObject <NSApplicationDelegate>
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation GLFWApplicationDelegate
|
||||||
|
|
||||||
|
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
||||||
|
{
|
||||||
|
_GLFWwindow* window;
|
||||||
|
|
||||||
|
for (window = _glfw.windowListHead; window; window = window->next)
|
||||||
|
_glfwInputWindowCloseRequest(window);
|
||||||
|
|
||||||
|
return NSTerminateCancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationDidChangeScreenParameters:(NSNotification *) notification
|
||||||
|
{
|
||||||
|
_GLFWwindow* window;
|
||||||
|
|
||||||
|
for (window = _glfw.windowListHead; window; window = window->next)
|
||||||
|
{
|
||||||
|
if (window->context.client != GLFW_NO_API)
|
||||||
|
[window->context.nsgl.object update];
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPollMonitorsNS();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationWillFinishLaunching:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
if (_glfw.hints.init.ns.menubar)
|
||||||
|
{
|
||||||
|
// Menu bar setup must go between sharedApplication and finishLaunching
|
||||||
|
// in order to properly emulate the behavior of NSApplicationMain
|
||||||
|
|
||||||
|
if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
|
||||||
|
{
|
||||||
|
[[NSBundle mainBundle] loadNibNamed:@"MainMenu"
|
||||||
|
owner:NSApp
|
||||||
|
topLevelObjects:&_glfw.ns.nibObjects];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
createMenuBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationDidFinishLaunching:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
_glfw.ns.finishedLaunching = GLFW_TRUE;
|
||||||
|
_glfwPlatformPostEmptyEvent();
|
||||||
|
|
||||||
|
// In case we are unbundled, make us a proper UI application
|
||||||
|
if (_glfw.hints.init.ns.menubar)
|
||||||
|
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||||
|
|
||||||
|
[NSApp stop:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationDidHide:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < _glfw.monitorCount; i++)
|
||||||
|
_glfwRestoreVideoModeNS(_glfw.monitors[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end // GLFWApplicationDelegate
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void* _glfwLoadLocalVulkanLoaderNS(void)
|
||||||
|
{
|
||||||
|
CFBundleRef bundle = CFBundleGetMainBundle();
|
||||||
|
if (!bundle)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
CFURLRef url =
|
||||||
|
CFBundleCopyAuxiliaryExecutableURL(bundle, CFSTR("libvulkan.1.dylib"));
|
||||||
|
if (!url)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char path[PATH_MAX];
|
||||||
|
void* handle = NULL;
|
||||||
|
|
||||||
|
if (CFURLGetFileSystemRepresentation(url, true, (UInt8*) path, sizeof(path) - 1))
|
||||||
|
handle = _glfw_dlopen(path);
|
||||||
|
|
||||||
|
CFRelease(url);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int _glfwPlatformInit(void)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
|
_glfw.ns.helper = [[GLFWHelper alloc] init];
|
||||||
|
|
||||||
|
[NSThread detachNewThreadSelector:@selector(doNothing:)
|
||||||
|
toTarget:_glfw.ns.helper
|
||||||
|
withObject:nil];
|
||||||
|
|
||||||
|
if (NSApp)
|
||||||
|
_glfw.ns.finishedLaunching = GLFW_TRUE;
|
||||||
|
|
||||||
|
[NSApplication sharedApplication];
|
||||||
|
|
||||||
|
_glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
|
||||||
|
if (_glfw.ns.delegate == nil)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Cocoa: Failed to create application delegate");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
[NSApp setDelegate:_glfw.ns.delegate];
|
||||||
|
|
||||||
|
NSEvent* (^block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
|
||||||
|
{
|
||||||
|
if ([event modifierFlags] & NSEventModifierFlagCommand)
|
||||||
|
[[NSApp keyWindow] sendEvent:event];
|
||||||
|
|
||||||
|
return event;
|
||||||
|
};
|
||||||
|
|
||||||
|
_glfw.ns.keyUpMonitor =
|
||||||
|
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyUp
|
||||||
|
handler:block];
|
||||||
|
|
||||||
|
if (_glfw.hints.init.ns.chdir)
|
||||||
|
changeToResourcesDirectory();
|
||||||
|
|
||||||
|
// Press and Hold prevents some keys from emitting repeated characters
|
||||||
|
NSDictionary* defaults = @{@"ApplePressAndHoldEnabled":@NO};
|
||||||
|
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
|
||||||
|
|
||||||
|
[[NSNotificationCenter defaultCenter]
|
||||||
|
addObserver:_glfw.ns.helper
|
||||||
|
selector:@selector(selectedKeyboardInputSourceChanged:)
|
||||||
|
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
||||||
|
object:nil];
|
||||||
|
|
||||||
|
createKeyTables();
|
||||||
|
|
||||||
|
_glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||||
|
if (!_glfw.ns.eventSource)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
CGEventSourceSetLocalEventsSuppressionInterval(_glfw.ns.eventSource, 0.0);
|
||||||
|
|
||||||
|
if (!initializeTIS())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
_glfwInitTimerNS();
|
||||||
|
_glfwInitJoysticksNS();
|
||||||
|
|
||||||
|
_glfwPollMonitorsNS();
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
} // autoreleasepool
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformTerminate(void)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
|
if (_glfw.ns.inputSource)
|
||||||
|
{
|
||||||
|
CFRelease(_glfw.ns.inputSource);
|
||||||
|
_glfw.ns.inputSource = NULL;
|
||||||
|
_glfw.ns.unicodeData = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.ns.eventSource)
|
||||||
|
{
|
||||||
|
CFRelease(_glfw.ns.eventSource);
|
||||||
|
_glfw.ns.eventSource = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.ns.delegate)
|
||||||
|
{
|
||||||
|
[NSApp setDelegate:nil];
|
||||||
|
[_glfw.ns.delegate release];
|
||||||
|
_glfw.ns.delegate = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.ns.helper)
|
||||||
|
{
|
||||||
|
[[NSNotificationCenter defaultCenter]
|
||||||
|
removeObserver:_glfw.ns.helper
|
||||||
|
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
||||||
|
object:nil];
|
||||||
|
[[NSNotificationCenter defaultCenter]
|
||||||
|
removeObserver:_glfw.ns.helper];
|
||||||
|
[_glfw.ns.helper release];
|
||||||
|
_glfw.ns.helper = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.ns.keyUpMonitor)
|
||||||
|
[NSEvent removeMonitor:_glfw.ns.keyUpMonitor];
|
||||||
|
|
||||||
|
free(_glfw.ns.clipboardString);
|
||||||
|
|
||||||
|
_glfwTerminateNSGL();
|
||||||
|
_glfwTerminateJoysticksNS();
|
||||||
|
|
||||||
|
} // autoreleasepool
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
|
{
|
||||||
|
return _GLFW_VERSION_NUMBER " Cocoa NSGL EGL OSMesa"
|
||||||
|
#if defined(_GLFW_BUILD_DLL)
|
||||||
|
" dynamic"
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 Cocoa - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include <IOKit/IOKitLib.h>
|
||||||
|
#include <IOKit/IOCFPlugIn.h>
|
||||||
|
#include <IOKit/hid/IOHIDLib.h>
|
||||||
|
#include <IOKit/hid/IOHIDKeys.h>
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickNS ns
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE struct { int dummyJoystick; }
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_MAPPING_NAME "Mac OS X"
|
||||||
|
|
||||||
|
// Cocoa-specific per-joystick data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWjoystickNS
|
||||||
|
{
|
||||||
|
IOHIDDeviceRef device;
|
||||||
|
CFMutableArrayRef axes;
|
||||||
|
CFMutableArrayRef buttons;
|
||||||
|
CFMutableArrayRef hats;
|
||||||
|
} _GLFWjoystickNS;
|
||||||
|
|
||||||
|
|
||||||
|
void _glfwInitJoysticksNS(void);
|
||||||
|
void _glfwTerminateJoysticksNS(void);
|
||||||
|
|
|
@ -0,0 +1,487 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 Cocoa - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <mach/mach.h>
|
||||||
|
#include <mach/mach_error.h>
|
||||||
|
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Joystick element information
|
||||||
|
//
|
||||||
|
typedef struct _GLFWjoyelementNS
|
||||||
|
{
|
||||||
|
IOHIDElementRef native;
|
||||||
|
uint32_t usage;
|
||||||
|
int index;
|
||||||
|
long minimum;
|
||||||
|
long maximum;
|
||||||
|
|
||||||
|
} _GLFWjoyelementNS;
|
||||||
|
|
||||||
|
|
||||||
|
// Returns the value of the specified element of the specified joystick
|
||||||
|
//
|
||||||
|
static long getElementValue(_GLFWjoystick* js, _GLFWjoyelementNS* element)
|
||||||
|
{
|
||||||
|
IOHIDValueRef valueRef;
|
||||||
|
long value = 0;
|
||||||
|
|
||||||
|
if (js->ns.device)
|
||||||
|
{
|
||||||
|
if (IOHIDDeviceGetValue(js->ns.device,
|
||||||
|
element->native,
|
||||||
|
&valueRef) == kIOReturnSuccess)
|
||||||
|
{
|
||||||
|
value = IOHIDValueGetIntegerValue(valueRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comparison function for matching the SDL element order
|
||||||
|
//
|
||||||
|
static CFComparisonResult compareElements(const void* fp,
|
||||||
|
const void* sp,
|
||||||
|
void* user)
|
||||||
|
{
|
||||||
|
const _GLFWjoyelementNS* fe = fp;
|
||||||
|
const _GLFWjoyelementNS* se = sp;
|
||||||
|
if (fe->usage < se->usage)
|
||||||
|
return kCFCompareLessThan;
|
||||||
|
if (fe->usage > se->usage)
|
||||||
|
return kCFCompareGreaterThan;
|
||||||
|
if (fe->index < se->index)
|
||||||
|
return kCFCompareLessThan;
|
||||||
|
if (fe->index > se->index)
|
||||||
|
return kCFCompareGreaterThan;
|
||||||
|
return kCFCompareEqualTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes the specified joystick
|
||||||
|
//
|
||||||
|
static void closeJoystick(_GLFWjoystick* js)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!js->present)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < CFArrayGetCount(js->ns.axes); i++)
|
||||||
|
free((void*) CFArrayGetValueAtIndex(js->ns.axes, i));
|
||||||
|
CFRelease(js->ns.axes);
|
||||||
|
|
||||||
|
for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
|
||||||
|
free((void*) CFArrayGetValueAtIndex(js->ns.buttons, i));
|
||||||
|
CFRelease(js->ns.buttons);
|
||||||
|
|
||||||
|
for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
|
||||||
|
free((void*) CFArrayGetValueAtIndex(js->ns.hats, i));
|
||||||
|
CFRelease(js->ns.hats);
|
||||||
|
|
||||||
|
_glfwFreeJoystick(js);
|
||||||
|
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback for user-initiated joystick addition
|
||||||
|
//
|
||||||
|
static void matchCallback(void* context,
|
||||||
|
IOReturn result,
|
||||||
|
void* sender,
|
||||||
|
IOHIDDeviceRef device)
|
||||||
|
{
|
||||||
|
int jid;
|
||||||
|
char name[256];
|
||||||
|
char guid[33];
|
||||||
|
CFIndex i;
|
||||||
|
CFTypeRef property;
|
||||||
|
uint32_t vendor = 0, product = 0, version = 0;
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
CFMutableArrayRef axes, buttons, hats;
|
||||||
|
|
||||||
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
{
|
||||||
|
if (_glfw.joysticks[jid].ns.device == device)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
axes = CFArrayCreateMutable(NULL, 0, NULL);
|
||||||
|
buttons = CFArrayCreateMutable(NULL, 0, NULL);
|
||||||
|
hats = CFArrayCreateMutable(NULL, 0, NULL);
|
||||||
|
|
||||||
|
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
|
||||||
|
if (property)
|
||||||
|
{
|
||||||
|
CFStringGetCString(property,
|
||||||
|
name,
|
||||||
|
sizeof(name),
|
||||||
|
kCFStringEncodingUTF8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
strncpy(name, "Unknown", sizeof(name));
|
||||||
|
|
||||||
|
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey));
|
||||||
|
if (property)
|
||||||
|
CFNumberGetValue(property, kCFNumberSInt32Type, &vendor);
|
||||||
|
|
||||||
|
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey));
|
||||||
|
if (property)
|
||||||
|
CFNumberGetValue(property, kCFNumberSInt32Type, &product);
|
||||||
|
|
||||||
|
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVersionNumberKey));
|
||||||
|
if (property)
|
||||||
|
CFNumberGetValue(property, kCFNumberSInt32Type, &version);
|
||||||
|
|
||||||
|
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
||||||
|
if (vendor && product)
|
||||||
|
{
|
||||||
|
sprintf(guid, "03000000%02x%02x0000%02x%02x0000%02x%02x0000",
|
||||||
|
(uint8_t) vendor, (uint8_t) (vendor >> 8),
|
||||||
|
(uint8_t) product, (uint8_t) (product >> 8),
|
||||||
|
(uint8_t) version, (uint8_t) (version >> 8));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
|
||||||
|
name[0], name[1], name[2], name[3],
|
||||||
|
name[4], name[5], name[6], name[7],
|
||||||
|
name[8], name[9], name[10]);
|
||||||
|
}
|
||||||
|
|
||||||
|
CFArrayRef elements =
|
||||||
|
IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
|
||||||
|
|
||||||
|
for (i = 0; i < CFArrayGetCount(elements); i++)
|
||||||
|
{
|
||||||
|
IOHIDElementRef native = (IOHIDElementRef)
|
||||||
|
CFArrayGetValueAtIndex(elements, i);
|
||||||
|
if (CFGetTypeID(native) != IOHIDElementGetTypeID())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const IOHIDElementType type = IOHIDElementGetType(native);
|
||||||
|
if ((type != kIOHIDElementTypeInput_Axis) &&
|
||||||
|
(type != kIOHIDElementTypeInput_Button) &&
|
||||||
|
(type != kIOHIDElementTypeInput_Misc))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFMutableArrayRef target = NULL;
|
||||||
|
|
||||||
|
const uint32_t usage = IOHIDElementGetUsage(native);
|
||||||
|
const uint32_t page = IOHIDElementGetUsagePage(native);
|
||||||
|
if (page == kHIDPage_GenericDesktop)
|
||||||
|
{
|
||||||
|
switch (usage)
|
||||||
|
{
|
||||||
|
case kHIDUsage_GD_X:
|
||||||
|
case kHIDUsage_GD_Y:
|
||||||
|
case kHIDUsage_GD_Z:
|
||||||
|
case kHIDUsage_GD_Rx:
|
||||||
|
case kHIDUsage_GD_Ry:
|
||||||
|
case kHIDUsage_GD_Rz:
|
||||||
|
case kHIDUsage_GD_Slider:
|
||||||
|
case kHIDUsage_GD_Dial:
|
||||||
|
case kHIDUsage_GD_Wheel:
|
||||||
|
target = axes;
|
||||||
|
break;
|
||||||
|
case kHIDUsage_GD_Hatswitch:
|
||||||
|
target = hats;
|
||||||
|
break;
|
||||||
|
case kHIDUsage_GD_DPadUp:
|
||||||
|
case kHIDUsage_GD_DPadRight:
|
||||||
|
case kHIDUsage_GD_DPadDown:
|
||||||
|
case kHIDUsage_GD_DPadLeft:
|
||||||
|
case kHIDUsage_GD_SystemMainMenu:
|
||||||
|
case kHIDUsage_GD_Select:
|
||||||
|
case kHIDUsage_GD_Start:
|
||||||
|
target = buttons;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (page == kHIDPage_Simulation)
|
||||||
|
{
|
||||||
|
switch (usage)
|
||||||
|
{
|
||||||
|
case kHIDUsage_Sim_Accelerator:
|
||||||
|
case kHIDUsage_Sim_Brake:
|
||||||
|
case kHIDUsage_Sim_Throttle:
|
||||||
|
case kHIDUsage_Sim_Rudder:
|
||||||
|
case kHIDUsage_Sim_Steering:
|
||||||
|
target = axes;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (page == kHIDPage_Button || page == kHIDPage_Consumer)
|
||||||
|
target = buttons;
|
||||||
|
|
||||||
|
if (target)
|
||||||
|
{
|
||||||
|
_GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));
|
||||||
|
element->native = native;
|
||||||
|
element->usage = usage;
|
||||||
|
element->index = (int) CFArrayGetCount(target);
|
||||||
|
element->minimum = IOHIDElementGetLogicalMin(native);
|
||||||
|
element->maximum = IOHIDElementGetLogicalMax(native);
|
||||||
|
CFArrayAppendValue(target, element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(elements);
|
||||||
|
|
||||||
|
CFArraySortValues(axes, CFRangeMake(0, CFArrayGetCount(axes)),
|
||||||
|
compareElements, NULL);
|
||||||
|
CFArraySortValues(buttons, CFRangeMake(0, CFArrayGetCount(buttons)),
|
||||||
|
compareElements, NULL);
|
||||||
|
CFArraySortValues(hats, CFRangeMake(0, CFArrayGetCount(hats)),
|
||||||
|
compareElements, NULL);
|
||||||
|
|
||||||
|
js = _glfwAllocJoystick(name, guid,
|
||||||
|
(int) CFArrayGetCount(axes),
|
||||||
|
(int) CFArrayGetCount(buttons),
|
||||||
|
(int) CFArrayGetCount(hats));
|
||||||
|
|
||||||
|
js->ns.device = device;
|
||||||
|
js->ns.axes = axes;
|
||||||
|
js->ns.buttons = buttons;
|
||||||
|
js->ns.hats = hats;
|
||||||
|
|
||||||
|
_glfwInputJoystick(js, GLFW_CONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback for user-initiated joystick removal
|
||||||
|
//
|
||||||
|
static void removeCallback(void* context,
|
||||||
|
IOReturn result,
|
||||||
|
void* sender,
|
||||||
|
IOHIDDeviceRef device)
|
||||||
|
{
|
||||||
|
int jid;
|
||||||
|
|
||||||
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
{
|
||||||
|
if (_glfw.joysticks[jid].ns.device == device)
|
||||||
|
{
|
||||||
|
closeJoystick(_glfw.joysticks + jid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Initialize joystick interface
|
||||||
|
//
|
||||||
|
void _glfwInitJoysticksNS(void)
|
||||||
|
{
|
||||||
|
CFMutableArrayRef matching;
|
||||||
|
const long usages[] =
|
||||||
|
{
|
||||||
|
kHIDUsage_GD_Joystick,
|
||||||
|
kHIDUsage_GD_GamePad,
|
||||||
|
kHIDUsage_GD_MultiAxisController
|
||||||
|
};
|
||||||
|
|
||||||
|
_glfw.ns.hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
|
||||||
|
kIOHIDOptionsTypeNone);
|
||||||
|
|
||||||
|
matching = CFArrayCreateMutable(kCFAllocatorDefault,
|
||||||
|
0,
|
||||||
|
&kCFTypeArrayCallBacks);
|
||||||
|
if (!matching)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create array");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(usages) / sizeof(long); i++)
|
||||||
|
{
|
||||||
|
const long page = kHIDPage_GenericDesktop;
|
||||||
|
|
||||||
|
CFMutableDictionaryRef dict =
|
||||||
|
CFDictionaryCreateMutable(kCFAllocatorDefault,
|
||||||
|
0,
|
||||||
|
&kCFTypeDictionaryKeyCallBacks,
|
||||||
|
&kCFTypeDictionaryValueCallBacks);
|
||||||
|
if (!dict)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CFNumberRef pageRef = CFNumberCreate(kCFAllocatorDefault,
|
||||||
|
kCFNumberLongType,
|
||||||
|
&page);
|
||||||
|
CFNumberRef usageRef = CFNumberCreate(kCFAllocatorDefault,
|
||||||
|
kCFNumberLongType,
|
||||||
|
&usages[i]);
|
||||||
|
if (pageRef && usageRef)
|
||||||
|
{
|
||||||
|
CFDictionarySetValue(dict,
|
||||||
|
CFSTR(kIOHIDDeviceUsagePageKey),
|
||||||
|
pageRef);
|
||||||
|
CFDictionarySetValue(dict,
|
||||||
|
CFSTR(kIOHIDDeviceUsageKey),
|
||||||
|
usageRef);
|
||||||
|
CFArrayAppendValue(matching, dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pageRef)
|
||||||
|
CFRelease(pageRef);
|
||||||
|
if (usageRef)
|
||||||
|
CFRelease(usageRef);
|
||||||
|
|
||||||
|
CFRelease(dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns.hidManager, matching);
|
||||||
|
CFRelease(matching);
|
||||||
|
|
||||||
|
IOHIDManagerRegisterDeviceMatchingCallback(_glfw.ns.hidManager,
|
||||||
|
&matchCallback, NULL);
|
||||||
|
IOHIDManagerRegisterDeviceRemovalCallback(_glfw.ns.hidManager,
|
||||||
|
&removeCallback, NULL);
|
||||||
|
IOHIDManagerScheduleWithRunLoop(_glfw.ns.hidManager,
|
||||||
|
CFRunLoopGetMain(),
|
||||||
|
kCFRunLoopDefaultMode);
|
||||||
|
IOHIDManagerOpen(_glfw.ns.hidManager, kIOHIDOptionsTypeNone);
|
||||||
|
|
||||||
|
// Execute the run loop once in order to register any initially-attached
|
||||||
|
// joysticks
|
||||||
|
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close all opened joystick handles
|
||||||
|
//
|
||||||
|
void _glfwTerminateJoysticksNS(void)
|
||||||
|
{
|
||||||
|
int jid;
|
||||||
|
|
||||||
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
closeJoystick(_glfw.joysticks + jid);
|
||||||
|
|
||||||
|
CFRelease(_glfw.ns.hidManager);
|
||||||
|
_glfw.ns.hidManager = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||||
|
{
|
||||||
|
if (mode & _GLFW_POLL_AXES)
|
||||||
|
{
|
||||||
|
CFIndex i;
|
||||||
|
|
||||||
|
for (i = 0; i < CFArrayGetCount(js->ns.axes); i++)
|
||||||
|
{
|
||||||
|
_GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
|
||||||
|
CFArrayGetValueAtIndex(js->ns.axes, i);
|
||||||
|
|
||||||
|
const long raw = getElementValue(js, axis);
|
||||||
|
// Perform auto calibration
|
||||||
|
if (raw < axis->minimum)
|
||||||
|
axis->minimum = raw;
|
||||||
|
if (raw > axis->maximum)
|
||||||
|
axis->maximum = raw;
|
||||||
|
|
||||||
|
const long size = axis->maximum - axis->minimum;
|
||||||
|
if (size == 0)
|
||||||
|
_glfwInputJoystickAxis(js, (int) i, 0.f);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const float value = (2.f * (raw - axis->minimum) / size) - 1.f;
|
||||||
|
_glfwInputJoystickAxis(js, (int) i, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode & _GLFW_POLL_BUTTONS)
|
||||||
|
{
|
||||||
|
CFIndex i;
|
||||||
|
|
||||||
|
for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
|
||||||
|
{
|
||||||
|
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
||||||
|
CFArrayGetValueAtIndex(js->ns.buttons, i);
|
||||||
|
const char value = getElementValue(js, button) - button->minimum;
|
||||||
|
const int state = (value > 0) ? GLFW_PRESS : GLFW_RELEASE;
|
||||||
|
_glfwInputJoystickButton(js, (int) i, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
|
||||||
|
{
|
||||||
|
const int states[9] =
|
||||||
|
{
|
||||||
|
GLFW_HAT_UP,
|
||||||
|
GLFW_HAT_RIGHT_UP,
|
||||||
|
GLFW_HAT_RIGHT,
|
||||||
|
GLFW_HAT_RIGHT_DOWN,
|
||||||
|
GLFW_HAT_DOWN,
|
||||||
|
GLFW_HAT_LEFT_DOWN,
|
||||||
|
GLFW_HAT_LEFT,
|
||||||
|
GLFW_HAT_LEFT_UP,
|
||||||
|
GLFW_HAT_CENTERED
|
||||||
|
};
|
||||||
|
|
||||||
|
_GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
|
||||||
|
CFArrayGetValueAtIndex(js->ns.hats, i);
|
||||||
|
long state = getElementValue(js, hat) - hat->minimum;
|
||||||
|
if (state < 0 || state > 8)
|
||||||
|
state = 8;
|
||||||
|
|
||||||
|
_glfwInputJoystickHat(js, (int) i, states[state]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return js->present;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||||
|
{
|
||||||
|
if ((strncmp(guid + 4, "000000000000", 12) == 0) &&
|
||||||
|
(strncmp(guid + 20, "000000000000", 12) == 0))
|
||||||
|
{
|
||||||
|
char original[33];
|
||||||
|
strncpy(original, guid, sizeof(original) - 1);
|
||||||
|
sprintf(guid, "03000000%.4s0000%.4s000000000000",
|
||||||
|
original, original + 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,631 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 macOS - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <IOKit/graphics/IOGraphicsLib.h>
|
||||||
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Get the name of the specified display, or NULL
|
||||||
|
//
|
||||||
|
static char* getMonitorName(CGDirectDisplayID displayID, NSScreen* screen)
|
||||||
|
{
|
||||||
|
// IOKit doesn't work on Apple Silicon anymore
|
||||||
|
// Luckily, 10.15 introduced -[NSScreen localizedName].
|
||||||
|
// Use it if available, and fall back to IOKit otherwise.
|
||||||
|
if (screen)
|
||||||
|
{
|
||||||
|
if ([screen respondsToSelector:@selector(localizedName)])
|
||||||
|
{
|
||||||
|
NSString* name = [screen valueForKey:@"localizedName"];
|
||||||
|
if (name)
|
||||||
|
return _glfw_strdup([name UTF8String]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
io_iterator_t it;
|
||||||
|
io_service_t service;
|
||||||
|
CFDictionaryRef info;
|
||||||
|
|
||||||
|
if (IOServiceGetMatchingServices(kIOMasterPortDefault,
|
||||||
|
IOServiceMatching("IODisplayConnect"),
|
||||||
|
&it) != 0)
|
||||||
|
{
|
||||||
|
// This may happen if a desktop Mac is running headless
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((service = IOIteratorNext(it)) != 0)
|
||||||
|
{
|
||||||
|
info = IODisplayCreateInfoDictionary(service,
|
||||||
|
kIODisplayOnlyPreferredName);
|
||||||
|
|
||||||
|
CFNumberRef vendorIDRef =
|
||||||
|
CFDictionaryGetValue(info, CFSTR(kDisplayVendorID));
|
||||||
|
CFNumberRef productIDRef =
|
||||||
|
CFDictionaryGetValue(info, CFSTR(kDisplayProductID));
|
||||||
|
if (!vendorIDRef || !productIDRef)
|
||||||
|
{
|
||||||
|
CFRelease(info);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int vendorID, productID;
|
||||||
|
CFNumberGetValue(vendorIDRef, kCFNumberIntType, &vendorID);
|
||||||
|
CFNumberGetValue(productIDRef, kCFNumberIntType, &productID);
|
||||||
|
|
||||||
|
if (CGDisplayVendorNumber(displayID) == vendorID &&
|
||||||
|
CGDisplayModelNumber(displayID) == productID)
|
||||||
|
{
|
||||||
|
// Info dictionary is used and freed below
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
IOObjectRelease(it);
|
||||||
|
|
||||||
|
if (!service)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Cocoa: Failed to find service port for display");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFDictionaryRef names =
|
||||||
|
CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
|
||||||
|
|
||||||
|
CFStringRef nameRef;
|
||||||
|
|
||||||
|
if (!names || !CFDictionaryGetValueIfPresent(names, CFSTR("en_US"),
|
||||||
|
(const void**) &nameRef))
|
||||||
|
{
|
||||||
|
// This may happen if a desktop Mac is running headless
|
||||||
|
CFRelease(info);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CFIndex size =
|
||||||
|
CFStringGetMaximumSizeForEncoding(CFStringGetLength(nameRef),
|
||||||
|
kCFStringEncodingUTF8);
|
||||||
|
char* name = calloc(size + 1, 1);
|
||||||
|
CFStringGetCString(nameRef, name, size, kCFStringEncodingUTF8);
|
||||||
|
|
||||||
|
CFRelease(info);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether the display mode should be included in enumeration
|
||||||
|
//
|
||||||
|
static GLFWbool modeIsGood(CGDisplayModeRef mode)
|
||||||
|
{
|
||||||
|
uint32_t flags = CGDisplayModeGetIOFlags(mode);
|
||||||
|
|
||||||
|
if (!(flags & kDisplayModeValidFlag) || !(flags & kDisplayModeSafeFlag))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
if (flags & kDisplayModeInterlacedFlag)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
if (flags & kDisplayModeStretchedFlag)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
||||||
|
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
|
||||||
|
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) &&
|
||||||
|
CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
|
||||||
|
{
|
||||||
|
CFRelease(format);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(format);
|
||||||
|
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert Core Graphics display mode to GLFW video mode
|
||||||
|
//
|
||||||
|
static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
|
||||||
|
double fallbackRefreshRate)
|
||||||
|
{
|
||||||
|
GLFWvidmode result;
|
||||||
|
result.width = (int) CGDisplayModeGetWidth(mode);
|
||||||
|
result.height = (int) CGDisplayModeGetHeight(mode);
|
||||||
|
result.refreshRate = (int) round(CGDisplayModeGetRefreshRate(mode));
|
||||||
|
|
||||||
|
if (result.refreshRate == 0)
|
||||||
|
result.refreshRate = (int) round(fallbackRefreshRate);
|
||||||
|
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
||||||
|
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
|
||||||
|
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
|
||||||
|
{
|
||||||
|
result.redBits = 5;
|
||||||
|
result.greenBits = 5;
|
||||||
|
result.blueBits = 5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
|
||||||
|
{
|
||||||
|
result.redBits = 8;
|
||||||
|
result.greenBits = 8;
|
||||||
|
result.blueBits = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
||||||
|
CFRelease(format);
|
||||||
|
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Starts reservation for display fading
|
||||||
|
//
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ends reservation for display fading
|
||||||
|
//
|
||||||
|
static void endFadeReservation(CGDisplayFadeReservationToken token)
|
||||||
|
{
|
||||||
|
if (token != kCGDisplayFadeReservationInvalidToken)
|
||||||
|
{
|
||||||
|
CGDisplayFade(token, 0.5,
|
||||||
|
kCGDisplayBlendSolidColor,
|
||||||
|
kCGDisplayBlendNormal,
|
||||||
|
0.0, 0.0, 0.0,
|
||||||
|
FALSE);
|
||||||
|
CGReleaseDisplayFadeReservation(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the display refresh rate queried from the I/O registry
|
||||||
|
//
|
||||||
|
static double getFallbackRefreshRate(CGDirectDisplayID displayID)
|
||||||
|
{
|
||||||
|
double refreshRate = 60.0;
|
||||||
|
|
||||||
|
io_iterator_t it;
|
||||||
|
io_service_t service;
|
||||||
|
|
||||||
|
if (IOServiceGetMatchingServices(kIOMasterPortDefault,
|
||||||
|
IOServiceMatching("IOFramebuffer"),
|
||||||
|
&it) != 0)
|
||||||
|
{
|
||||||
|
return refreshRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((service = IOIteratorNext(it)) != 0)
|
||||||
|
{
|
||||||
|
const CFNumberRef indexRef =
|
||||||
|
IORegistryEntryCreateCFProperty(service,
|
||||||
|
CFSTR("IOFramebufferOpenGLIndex"),
|
||||||
|
kCFAllocatorDefault,
|
||||||
|
kNilOptions);
|
||||||
|
if (!indexRef)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint32_t index = 0;
|
||||||
|
CFNumberGetValue(indexRef, kCFNumberIntType, &index);
|
||||||
|
CFRelease(indexRef);
|
||||||
|
|
||||||
|
if (CGOpenGLDisplayMaskToDisplayID(1 << index) != displayID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const CFNumberRef clockRef =
|
||||||
|
IORegistryEntryCreateCFProperty(service,
|
||||||
|
CFSTR("IOFBCurrentPixelClock"),
|
||||||
|
kCFAllocatorDefault,
|
||||||
|
kNilOptions);
|
||||||
|
const CFNumberRef countRef =
|
||||||
|
IORegistryEntryCreateCFProperty(service,
|
||||||
|
CFSTR("IOFBCurrentPixelCount"),
|
||||||
|
kCFAllocatorDefault,
|
||||||
|
kNilOptions);
|
||||||
|
|
||||||
|
uint32_t clock = 0, count = 0;
|
||||||
|
|
||||||
|
if (clockRef)
|
||||||
|
{
|
||||||
|
CFNumberGetValue(clockRef, kCFNumberIntType, &clock);
|
||||||
|
CFRelease(clockRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (countRef)
|
||||||
|
{
|
||||||
|
CFNumberGetValue(countRef, kCFNumberIntType, &count);
|
||||||
|
CFRelease(countRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clock > 0 && count > 0)
|
||||||
|
refreshRate = clock / (double) count;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOObjectRelease(it);
|
||||||
|
return refreshRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Poll for changes in the set of connected monitors
|
||||||
|
//
|
||||||
|
void _glfwPollMonitorsNS(void)
|
||||||
|
{
|
||||||
|
uint32_t displayCount;
|
||||||
|
CGGetOnlineDisplayList(0, NULL, &displayCount);
|
||||||
|
CGDirectDisplayID* displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
||||||
|
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
||||||
|
|
||||||
|
for (int i = 0; i < _glfw.monitorCount; i++)
|
||||||
|
_glfw.monitors[i]->ns.screen = nil;
|
||||||
|
|
||||||
|
_GLFWmonitor** disconnected = NULL;
|
||||||
|
uint32_t disconnectedCount = _glfw.monitorCount;
|
||||||
|
if (disconnectedCount)
|
||||||
|
{
|
||||||
|
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
|
||||||
|
memcpy(disconnected,
|
||||||
|
_glfw.monitors,
|
||||||
|
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < displayCount; i++)
|
||||||
|
{
|
||||||
|
if (CGDisplayIsAsleep(displays[i]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);
|
||||||
|
NSScreen* screen = nil;
|
||||||
|
|
||||||
|
for (screen in [NSScreen screens])
|
||||||
|
{
|
||||||
|
NSNumber* screenNumber = [screen deviceDescription][@"NSScreenNumber"];
|
||||||
|
|
||||||
|
// HACK: Compare unit numbers instead of display IDs to work around
|
||||||
|
// display replacement on machines with automatic graphics
|
||||||
|
// switching
|
||||||
|
if (CGDisplayUnitNumber([screenNumber unsignedIntValue]) == unitNumber)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK: Compare unit numbers instead of display IDs to work around
|
||||||
|
// display replacement on machines with automatic graphics
|
||||||
|
// switching
|
||||||
|
uint32_t j;
|
||||||
|
for (j = 0; j < disconnectedCount; j++)
|
||||||
|
{
|
||||||
|
if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber)
|
||||||
|
{
|
||||||
|
disconnected[j]->ns.screen = screen;
|
||||||
|
disconnected[j] = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j < disconnectedCount)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const CGSize size = CGDisplayScreenSize(displays[i]);
|
||||||
|
char* name = getMonitorName(displays[i], screen);
|
||||||
|
if (!name)
|
||||||
|
name = _glfw_strdup("Unknown");
|
||||||
|
|
||||||
|
_GLFWmonitor* monitor = _glfwAllocMonitor(name, size.width, size.height);
|
||||||
|
monitor->ns.displayID = displays[i];
|
||||||
|
monitor->ns.unitNumber = unitNumber;
|
||||||
|
monitor->ns.screen = screen;
|
||||||
|
|
||||||
|
free(name);
|
||||||
|
|
||||||
|
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displays[i]);
|
||||||
|
if (CGDisplayModeGetRefreshRate(mode) == 0.0)
|
||||||
|
monitor->ns.fallbackRefreshRate = getFallbackRefreshRate(displays[i]);
|
||||||
|
CGDisplayModeRelease(mode);
|
||||||
|
|
||||||
|
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < disconnectedCount; i++)
|
||||||
|
{
|
||||||
|
if (disconnected[i])
|
||||||
|
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(disconnected);
|
||||||
|
free(displays);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the current video mode
|
||||||
|
//
|
||||||
|
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||||
|
{
|
||||||
|
GLFWvidmode current;
|
||||||
|
_glfwPlatformGetVideoMode(monitor, ¤t);
|
||||||
|
|
||||||
|
const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired);
|
||||||
|
if (_glfwCompareVideoModes(¤t, best) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
|
||||||
|
const CFIndex count = CFArrayGetCount(modes);
|
||||||
|
CGDisplayModeRef native = NULL;
|
||||||
|
|
||||||
|
for (CFIndex i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
|
||||||
|
if (!modeIsGood(dm))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const GLFWvidmode mode =
|
||||||
|
vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate);
|
||||||
|
if (_glfwCompareVideoModes(best, &mode) == 0)
|
||||||
|
{
|
||||||
|
native = dm;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (native)
|
||||||
|
{
|
||||||
|
if (monitor->ns.previousMode == NULL)
|
||||||
|
monitor->ns.previousMode = CGDisplayCopyDisplayMode(monitor->ns.displayID);
|
||||||
|
|
||||||
|
CGDisplayFadeReservationToken token = beginFadeReservation();
|
||||||
|
CGDisplaySetDisplayMode(monitor->ns.displayID, native, NULL);
|
||||||
|
endFadeReservation(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(modes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore the previously saved (original) video mode
|
||||||
|
//
|
||||||
|
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor)
|
||||||
|
{
|
||||||
|
if (monitor->ns.previousMode)
|
||||||
|
{
|
||||||
|
CGDisplayFadeReservationToken token = beginFadeReservation();
|
||||||
|
CGDisplaySetDisplayMode(monitor->ns.displayID,
|
||||||
|
monitor->ns.previousMode, NULL);
|
||||||
|
endFadeReservation(token);
|
||||||
|
|
||||||
|
CGDisplayModeRelease(monitor->ns.previousMode);
|
||||||
|
monitor->ns.previousMode = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
|
const CGRect bounds = CGDisplayBounds(monitor->ns.displayID);
|
||||||
|
|
||||||
|
if (xpos)
|
||||||
|
*xpos = (int) bounds.origin.x;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = (int) bounds.origin.y;
|
||||||
|
|
||||||
|
} // autoreleasepool
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||||
|
float* xscale, float* yscale)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
|
if (!monitor->ns.screen)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Cocoa: Cannot query content scale without screen");
|
||||||
|
}
|
||||||
|
|
||||||
|
const NSRect points = [monitor->ns.screen frame];
|
||||||
|
const NSRect pixels = [monitor->ns.screen convertRectToBacking:points];
|
||||||
|
|
||||||
|
if (xscale)
|
||||||
|
*xscale = (float) (pixels.size.width / points.size.width);
|
||||||
|
if (yscale)
|
||||||
|
*yscale = (float) (pixels.size.height / points.size.height);
|
||||||
|
|
||||||
|
} // autoreleasepool
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
|
||||||
|
int* xpos, int* ypos,
|
||||||
|
int* width, int* height)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
|
if (!monitor->ns.screen)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Cocoa: Cannot query workarea without screen");
|
||||||
|
}
|
||||||
|
|
||||||
|
const NSRect frameRect = [monitor->ns.screen visibleFrame];
|
||||||
|
|
||||||
|
if (xpos)
|
||||||
|
*xpos = frameRect.origin.x;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = _glfwTransformYNS(frameRect.origin.y + frameRect.size.height - 1);
|
||||||
|
if (width)
|
||||||
|
*width = frameRect.size.width;
|
||||||
|
if (height)
|
||||||
|
*height = frameRect.size.height;
|
||||||
|
|
||||||
|
} // autoreleasepool
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
|
||||||
|
const CFIndex found = CFArrayGetCount(modes);
|
||||||
|
GLFWvidmode* result = calloc(found, sizeof(GLFWvidmode));
|
||||||
|
|
||||||
|
for (CFIndex i = 0; i < found; i++)
|
||||||
|
{
|
||||||
|
CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
|
||||||
|
if (!modeIsGood(dm))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const GLFWvidmode mode =
|
||||||
|
vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate);
|
||||||
|
CFIndex j;
|
||||||
|
|
||||||
|
for (j = 0; j < *count; j++)
|
||||||
|
{
|
||||||
|
if (_glfwCompareVideoModes(result + j, &mode) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip duplicate modes
|
||||||
|
if (j < *count)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
(*count)++;
|
||||||
|
result[*count - 1] = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(modes);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
} // autoreleasepool
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
|
CGDisplayModeRef native = CGDisplayCopyDisplayMode(monitor->ns.displayID);
|
||||||
|
*mode = vidmodeFromCGDisplayMode(native, monitor->ns.fallbackRefreshRate);
|
||||||
|
CGDisplayModeRelease(native);
|
||||||
|
|
||||||
|
} // autoreleasepool
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
|
uint32_t size = CGDisplayGammaTableCapacity(monitor->ns.displayID);
|
||||||
|
CGGammaValue* values = calloc(size * 3, sizeof(CGGammaValue));
|
||||||
|
|
||||||
|
CGGetDisplayTransferByTable(monitor->ns.displayID,
|
||||||
|
size,
|
||||||
|
values,
|
||||||
|
values + size,
|
||||||
|
values + size * 2,
|
||||||
|
&size);
|
||||||
|
|
||||||
|
_glfwAllocGammaArrays(ramp, size);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
ramp->red[i] = (unsigned short) (values[i] * 65535);
|
||||||
|
ramp->green[i] = (unsigned short) (values[i + size] * 65535);
|
||||||
|
ramp->blue[i] = (unsigned short) (values[i + size * 2] * 65535);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(values);
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
} // autoreleasepool
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
|
CGGammaValue* values = calloc(ramp->size * 3, sizeof(CGGammaValue));
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < ramp->size; i++)
|
||||||
|
{
|
||||||
|
values[i] = ramp->red[i] / 65535.f;
|
||||||
|
values[i + ramp->size] = ramp->green[i] / 65535.f;
|
||||||
|
values[i + ramp->size * 2] = ramp->blue[i] / 65535.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGSetDisplayTransferByTable(monitor->ns.displayID,
|
||||||
|
ramp->size,
|
||||||
|
values,
|
||||||
|
values + ramp->size,
|
||||||
|
values + ramp->size * 2);
|
||||||
|
|
||||||
|
free(values);
|
||||||
|
|
||||||
|
} // autoreleasepool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW native API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* handle)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(kCGNullDirectDisplay);
|
||||||
|
return monitor->ns.displayID;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,212 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 macOS - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#include <Carbon/Carbon.h>
|
||||||
|
|
||||||
|
// NOTE: All of NSGL was deprecated in the 10.14 SDK
|
||||||
|
// This disables the pointless warnings for every symbol we use
|
||||||
|
#define GL_SILENCE_DEPRECATION
|
||||||
|
|
||||||
|
#if defined(__OBJC__)
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#else
|
||||||
|
typedef void* id;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// NOTE: Many Cocoa enum values have been renamed and we need to build across
|
||||||
|
// SDK versions where one is unavailable or the other deprecated
|
||||||
|
// We use the newer names in code and these macros to handle compatibility
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
||||||
|
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
|
||||||
|
#define NSEventMaskAny NSAnyEventMask
|
||||||
|
#define NSEventMaskKeyUp NSKeyUpMask
|
||||||
|
#define NSEventModifierFlagCapsLock NSAlphaShiftKeyMask
|
||||||
|
#define NSEventModifierFlagCommand NSCommandKeyMask
|
||||||
|
#define NSEventModifierFlagControl NSControlKeyMask
|
||||||
|
#define NSEventModifierFlagDeviceIndependentFlagsMask NSDeviceIndependentModifierFlagsMask
|
||||||
|
#define NSEventModifierFlagOption NSAlternateKeyMask
|
||||||
|
#define NSEventModifierFlagShift NSShiftKeyMask
|
||||||
|
#define NSEventTypeApplicationDefined NSApplicationDefined
|
||||||
|
#define NSWindowStyleMaskBorderless NSBorderlessWindowMask
|
||||||
|
#define NSWindowStyleMaskClosable NSClosableWindowMask
|
||||||
|
#define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask
|
||||||
|
#define NSWindowStyleMaskResizable NSResizableWindowMask
|
||||||
|
#define NSWindowStyleMaskTitled NSTitledWindowMask
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
|
||||||
|
typedef VkFlags VkMetalSurfaceCreateFlagsEXT;
|
||||||
|
|
||||||
|
typedef struct VkMacOSSurfaceCreateInfoMVK
|
||||||
|
{
|
||||||
|
VkStructureType sType;
|
||||||
|
const void* pNext;
|
||||||
|
VkMacOSSurfaceCreateFlagsMVK flags;
|
||||||
|
const void* pView;
|
||||||
|
} VkMacOSSurfaceCreateInfoMVK;
|
||||||
|
|
||||||
|
typedef struct VkMetalSurfaceCreateInfoEXT
|
||||||
|
{
|
||||||
|
VkStructureType sType;
|
||||||
|
const void* pNext;
|
||||||
|
VkMetalSurfaceCreateFlagsEXT flags;
|
||||||
|
const void* pLayer;
|
||||||
|
} VkMetalSurfaceCreateInfoEXT;
|
||||||
|
|
||||||
|
typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||||
|
typedef VkResult (APIENTRY *PFN_vkCreateMetalSurfaceEXT)(VkInstance,const VkMetalSurfaceCreateInfoEXT*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||||
|
|
||||||
|
#include "posix_thread.h"
|
||||||
|
#include "cocoa_joystick.h"
|
||||||
|
#include "nsgl_context.h"
|
||||||
|
#include "egl_context.h"
|
||||||
|
#include "osmesa_context.h"
|
||||||
|
|
||||||
|
#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_WINDOW ((EGLNativeWindowType) window->ns.layer)
|
||||||
|
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS ns
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerNS ns
|
||||||
|
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNS ns
|
||||||
|
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorNS ns
|
||||||
|
|
||||||
|
// HIToolbox.framework pointer typedefs
|
||||||
|
#define kTISPropertyUnicodeKeyLayoutData _glfw.ns.tis.kPropertyUnicodeKeyLayoutData
|
||||||
|
typedef TISInputSourceRef (*PFN_TISCopyCurrentKeyboardLayoutInputSource)(void);
|
||||||
|
#define TISCopyCurrentKeyboardLayoutInputSource _glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource
|
||||||
|
typedef void* (*PFN_TISGetInputSourceProperty)(TISInputSourceRef,CFStringRef);
|
||||||
|
#define TISGetInputSourceProperty _glfw.ns.tis.GetInputSourceProperty
|
||||||
|
typedef UInt8 (*PFN_LMGetKbdType)(void);
|
||||||
|
#define LMGetKbdType _glfw.ns.tis.GetKbdType
|
||||||
|
|
||||||
|
|
||||||
|
// Cocoa-specific per-window data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWwindowNS
|
||||||
|
{
|
||||||
|
id object;
|
||||||
|
id delegate;
|
||||||
|
id view;
|
||||||
|
id layer;
|
||||||
|
|
||||||
|
GLFWbool maximized;
|
||||||
|
GLFWbool occluded;
|
||||||
|
GLFWbool retina;
|
||||||
|
|
||||||
|
// Cached window properties to filter out duplicate events
|
||||||
|
int width, height;
|
||||||
|
int fbWidth, fbHeight;
|
||||||
|
float xscale, yscale;
|
||||||
|
|
||||||
|
// The total sum of the distances the cursor has been warped
|
||||||
|
// since the last cursor motion event was processed
|
||||||
|
// This is kept to counteract Cocoa doing the same internally
|
||||||
|
double cursorWarpDeltaX, cursorWarpDeltaY;
|
||||||
|
|
||||||
|
} _GLFWwindowNS;
|
||||||
|
|
||||||
|
// Cocoa-specific global data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWlibraryNS
|
||||||
|
{
|
||||||
|
CGEventSourceRef eventSource;
|
||||||
|
id delegate;
|
||||||
|
GLFWbool finishedLaunching;
|
||||||
|
GLFWbool cursorHidden;
|
||||||
|
TISInputSourceRef inputSource;
|
||||||
|
IOHIDManagerRef hidManager;
|
||||||
|
id unicodeData;
|
||||||
|
id helper;
|
||||||
|
id keyUpMonitor;
|
||||||
|
id nibObjects;
|
||||||
|
|
||||||
|
char keynames[GLFW_KEY_LAST + 1][17];
|
||||||
|
short int keycodes[256];
|
||||||
|
short int scancodes[GLFW_KEY_LAST + 1];
|
||||||
|
char* clipboardString;
|
||||||
|
CGPoint cascadePoint;
|
||||||
|
// Where to place the cursor when re-enabled
|
||||||
|
double restoreCursorPosX, restoreCursorPosY;
|
||||||
|
// The window whose disabled cursor mode is active
|
||||||
|
_GLFWwindow* disabledCursorWindow;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
CFBundleRef bundle;
|
||||||
|
PFN_TISCopyCurrentKeyboardLayoutInputSource CopyCurrentKeyboardLayoutInputSource;
|
||||||
|
PFN_TISGetInputSourceProperty GetInputSourceProperty;
|
||||||
|
PFN_LMGetKbdType GetKbdType;
|
||||||
|
CFStringRef kPropertyUnicodeKeyLayoutData;
|
||||||
|
} tis;
|
||||||
|
|
||||||
|
} _GLFWlibraryNS;
|
||||||
|
|
||||||
|
// Cocoa-specific per-monitor data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWmonitorNS
|
||||||
|
{
|
||||||
|
CGDirectDisplayID displayID;
|
||||||
|
CGDisplayModeRef previousMode;
|
||||||
|
uint32_t unitNumber;
|
||||||
|
id screen;
|
||||||
|
double fallbackRefreshRate;
|
||||||
|
|
||||||
|
} _GLFWmonitorNS;
|
||||||
|
|
||||||
|
// Cocoa-specific per-cursor data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWcursorNS
|
||||||
|
{
|
||||||
|
id object;
|
||||||
|
|
||||||
|
} _GLFWcursorNS;
|
||||||
|
|
||||||
|
// Cocoa-specific global timer data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWtimerNS
|
||||||
|
{
|
||||||
|
uint64_t frequency;
|
||||||
|
|
||||||
|
} _GLFWtimerNS;
|
||||||
|
|
||||||
|
|
||||||
|
void _glfwInitTimerNS(void);
|
||||||
|
|
||||||
|
void _glfwPollMonitorsNS(void);
|
||||||
|
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||||
|
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
|
||||||
|
|
||||||
|
float _glfwTransformYNS(float y);
|
||||||
|
|
||||||
|
void* _glfwLoadLocalVulkanLoaderNS(void);
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 macOS - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <mach/mach_time.h>
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Initialise timer
|
||||||
|
//
|
||||||
|
void _glfwInitTimerNS(void)
|
||||||
|
{
|
||||||
|
mach_timebase_info_data_t info;
|
||||||
|
mach_timebase_info(&info);
|
||||||
|
|
||||||
|
_glfw.timer.ns.frequency = (info.denom * 1e9) / info.numer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
uint64_t _glfwPlatformGetTimerValue(void)
|
||||||
|
{
|
||||||
|
return mach_absolute_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t _glfwPlatformGetTimerFrequency(void)
|
||||||
|
{
|
||||||
|
return _glfw.timer.ns.frequency;
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,760 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Checks whether the desired context attributes are valid
|
||||||
|
//
|
||||||
|
// This function checks things like whether the specified client API version
|
||||||
|
// exists and whether all relevant options have supported and non-conflicting
|
||||||
|
// values
|
||||||
|
//
|
||||||
|
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||||
|
{
|
||||||
|
if (ctxconfig->share)
|
||||||
|
{
|
||||||
|
if (ctxconfig->client == GLFW_NO_API ||
|
||||||
|
ctxconfig->share->context.client == GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
|
||||||
|
ctxconfig->source != GLFW_EGL_CONTEXT_API &&
|
||||||
|
ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
|
"Invalid context creation API 0x%08X",
|
||||||
|
ctxconfig->source);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->client != GLFW_NO_API &&
|
||||||
|
ctxconfig->client != GLFW_OPENGL_API &&
|
||||||
|
ctxconfig->client != GLFW_OPENGL_ES_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
|
"Invalid client API 0x%08X",
|
||||||
|
ctxconfig->client);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
|
{
|
||||||
|
if ((ctxconfig->major < 1 || ctxconfig->minor < 0) ||
|
||||||
|
(ctxconfig->major == 1 && ctxconfig->minor > 5) ||
|
||||||
|
(ctxconfig->major == 2 && ctxconfig->minor > 1) ||
|
||||||
|
(ctxconfig->major == 3 && ctxconfig->minor > 3))
|
||||||
|
{
|
||||||
|
// OpenGL 1.0 is the smallest valid version
|
||||||
|
// OpenGL 1.x series ended with version 1.5
|
||||||
|
// OpenGL 2.x series ended with version 2.1
|
||||||
|
// OpenGL 3.x series ended with version 3.3
|
||||||
|
// For now, let everything else through
|
||||||
|
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Invalid OpenGL version %i.%i",
|
||||||
|
ctxconfig->major, ctxconfig->minor);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->profile)
|
||||||
|
{
|
||||||
|
if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE &&
|
||||||
|
ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
|
"Invalid OpenGL profile 0x%08X",
|
||||||
|
ctxconfig->profile);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->major <= 2 ||
|
||||||
|
(ctxconfig->major == 3 && ctxconfig->minor < 2))
|
||||||
|
{
|
||||||
|
// Desktop OpenGL context profiles are only defined for version 3.2
|
||||||
|
// and above
|
||||||
|
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Context profiles are only defined for OpenGL version 3.2 and above");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->forward && ctxconfig->major <= 2)
|
||||||
|
{
|
||||||
|
// Forward-compatible contexts are only defined for OpenGL version 3.0 and above
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Forward-compatibility is only defined for OpenGL version 3.0 and above");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
|
{
|
||||||
|
if (ctxconfig->major < 1 || ctxconfig->minor < 0 ||
|
||||||
|
(ctxconfig->major == 1 && ctxconfig->minor > 1) ||
|
||||||
|
(ctxconfig->major == 2 && ctxconfig->minor > 0))
|
||||||
|
{
|
||||||
|
// OpenGL ES 1.0 is the smallest valid version
|
||||||
|
// OpenGL ES 1.x series ended with version 1.1
|
||||||
|
// OpenGL ES 2.x series ended with version 2.0
|
||||||
|
// For now, let everything else through
|
||||||
|
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Invalid OpenGL ES version %i.%i",
|
||||||
|
ctxconfig->major, ctxconfig->minor);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->robustness)
|
||||||
|
{
|
||||||
|
if (ctxconfig->robustness != GLFW_NO_RESET_NOTIFICATION &&
|
||||||
|
ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
|
"Invalid context robustness mode 0x%08X",
|
||||||
|
ctxconfig->robustness);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->release)
|
||||||
|
{
|
||||||
|
if (ctxconfig->release != GLFW_RELEASE_BEHAVIOR_NONE &&
|
||||||
|
ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
|
"Invalid context release behavior 0x%08X",
|
||||||
|
ctxconfig->release);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chooses the framebuffer config that best matches the desired one
|
||||||
|
//
|
||||||
|
const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
||||||
|
const _GLFWfbconfig* alternatives,
|
||||||
|
unsigned int count)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
unsigned int missing, leastMissing = UINT_MAX;
|
||||||
|
unsigned int colorDiff, leastColorDiff = UINT_MAX;
|
||||||
|
unsigned int extraDiff, leastExtraDiff = UINT_MAX;
|
||||||
|
const _GLFWfbconfig* current;
|
||||||
|
const _GLFWfbconfig* closest = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
current = alternatives + i;
|
||||||
|
|
||||||
|
if (desired->stereo > 0 && current->stereo == 0)
|
||||||
|
{
|
||||||
|
// Stereo is a hard constraint
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desired->doublebuffer != current->doublebuffer)
|
||||||
|
{
|
||||||
|
// Double buffering is a hard constraint
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count number of missing buffers
|
||||||
|
{
|
||||||
|
missing = 0;
|
||||||
|
|
||||||
|
if (desired->alphaBits > 0 && current->alphaBits == 0)
|
||||||
|
missing++;
|
||||||
|
|
||||||
|
if (desired->depthBits > 0 && current->depthBits == 0)
|
||||||
|
missing++;
|
||||||
|
|
||||||
|
if (desired->stencilBits > 0 && current->stencilBits == 0)
|
||||||
|
missing++;
|
||||||
|
|
||||||
|
if (desired->auxBuffers > 0 &&
|
||||||
|
current->auxBuffers < desired->auxBuffers)
|
||||||
|
{
|
||||||
|
missing += desired->auxBuffers - current->auxBuffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desired->samples > 0 && current->samples == 0)
|
||||||
|
{
|
||||||
|
// Technically, several multisampling buffers could be
|
||||||
|
// involved, but that's a lower level implementation detail and
|
||||||
|
// not important to us here, so we count them as one
|
||||||
|
missing++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desired->transparent != current->transparent)
|
||||||
|
missing++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// These polynomials make many small channel size differences matter
|
||||||
|
// less than one large channel size difference
|
||||||
|
|
||||||
|
// Calculate color channel size difference value
|
||||||
|
{
|
||||||
|
colorDiff = 0;
|
||||||
|
|
||||||
|
if (desired->redBits != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
colorDiff += (desired->redBits - current->redBits) *
|
||||||
|
(desired->redBits - current->redBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desired->greenBits != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
colorDiff += (desired->greenBits - current->greenBits) *
|
||||||
|
(desired->greenBits - current->greenBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desired->blueBits != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
colorDiff += (desired->blueBits - current->blueBits) *
|
||||||
|
(desired->blueBits - current->blueBits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate non-color channel size difference value
|
||||||
|
{
|
||||||
|
extraDiff = 0;
|
||||||
|
|
||||||
|
if (desired->alphaBits != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
extraDiff += (desired->alphaBits - current->alphaBits) *
|
||||||
|
(desired->alphaBits - current->alphaBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desired->depthBits != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
extraDiff += (desired->depthBits - current->depthBits) *
|
||||||
|
(desired->depthBits - current->depthBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desired->stencilBits != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
extraDiff += (desired->stencilBits - current->stencilBits) *
|
||||||
|
(desired->stencilBits - current->stencilBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desired->accumRedBits != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
extraDiff += (desired->accumRedBits - current->accumRedBits) *
|
||||||
|
(desired->accumRedBits - current->accumRedBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desired->accumGreenBits != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
extraDiff += (desired->accumGreenBits - current->accumGreenBits) *
|
||||||
|
(desired->accumGreenBits - current->accumGreenBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desired->accumBlueBits != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
extraDiff += (desired->accumBlueBits - current->accumBlueBits) *
|
||||||
|
(desired->accumBlueBits - current->accumBlueBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desired->accumAlphaBits != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
extraDiff += (desired->accumAlphaBits - current->accumAlphaBits) *
|
||||||
|
(desired->accumAlphaBits - current->accumAlphaBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desired->samples != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
extraDiff += (desired->samples - current->samples) *
|
||||||
|
(desired->samples - current->samples);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desired->sRGB && !current->sRGB)
|
||||||
|
extraDiff++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Figure out if the current one is better than the best one found so far
|
||||||
|
// Least number of missing buffers is the most important heuristic,
|
||||||
|
// then color buffer size match and lastly size match for other buffers
|
||||||
|
|
||||||
|
if (missing < leastMissing)
|
||||||
|
closest = current;
|
||||||
|
else if (missing == leastMissing)
|
||||||
|
{
|
||||||
|
if ((colorDiff < leastColorDiff) ||
|
||||||
|
(colorDiff == leastColorDiff && extraDiff < leastExtraDiff))
|
||||||
|
{
|
||||||
|
closest = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current == closest)
|
||||||
|
{
|
||||||
|
leastMissing = missing;
|
||||||
|
leastColorDiff = colorDiff;
|
||||||
|
leastExtraDiff = extraDiff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return closest;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieves the attributes of the current context
|
||||||
|
//
|
||||||
|
GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
_GLFWwindow* previous;
|
||||||
|
const char* version;
|
||||||
|
const char* prefixes[] =
|
||||||
|
{
|
||||||
|
"OpenGL ES-CM ",
|
||||||
|
"OpenGL ES-CL ",
|
||||||
|
"OpenGL ES ",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
window->context.source = ctxconfig->source;
|
||||||
|
window->context.client = GLFW_OPENGL_API;
|
||||||
|
|
||||||
|
previous = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) window);
|
||||||
|
|
||||||
|
window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
|
||||||
|
window->context.getProcAddress("glGetIntegerv");
|
||||||
|
window->context.GetString = (PFNGLGETSTRINGPROC)
|
||||||
|
window->context.getProcAddress("glGetString");
|
||||||
|
if (!window->context.GetIntegerv || !window->context.GetString)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
version = (const char*) window->context.GetString(GL_VERSION);
|
||||||
|
if (!version)
|
||||||
|
{
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"OpenGL version string retrieval is broken");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"OpenGL ES version string retrieval is broken");
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; prefixes[i]; i++)
|
||||||
|
{
|
||||||
|
const size_t length = strlen(prefixes[i]);
|
||||||
|
|
||||||
|
if (strncmp(version, prefixes[i], length) == 0)
|
||||||
|
{
|
||||||
|
version += length;
|
||||||
|
window->context.client = GLFW_OPENGL_ES_API;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sscanf(version, "%d.%d.%d",
|
||||||
|
&window->context.major,
|
||||||
|
&window->context.minor,
|
||||||
|
&window->context.revision))
|
||||||
|
{
|
||||||
|
if (window->context.client == GLFW_OPENGL_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"No version found in OpenGL version string");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"No version found in OpenGL ES version string");
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->context.major < ctxconfig->major ||
|
||||||
|
(window->context.major == ctxconfig->major &&
|
||||||
|
window->context.minor < ctxconfig->minor))
|
||||||
|
{
|
||||||
|
// The desired OpenGL version is greater than the actual version
|
||||||
|
// This only happens if the machine lacks {GLX|WGL}_ARB_create_context
|
||||||
|
// /and/ the user has requested an OpenGL version greater than 1.0
|
||||||
|
|
||||||
|
// For API consistency, we emulate the behavior of the
|
||||||
|
// {GLX|WGL}_ARB_create_context extension and fail here
|
||||||
|
|
||||||
|
if (window->context.client == GLFW_OPENGL_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"Requested OpenGL version %i.%i, got version %i.%i",
|
||||||
|
ctxconfig->major, ctxconfig->minor,
|
||||||
|
window->context.major, window->context.minor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"Requested OpenGL ES version %i.%i, got version %i.%i",
|
||||||
|
ctxconfig->major, ctxconfig->minor,
|
||||||
|
window->context.major, window->context.minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->context.major >= 3)
|
||||||
|
{
|
||||||
|
// OpenGL 3.0+ uses a different function for extension string retrieval
|
||||||
|
// We cache it here instead of in glfwExtensionSupported mostly to alert
|
||||||
|
// users as early as possible that their build may be broken
|
||||||
|
|
||||||
|
window->context.GetStringi = (PFNGLGETSTRINGIPROC)
|
||||||
|
window->context.getProcAddress("glGetStringi");
|
||||||
|
if (!window->context.GetStringi)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Entry point retrieval is broken");
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->context.client == GLFW_OPENGL_API)
|
||||||
|
{
|
||||||
|
// Read back context flags (OpenGL 3.0 and above)
|
||||||
|
if (window->context.major >= 3)
|
||||||
|
{
|
||||||
|
GLint flags;
|
||||||
|
window->context.GetIntegerv(GL_CONTEXT_FLAGS, &flags);
|
||||||
|
|
||||||
|
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
|
||||||
|
window->context.forward = GLFW_TRUE;
|
||||||
|
|
||||||
|
if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
|
||||||
|
window->context.debug = GLFW_TRUE;
|
||||||
|
else if (glfwExtensionSupported("GL_ARB_debug_output") &&
|
||||||
|
ctxconfig->debug)
|
||||||
|
{
|
||||||
|
// HACK: This is a workaround for older drivers (pre KHR_debug)
|
||||||
|
// not setting the debug bit in the context flags for
|
||||||
|
// debug contexts
|
||||||
|
window->context.debug = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR)
|
||||||
|
window->context.noerror = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read back OpenGL context profile (OpenGL 3.2 and above)
|
||||||
|
if (window->context.major >= 4 ||
|
||||||
|
(window->context.major == 3 && window->context.minor >= 2))
|
||||||
|
{
|
||||||
|
GLint mask;
|
||||||
|
window->context.GetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
|
||||||
|
|
||||||
|
if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
|
||||||
|
window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
|
||||||
|
else if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
|
||||||
|
window->context.profile = GLFW_OPENGL_CORE_PROFILE;
|
||||||
|
else if (glfwExtensionSupported("GL_ARB_compatibility"))
|
||||||
|
{
|
||||||
|
// HACK: This is a workaround for the compatibility profile bit
|
||||||
|
// not being set in the context flags if an OpenGL 3.2+
|
||||||
|
// context was created without having requested a specific
|
||||||
|
// version
|
||||||
|
window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read back robustness strategy
|
||||||
|
if (glfwExtensionSupported("GL_ARB_robustness"))
|
||||||
|
{
|
||||||
|
// NOTE: We avoid using the context flags for detection, as they are
|
||||||
|
// only present from 3.0 while the extension applies from 1.1
|
||||||
|
|
||||||
|
GLint strategy;
|
||||||
|
window->context.GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||||
|
&strategy);
|
||||||
|
|
||||||
|
if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
|
||||||
|
window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
|
||||||
|
else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
|
||||||
|
window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Read back robustness strategy
|
||||||
|
if (glfwExtensionSupported("GL_EXT_robustness"))
|
||||||
|
{
|
||||||
|
// NOTE: The values of these constants match those of the OpenGL ARB
|
||||||
|
// one, so we can reuse them here
|
||||||
|
|
||||||
|
GLint strategy;
|
||||||
|
window->context.GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||||
|
&strategy);
|
||||||
|
|
||||||
|
if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
|
||||||
|
window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
|
||||||
|
else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
|
||||||
|
window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glfwExtensionSupported("GL_KHR_context_flush_control"))
|
||||||
|
{
|
||||||
|
GLint behavior;
|
||||||
|
window->context.GetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior);
|
||||||
|
|
||||||
|
if (behavior == GL_NONE)
|
||||||
|
window->context.release = GLFW_RELEASE_BEHAVIOR_NONE;
|
||||||
|
else if (behavior == GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH)
|
||||||
|
window->context.release = GLFW_RELEASE_BEHAVIOR_FLUSH;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clearing the front buffer to black to avoid garbage pixels left over from
|
||||||
|
// previous uses of our bit of VRAM
|
||||||
|
{
|
||||||
|
PFNGLCLEARPROC glClear = (PFNGLCLEARPROC)
|
||||||
|
window->context.getProcAddress("glClear");
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
window->context.swapBuffers(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Searches an extension string for the specified extension
|
||||||
|
//
|
||||||
|
GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions)
|
||||||
|
{
|
||||||
|
const char* start = extensions;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
const char* where;
|
||||||
|
const char* terminator;
|
||||||
|
|
||||||
|
where = strstr(start, string);
|
||||||
|
if (!where)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
terminator = where + strlen(string);
|
||||||
|
if (where == start || *(where - 1) == ' ')
|
||||||
|
{
|
||||||
|
if (*terminator == ' ' || *terminator == '\0')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = terminator;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW public API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
_GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (window && window->context.client == GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT,
|
||||||
|
"Cannot make current with a window that has no OpenGL or OpenGL ES context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous)
|
||||||
|
{
|
||||||
|
if (!window || window->context.source != previous->context.source)
|
||||||
|
previous->context.makeCurrent(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window)
|
||||||
|
window->context.makeCurrent(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
return _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (window->context.client == GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT,
|
||||||
|
"Cannot swap buffers of a window that has no OpenGL or OpenGL ES context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->context.swapBuffers(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSwapInterval(int interval)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_CURRENT_CONTEXT,
|
||||||
|
"Cannot set swap interval without a current OpenGL or OpenGL ES context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->context.swapInterval(interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwExtensionSupported(const char* extension)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window;
|
||||||
|
assert(extension != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
|
||||||
|
window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_CURRENT_CONTEXT,
|
||||||
|
"Cannot query extension without a current OpenGL or OpenGL ES context");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*extension == '\0')
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->context.major >= 3)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
GLint count;
|
||||||
|
|
||||||
|
// Check if extension is in the modern OpenGL extensions string list
|
||||||
|
|
||||||
|
window->context.GetIntegerv(GL_NUM_EXTENSIONS, &count);
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
const char* en = (const char*)
|
||||||
|
window->context.GetStringi(GL_EXTENSIONS, i);
|
||||||
|
if (!en)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Extension string retrieval is broken");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(en, extension) == 0)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Check if extension is in the old style OpenGL extensions string
|
||||||
|
|
||||||
|
const char* extensions = (const char*)
|
||||||
|
window->context.GetString(GL_EXTENSIONS);
|
||||||
|
if (!extensions)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Extension string retrieval is broken");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfwStringInExtensionString(extension, extensions))
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if extension is in the platform-specific string
|
||||||
|
return window->context.extensionSupported(extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window;
|
||||||
|
assert(procname != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_CURRENT_CONTEXT,
|
||||||
|
"Cannot query entry point without a current OpenGL or OpenGL ES context");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window->context.getProcAddress(procname);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,787 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 EGL - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Return a description of the specified EGL error
|
||||||
|
//
|
||||||
|
static const char* getEGLErrorString(EGLint error)
|
||||||
|
{
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case EGL_SUCCESS:
|
||||||
|
return "Success";
|
||||||
|
case EGL_NOT_INITIALIZED:
|
||||||
|
return "EGL is not or could not be initialized";
|
||||||
|
case EGL_BAD_ACCESS:
|
||||||
|
return "EGL cannot access a requested resource";
|
||||||
|
case EGL_BAD_ALLOC:
|
||||||
|
return "EGL failed to allocate resources for the requested operation";
|
||||||
|
case EGL_BAD_ATTRIBUTE:
|
||||||
|
return "An unrecognized attribute or attribute value was passed in the attribute list";
|
||||||
|
case EGL_BAD_CONTEXT:
|
||||||
|
return "An EGLContext argument does not name a valid EGL rendering context";
|
||||||
|
case EGL_BAD_CONFIG:
|
||||||
|
return "An EGLConfig argument does not name a valid EGL frame buffer configuration";
|
||||||
|
case EGL_BAD_CURRENT_SURFACE:
|
||||||
|
return "The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid";
|
||||||
|
case EGL_BAD_DISPLAY:
|
||||||
|
return "An EGLDisplay argument does not name a valid EGL display connection";
|
||||||
|
case EGL_BAD_SURFACE:
|
||||||
|
return "An EGLSurface argument does not name a valid surface configured for GL rendering";
|
||||||
|
case EGL_BAD_MATCH:
|
||||||
|
return "Arguments are inconsistent";
|
||||||
|
case EGL_BAD_PARAMETER:
|
||||||
|
return "One or more argument values are invalid";
|
||||||
|
case EGL_BAD_NATIVE_PIXMAP:
|
||||||
|
return "A NativePixmapType argument does not refer to a valid native pixmap";
|
||||||
|
case EGL_BAD_NATIVE_WINDOW:
|
||||||
|
return "A NativeWindowType argument does not refer to a valid native window";
|
||||||
|
case EGL_CONTEXT_LOST:
|
||||||
|
return "The application must destroy all contexts and reinitialise";
|
||||||
|
default:
|
||||||
|
return "ERROR: UNKNOWN EGL ERROR";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the specified attribute of the specified EGLConfig
|
||||||
|
//
|
||||||
|
static int getEGLConfigAttrib(EGLConfig config, int attrib)
|
||||||
|
{
|
||||||
|
int value;
|
||||||
|
eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the EGLConfig most closely matching the specified hints
|
||||||
|
//
|
||||||
|
static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* desired,
|
||||||
|
EGLConfig* result)
|
||||||
|
{
|
||||||
|
EGLConfig* nativeConfigs;
|
||||||
|
_GLFWfbconfig* usableConfigs;
|
||||||
|
const _GLFWfbconfig* closest;
|
||||||
|
int i, nativeCount, usableCount;
|
||||||
|
|
||||||
|
eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
|
||||||
|
if (!nativeCount)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeConfigs = calloc(nativeCount, sizeof(EGLConfig));
|
||||||
|
eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount);
|
||||||
|
|
||||||
|
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
||||||
|
usableCount = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < nativeCount; i++)
|
||||||
|
{
|
||||||
|
const EGLConfig n = nativeConfigs[i];
|
||||||
|
_GLFWfbconfig* u = usableConfigs + usableCount;
|
||||||
|
|
||||||
|
// Only consider RGB(A) EGLConfigs
|
||||||
|
if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Only consider window EGLConfigs
|
||||||
|
if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
#if defined(_GLFW_X11)
|
||||||
|
{
|
||||||
|
XVisualInfo vi = {0};
|
||||||
|
|
||||||
|
// Only consider EGLConfigs with associated Visuals
|
||||||
|
vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
|
||||||
|
if (!vi.visualid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (desired->transparent)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
XVisualInfo* vis =
|
||||||
|
XGetVisualInfo(_glfw.x11.display, VisualIDMask, &vi, &count);
|
||||||
|
if (vis)
|
||||||
|
{
|
||||||
|
u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
|
||||||
|
XFree(vis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // _GLFW_X11
|
||||||
|
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
|
{
|
||||||
|
if (ctxconfig->major == 1)
|
||||||
|
{
|
||||||
|
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
|
{
|
||||||
|
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);
|
||||||
|
u->greenBits = getEGLConfigAttrib(n, EGL_GREEN_SIZE);
|
||||||
|
u->blueBits = getEGLConfigAttrib(n, EGL_BLUE_SIZE);
|
||||||
|
|
||||||
|
u->alphaBits = getEGLConfigAttrib(n, EGL_ALPHA_SIZE);
|
||||||
|
u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE);
|
||||||
|
u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
|
||||||
|
|
||||||
|
u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
|
||||||
|
u->doublebuffer = GLFW_TRUE;
|
||||||
|
|
||||||
|
u->handle = (uintptr_t) n;
|
||||||
|
usableCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
|
||||||
|
if (closest)
|
||||||
|
*result = (EGLConfig) closest->handle;
|
||||||
|
|
||||||
|
free(nativeConfigs);
|
||||||
|
free(usableConfigs);
|
||||||
|
|
||||||
|
return closest != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void makeContextCurrentEGL(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window)
|
||||||
|
{
|
||||||
|
if (!eglMakeCurrent(_glfw.egl.display,
|
||||||
|
window->context.egl.surface,
|
||||||
|
window->context.egl.surface,
|
||||||
|
window->context.egl.handle))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"EGL: Failed to make context current: %s",
|
||||||
|
getEGLErrorString(eglGetError()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!eglMakeCurrent(_glfw.egl.display,
|
||||||
|
EGL_NO_SURFACE,
|
||||||
|
EGL_NO_SURFACE,
|
||||||
|
EGL_NO_CONTEXT))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"EGL: Failed to clear current context: %s",
|
||||||
|
getEGLErrorString(eglGetError()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void swapBuffersEGL(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window != _glfwPlatformGetTls(&_glfw.contextSlot))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"EGL: The context must be current on the calling thread when swapping buffers");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void swapIntervalEGL(int interval)
|
||||||
|
{
|
||||||
|
eglSwapInterval(_glfw.egl.display, interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int extensionSupportedEGL(const char* extension)
|
||||||
|
{
|
||||||
|
const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
|
||||||
|
if (extensions)
|
||||||
|
{
|
||||||
|
if (_glfwStringInExtensionString(extension, extensions))
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLFWglproc getProcAddressEGL(const char* procname)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
|
|
||||||
|
if (window->context.egl.client)
|
||||||
|
{
|
||||||
|
GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->context.egl.client,
|
||||||
|
procname);
|
||||||
|
if (proc)
|
||||||
|
return proc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return eglGetProcAddress(procname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroyContextEGL(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
#if defined(_GLFW_X11)
|
||||||
|
// NOTE: Do not unload libGL.so.1 while the X11 display is still open,
|
||||||
|
// as it will make XCloseDisplay segfault
|
||||||
|
if (window->context.client != GLFW_OPENGL_API)
|
||||||
|
#endif // _GLFW_X11
|
||||||
|
{
|
||||||
|
if (window->context.egl.client)
|
||||||
|
{
|
||||||
|
_glfw_dlclose(window->context.egl.client);
|
||||||
|
window->context.egl.client = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->context.egl.surface)
|
||||||
|
{
|
||||||
|
eglDestroySurface(_glfw.egl.display, window->context.egl.surface);
|
||||||
|
window->context.egl.surface = EGL_NO_SURFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->context.egl.handle)
|
||||||
|
{
|
||||||
|
eglDestroyContext(_glfw.egl.display, window->context.egl.handle);
|
||||||
|
window->context.egl.handle = EGL_NO_CONTEXT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Initialize EGL
|
||||||
|
//
|
||||||
|
GLFWbool _glfwInitEGL(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char* sonames[] =
|
||||||
|
{
|
||||||
|
#if defined(_GLFW_EGL_LIBRARY)
|
||||||
|
_GLFW_EGL_LIBRARY,
|
||||||
|
#elif defined(_GLFW_WIN32)
|
||||||
|
"libEGL.dll",
|
||||||
|
"EGL.dll",
|
||||||
|
#elif defined(_GLFW_COCOA)
|
||||||
|
"libEGL.dylib",
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
|
"libEGL-1.so",
|
||||||
|
#else
|
||||||
|
"libEGL.so.1",
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_glfw.egl.handle)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
for (i = 0; sonames[i]; i++)
|
||||||
|
{
|
||||||
|
_glfw.egl.handle = _glfw_dlopen(sonames[i]);
|
||||||
|
if (_glfw.egl.handle)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_glfw.egl.handle)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
|
||||||
|
|
||||||
|
_glfw.egl.GetConfigAttrib = (PFN_eglGetConfigAttrib)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
|
||||||
|
_glfw.egl.GetConfigs = (PFN_eglGetConfigs)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
|
||||||
|
_glfw.egl.GetDisplay = (PFN_eglGetDisplay)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
|
||||||
|
_glfw.egl.GetError = (PFN_eglGetError)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglGetError");
|
||||||
|
_glfw.egl.Initialize = (PFN_eglInitialize)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglInitialize");
|
||||||
|
_glfw.egl.Terminate = (PFN_eglTerminate)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglTerminate");
|
||||||
|
_glfw.egl.BindAPI = (PFN_eglBindAPI)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
|
||||||
|
_glfw.egl.CreateContext = (PFN_eglCreateContext)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
|
||||||
|
_glfw.egl.DestroySurface = (PFN_eglDestroySurface)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
|
||||||
|
_glfw.egl.DestroyContext = (PFN_eglDestroyContext)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
|
||||||
|
_glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
|
||||||
|
_glfw.egl.MakeCurrent = (PFN_eglMakeCurrent)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
|
||||||
|
_glfw.egl.SwapBuffers = (PFN_eglSwapBuffers)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
|
||||||
|
_glfw.egl.SwapInterval = (PFN_eglSwapInterval)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
|
||||||
|
_glfw.egl.QueryString = (PFN_eglQueryString)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglQueryString");
|
||||||
|
_glfw.egl.GetProcAddress = (PFN_eglGetProcAddress)
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");
|
||||||
|
|
||||||
|
if (!_glfw.egl.GetConfigAttrib ||
|
||||||
|
!_glfw.egl.GetConfigs ||
|
||||||
|
!_glfw.egl.GetDisplay ||
|
||||||
|
!_glfw.egl.GetError ||
|
||||||
|
!_glfw.egl.Initialize ||
|
||||||
|
!_glfw.egl.Terminate ||
|
||||||
|
!_glfw.egl.BindAPI ||
|
||||||
|
!_glfw.egl.CreateContext ||
|
||||||
|
!_glfw.egl.DestroySurface ||
|
||||||
|
!_glfw.egl.DestroyContext ||
|
||||||
|
!_glfw.egl.CreateWindowSurface ||
|
||||||
|
!_glfw.egl.MakeCurrent ||
|
||||||
|
!_glfw.egl.SwapBuffers ||
|
||||||
|
!_glfw.egl.SwapInterval ||
|
||||||
|
!_glfw.egl.QueryString ||
|
||||||
|
!_glfw.egl.GetProcAddress)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"EGL: Failed to load required entry points");
|
||||||
|
|
||||||
|
_glfwTerminateEGL();
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
|
||||||
|
if (_glfw.egl.display == EGL_NO_DISPLAY)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"EGL: Failed to get EGL display: %s",
|
||||||
|
getEGLErrorString(eglGetError()));
|
||||||
|
|
||||||
|
_glfwTerminateEGL();
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"EGL: Failed to initialize EGL: %s",
|
||||||
|
getEGLErrorString(eglGetError()));
|
||||||
|
|
||||||
|
_glfwTerminateEGL();
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.egl.KHR_create_context =
|
||||||
|
extensionSupportedEGL("EGL_KHR_create_context");
|
||||||
|
_glfw.egl.KHR_create_context_no_error =
|
||||||
|
extensionSupportedEGL("EGL_KHR_create_context_no_error");
|
||||||
|
_glfw.egl.KHR_gl_colorspace =
|
||||||
|
extensionSupportedEGL("EGL_KHR_gl_colorspace");
|
||||||
|
_glfw.egl.KHR_get_all_proc_addresses =
|
||||||
|
extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
|
||||||
|
_glfw.egl.KHR_context_flush_control =
|
||||||
|
extensionSupportedEGL("EGL_KHR_context_flush_control");
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Terminate EGL
|
||||||
|
//
|
||||||
|
void _glfwTerminateEGL(void)
|
||||||
|
{
|
||||||
|
if (_glfw.egl.display)
|
||||||
|
{
|
||||||
|
eglTerminate(_glfw.egl.display);
|
||||||
|
_glfw.egl.display = EGL_NO_DISPLAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.egl.handle)
|
||||||
|
{
|
||||||
|
_glfw_dlclose(_glfw.egl.handle);
|
||||||
|
_glfw.egl.handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define setAttrib(a, v) \
|
||||||
|
{ \
|
||||||
|
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||||
|
attribs[index++] = a; \
|
||||||
|
attribs[index++] = v; \
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the OpenGL or OpenGL ES context
|
||||||
|
//
|
||||||
|
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig)
|
||||||
|
{
|
||||||
|
EGLint attribs[40];
|
||||||
|
EGLConfig config;
|
||||||
|
EGLContext share = NULL;
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
if (!_glfw.egl.display)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->share)
|
||||||
|
share = ctxconfig->share->context.egl.handle;
|
||||||
|
|
||||||
|
if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
|
"EGL: Failed to find a suitable EGLConfig");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
|
{
|
||||||
|
if (!eglBindAPI(EGL_OPENGL_ES_API))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"EGL: Failed to bind OpenGL ES: %s",
|
||||||
|
getEGLErrorString(eglGetError()));
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!eglBindAPI(EGL_OPENGL_API))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"EGL: Failed to bind OpenGL: %s",
|
||||||
|
getEGLErrorString(eglGetError()));
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.egl.KHR_create_context)
|
||||||
|
{
|
||||||
|
int mask = 0, flags = 0;
|
||||||
|
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
|
{
|
||||||
|
if (ctxconfig->forward)
|
||||||
|
flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
|
||||||
|
|
||||||
|
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
||||||
|
mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
|
||||||
|
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
||||||
|
mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->debug)
|
||||||
|
flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
|
||||||
|
|
||||||
|
if (ctxconfig->robustness)
|
||||||
|
{
|
||||||
|
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||||
|
{
|
||||||
|
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||||
|
EGL_NO_RESET_NOTIFICATION_KHR);
|
||||||
|
}
|
||||||
|
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||||
|
{
|
||||||
|
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||||
|
EGL_LOSE_CONTEXT_ON_RESET_KHR);
|
||||||
|
}
|
||||||
|
|
||||||
|
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->noerror)
|
||||||
|
{
|
||||||
|
if (_glfw.egl.KHR_create_context_no_error)
|
||||||
|
setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||||
|
{
|
||||||
|
setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
|
||||||
|
setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask)
|
||||||
|
setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
|
||||||
|
|
||||||
|
if (flags)
|
||||||
|
setAttrib(EGL_CONTEXT_FLAGS_KHR, flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
|
setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.egl.KHR_context_flush_control)
|
||||||
|
{
|
||||||
|
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||||
|
{
|
||||||
|
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||||
|
EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
|
||||||
|
}
|
||||||
|
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||||
|
{
|
||||||
|
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||||
|
EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setAttrib(EGL_NONE, EGL_NONE);
|
||||||
|
|
||||||
|
window->context.egl.handle = eglCreateContext(_glfw.egl.display,
|
||||||
|
config, share, attribs);
|
||||||
|
|
||||||
|
if (window->context.egl.handle == EGL_NO_CONTEXT)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"EGL: Failed to create context: %s",
|
||||||
|
getEGLErrorString(eglGetError()));
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up attributes for surface creation
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
if (fbconfig->sRGB)
|
||||||
|
{
|
||||||
|
if (_glfw.egl.KHR_gl_colorspace)
|
||||||
|
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||||
|
}
|
||||||
|
|
||||||
|
setAttrib(EGL_NONE, EGL_NONE);
|
||||||
|
|
||||||
|
window->context.egl.surface =
|
||||||
|
eglCreateWindowSurface(_glfw.egl.display,
|
||||||
|
config,
|
||||||
|
_GLFW_EGL_NATIVE_WINDOW,
|
||||||
|
attribs);
|
||||||
|
if (window->context.egl.surface == EGL_NO_SURFACE)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"EGL: Failed to create window surface: %s",
|
||||||
|
getEGLErrorString(eglGetError()));
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->context.egl.config = config;
|
||||||
|
|
||||||
|
// Load the appropriate client library
|
||||||
|
if (!_glfw.egl.KHR_get_all_proc_addresses)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char** sonames;
|
||||||
|
const char* es1sonames[] =
|
||||||
|
{
|
||||||
|
#if defined(_GLFW_GLESV1_LIBRARY)
|
||||||
|
_GLFW_GLESV1_LIBRARY,
|
||||||
|
#elif defined(_GLFW_WIN32)
|
||||||
|
"GLESv1_CM.dll",
|
||||||
|
"libGLES_CM.dll",
|
||||||
|
#elif defined(_GLFW_COCOA)
|
||||||
|
"libGLESv1_CM.dylib",
|
||||||
|
#else
|
||||||
|
"libGLESv1_CM.so.1",
|
||||||
|
"libGLES_CM.so.1",
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
const char* es2sonames[] =
|
||||||
|
{
|
||||||
|
#if defined(_GLFW_GLESV2_LIBRARY)
|
||||||
|
_GLFW_GLESV2_LIBRARY,
|
||||||
|
#elif defined(_GLFW_WIN32)
|
||||||
|
"GLESv2.dll",
|
||||||
|
"libGLESv2.dll",
|
||||||
|
#elif defined(_GLFW_COCOA)
|
||||||
|
"libGLESv2.dylib",
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
|
"libGLESv2-2.so",
|
||||||
|
#else
|
||||||
|
"libGLESv2.so.2",
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
const char* glsonames[] =
|
||||||
|
{
|
||||||
|
#if defined(_GLFW_OPENGL_LIBRARY)
|
||||||
|
_GLFW_OPENGL_LIBRARY,
|
||||||
|
#elif defined(_GLFW_WIN32)
|
||||||
|
#elif defined(_GLFW_COCOA)
|
||||||
|
#else
|
||||||
|
"libGL.so.1",
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
|
{
|
||||||
|
if (ctxconfig->major == 1)
|
||||||
|
sonames = es1sonames;
|
||||||
|
else
|
||||||
|
sonames = es2sonames;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sonames = glsonames;
|
||||||
|
|
||||||
|
for (i = 0; sonames[i]; i++)
|
||||||
|
{
|
||||||
|
// HACK: Match presence of lib prefix to increase chance of finding
|
||||||
|
// a matching pair in the jungle that is Win32 EGL/GLES
|
||||||
|
if (_glfw.egl.prefix != (strncmp(sonames[i], "lib", 3) == 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
window->context.egl.client = _glfw_dlopen(sonames[i]);
|
||||||
|
if (window->context.egl.client)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window->context.egl.client)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"EGL: Failed to load client library");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window->context.makeCurrent = makeContextCurrentEGL;
|
||||||
|
window->context.swapBuffers = swapBuffersEGL;
|
||||||
|
window->context.swapInterval = swapIntervalEGL;
|
||||||
|
window->context.extensionSupported = extensionSupportedEGL;
|
||||||
|
window->context.getProcAddress = getProcAddressEGL;
|
||||||
|
window->context.destroy = destroyContextEGL;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef setAttrib
|
||||||
|
|
||||||
|
// Returns the Visual and depth of the chosen EGLConfig
|
||||||
|
//
|
||||||
|
#if defined(_GLFW_X11)
|
||||||
|
GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig,
|
||||||
|
Visual** visual, int* depth)
|
||||||
|
{
|
||||||
|
XVisualInfo* result;
|
||||||
|
XVisualInfo desired;
|
||||||
|
EGLConfig native;
|
||||||
|
EGLint visualID = 0, count = 0;
|
||||||
|
const long vimask = VisualScreenMask | VisualIDMask;
|
||||||
|
|
||||||
|
if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
|
"EGL: Failed to find a suitable EGLConfig");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
eglGetConfigAttrib(_glfw.egl.display, native,
|
||||||
|
EGL_NATIVE_VISUAL_ID, &visualID);
|
||||||
|
|
||||||
|
desired.screen = _glfw.x11.screen;
|
||||||
|
desired.visualid = visualID;
|
||||||
|
|
||||||
|
result = XGetVisualInfo(_glfw.x11.display, vimask, &desired, &count);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"EGL: Failed to retrieve Visual for EGLConfig");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*visual = result->visual;
|
||||||
|
*depth = result->depth;
|
||||||
|
|
||||||
|
XFree(result);
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
#endif // _GLFW_X11
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW native API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI EGLDisplay glfwGetEGLDisplay(void)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_DISPLAY);
|
||||||
|
return _glfw.egl.display;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT);
|
||||||
|
|
||||||
|
if (window->context.client == GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||||
|
return EGL_NO_CONTEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window->context.egl.handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE);
|
||||||
|
|
||||||
|
if (window->context.client == GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||||
|
return EGL_NO_SURFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window->context.egl.surface;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,215 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 EGL - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#if defined(_GLFW_USE_EGLPLATFORM_H)
|
||||||
|
#include <EGL/eglplatform.h>
|
||||||
|
#elif defined(_GLFW_WIN32)
|
||||||
|
#define EGLAPIENTRY __stdcall
|
||||||
|
typedef HDC EGLNativeDisplayType;
|
||||||
|
typedef HWND EGLNativeWindowType;
|
||||||
|
#elif defined(_GLFW_COCOA)
|
||||||
|
#define EGLAPIENTRY
|
||||||
|
typedef void* EGLNativeDisplayType;
|
||||||
|
typedef id EGLNativeWindowType;
|
||||||
|
#elif defined(_GLFW_X11)
|
||||||
|
#define EGLAPIENTRY
|
||||||
|
typedef Display* EGLNativeDisplayType;
|
||||||
|
typedef Window EGLNativeWindowType;
|
||||||
|
#elif defined(_GLFW_WAYLAND)
|
||||||
|
#define EGLAPIENTRY
|
||||||
|
typedef struct wl_display* EGLNativeDisplayType;
|
||||||
|
typedef struct wl_egl_window* EGLNativeWindowType;
|
||||||
|
#else
|
||||||
|
#error "No supported EGL platform selected"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define EGL_SUCCESS 0x3000
|
||||||
|
#define EGL_NOT_INITIALIZED 0x3001
|
||||||
|
#define EGL_BAD_ACCESS 0x3002
|
||||||
|
#define EGL_BAD_ALLOC 0x3003
|
||||||
|
#define EGL_BAD_ATTRIBUTE 0x3004
|
||||||
|
#define EGL_BAD_CONFIG 0x3005
|
||||||
|
#define EGL_BAD_CONTEXT 0x3006
|
||||||
|
#define EGL_BAD_CURRENT_SURFACE 0x3007
|
||||||
|
#define EGL_BAD_DISPLAY 0x3008
|
||||||
|
#define EGL_BAD_MATCH 0x3009
|
||||||
|
#define EGL_BAD_NATIVE_PIXMAP 0x300a
|
||||||
|
#define EGL_BAD_NATIVE_WINDOW 0x300b
|
||||||
|
#define EGL_BAD_PARAMETER 0x300c
|
||||||
|
#define EGL_BAD_SURFACE 0x300d
|
||||||
|
#define EGL_CONTEXT_LOST 0x300e
|
||||||
|
#define EGL_COLOR_BUFFER_TYPE 0x303f
|
||||||
|
#define EGL_RGB_BUFFER 0x308e
|
||||||
|
#define EGL_SURFACE_TYPE 0x3033
|
||||||
|
#define EGL_WINDOW_BIT 0x0004
|
||||||
|
#define EGL_RENDERABLE_TYPE 0x3040
|
||||||
|
#define EGL_OPENGL_ES_BIT 0x0001
|
||||||
|
#define EGL_OPENGL_ES2_BIT 0x0004
|
||||||
|
#define EGL_OPENGL_BIT 0x0008
|
||||||
|
#define EGL_ALPHA_SIZE 0x3021
|
||||||
|
#define EGL_BLUE_SIZE 0x3022
|
||||||
|
#define EGL_GREEN_SIZE 0x3023
|
||||||
|
#define EGL_RED_SIZE 0x3024
|
||||||
|
#define EGL_DEPTH_SIZE 0x3025
|
||||||
|
#define EGL_STENCIL_SIZE 0x3026
|
||||||
|
#define EGL_SAMPLES 0x3031
|
||||||
|
#define EGL_OPENGL_ES_API 0x30a0
|
||||||
|
#define EGL_OPENGL_API 0x30a2
|
||||||
|
#define EGL_NONE 0x3038
|
||||||
|
#define EGL_EXTENSIONS 0x3055
|
||||||
|
#define EGL_CONTEXT_CLIENT_VERSION 0x3098
|
||||||
|
#define EGL_NATIVE_VISUAL_ID 0x302e
|
||||||
|
#define EGL_NO_SURFACE ((EGLSurface) 0)
|
||||||
|
#define EGL_NO_DISPLAY ((EGLDisplay) 0)
|
||||||
|
#define EGL_NO_CONTEXT ((EGLContext) 0)
|
||||||
|
#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType) 0)
|
||||||
|
|
||||||
|
#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
|
||||||
|
#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
|
||||||
|
#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
|
||||||
|
#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
|
||||||
|
#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31bd
|
||||||
|
#define EGL_NO_RESET_NOTIFICATION_KHR 0x31be
|
||||||
|
#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31bf
|
||||||
|
#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
|
||||||
|
#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
|
||||||
|
#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30fb
|
||||||
|
#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30fd
|
||||||
|
#define EGL_CONTEXT_FLAGS_KHR 0x30fc
|
||||||
|
#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3
|
||||||
|
#define EGL_GL_COLORSPACE_KHR 0x309d
|
||||||
|
#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
|
||||||
|
#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
|
||||||
|
#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
|
||||||
|
#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
|
||||||
|
|
||||||
|
typedef int EGLint;
|
||||||
|
typedef unsigned int EGLBoolean;
|
||||||
|
typedef unsigned int EGLenum;
|
||||||
|
typedef void* EGLConfig;
|
||||||
|
typedef void* EGLContext;
|
||||||
|
typedef void* EGLDisplay;
|
||||||
|
typedef void* EGLSurface;
|
||||||
|
|
||||||
|
// EGL function pointer typedefs
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigs)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
|
||||||
|
typedef EGLDisplay (EGLAPIENTRY * PFN_eglGetDisplay)(EGLNativeDisplayType);
|
||||||
|
typedef EGLint (EGLAPIENTRY * PFN_eglGetError)(void);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFN_eglInitialize)(EGLDisplay,EGLint*,EGLint*);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFN_eglTerminate)(EGLDisplay);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFN_eglBindAPI)(EGLenum);
|
||||||
|
typedef EGLContext (EGLAPIENTRY * PFN_eglCreateContext)(EGLDisplay,EGLConfig,EGLContext,const EGLint*);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroySurface)(EGLDisplay,EGLSurface);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext);
|
||||||
|
typedef EGLSurface (EGLAPIENTRY * PFN_eglCreateWindowSurface)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint);
|
||||||
|
typedef const char* (EGLAPIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint);
|
||||||
|
typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*);
|
||||||
|
#define eglGetConfigAttrib _glfw.egl.GetConfigAttrib
|
||||||
|
#define eglGetConfigs _glfw.egl.GetConfigs
|
||||||
|
#define eglGetDisplay _glfw.egl.GetDisplay
|
||||||
|
#define eglGetError _glfw.egl.GetError
|
||||||
|
#define eglInitialize _glfw.egl.Initialize
|
||||||
|
#define eglTerminate _glfw.egl.Terminate
|
||||||
|
#define eglBindAPI _glfw.egl.BindAPI
|
||||||
|
#define eglCreateContext _glfw.egl.CreateContext
|
||||||
|
#define eglDestroySurface _glfw.egl.DestroySurface
|
||||||
|
#define eglDestroyContext _glfw.egl.DestroyContext
|
||||||
|
#define eglCreateWindowSurface _glfw.egl.CreateWindowSurface
|
||||||
|
#define eglMakeCurrent _glfw.egl.MakeCurrent
|
||||||
|
#define eglSwapBuffers _glfw.egl.SwapBuffers
|
||||||
|
#define eglSwapInterval _glfw.egl.SwapInterval
|
||||||
|
#define eglQueryString _glfw.egl.QueryString
|
||||||
|
#define eglGetProcAddress _glfw.egl.GetProcAddress
|
||||||
|
|
||||||
|
#define _GLFW_EGL_CONTEXT_STATE _GLFWcontextEGL egl
|
||||||
|
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl
|
||||||
|
|
||||||
|
|
||||||
|
// EGL-specific per-context data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWcontextEGL
|
||||||
|
{
|
||||||
|
EGLConfig config;
|
||||||
|
EGLContext handle;
|
||||||
|
EGLSurface surface;
|
||||||
|
|
||||||
|
void* client;
|
||||||
|
|
||||||
|
} _GLFWcontextEGL;
|
||||||
|
|
||||||
|
// EGL-specific global data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWlibraryEGL
|
||||||
|
{
|
||||||
|
EGLDisplay display;
|
||||||
|
EGLint major, minor;
|
||||||
|
GLFWbool prefix;
|
||||||
|
|
||||||
|
GLFWbool KHR_create_context;
|
||||||
|
GLFWbool KHR_create_context_no_error;
|
||||||
|
GLFWbool KHR_gl_colorspace;
|
||||||
|
GLFWbool KHR_get_all_proc_addresses;
|
||||||
|
GLFWbool KHR_context_flush_control;
|
||||||
|
|
||||||
|
void* handle;
|
||||||
|
|
||||||
|
PFN_eglGetConfigAttrib GetConfigAttrib;
|
||||||
|
PFN_eglGetConfigs GetConfigs;
|
||||||
|
PFN_eglGetDisplay GetDisplay;
|
||||||
|
PFN_eglGetError GetError;
|
||||||
|
PFN_eglInitialize Initialize;
|
||||||
|
PFN_eglTerminate Terminate;
|
||||||
|
PFN_eglBindAPI BindAPI;
|
||||||
|
PFN_eglCreateContext CreateContext;
|
||||||
|
PFN_eglDestroySurface DestroySurface;
|
||||||
|
PFN_eglDestroyContext DestroyContext;
|
||||||
|
PFN_eglCreateWindowSurface CreateWindowSurface;
|
||||||
|
PFN_eglMakeCurrent MakeCurrent;
|
||||||
|
PFN_eglSwapBuffers SwapBuffers;
|
||||||
|
PFN_eglSwapInterval SwapInterval;
|
||||||
|
PFN_eglQueryString QueryString;
|
||||||
|
PFN_eglGetProcAddress GetProcAddress;
|
||||||
|
|
||||||
|
} _GLFWlibraryEGL;
|
||||||
|
|
||||||
|
|
||||||
|
GLFWbool _glfwInitEGL(void);
|
||||||
|
void _glfwTerminateEGL(void);
|
||||||
|
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig);
|
||||||
|
#if defined(_GLFW_X11)
|
||||||
|
GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig,
|
||||||
|
Visual** visual, int* depth);
|
||||||
|
#endif /*_GLFW_X11*/
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
prefix=@CMAKE_INSTALL_PREFIX@
|
||||||
|
exec_prefix=${prefix}
|
||||||
|
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
||||||
|
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
||||||
|
|
||||||
|
Name: GLFW
|
||||||
|
Description: A multi-platform library for OpenGL, window and input
|
||||||
|
Version: @GLFW_VERSION@
|
||||||
|
URL: https://www.glfw.org/
|
||||||
|
Requires.private: @GLFW_PKG_DEPS@
|
||||||
|
Libs: -L${libdir} -l@GLFW_LIB_NAME@
|
||||||
|
Libs.private: @GLFW_PKG_LIBS@
|
||||||
|
Cflags: -I${includedir}
|
|
@ -0,0 +1 @@
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/glfw3Targets.cmake")
|
|
@ -0,0 +1,60 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2010-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// As glfw_config.h.in, this file is used by CMake to produce the
|
||||||
|
// glfw_config.h configuration header file. If you are adding a feature
|
||||||
|
// requiring conditional compilation, this is where to add the macro.
|
||||||
|
//========================================================================
|
||||||
|
// As glfw_config.h, this file defines compile-time option macros for a
|
||||||
|
// specific platform and development environment. If you are using the
|
||||||
|
// GLFW CMake files, modify glfw_config.h.in instead of this file. If you
|
||||||
|
// are using your own build system, make this file define the appropriate
|
||||||
|
// macros in whatever way is suitable.
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
// Define this to 1 if building GLFW for X11
|
||||||
|
#cmakedefine _GLFW_X11
|
||||||
|
// Define this to 1 if building GLFW for Win32
|
||||||
|
#cmakedefine _GLFW_WIN32
|
||||||
|
// Define this to 1 if building GLFW for Cocoa
|
||||||
|
#cmakedefine _GLFW_COCOA
|
||||||
|
// Define this to 1 if building GLFW for Wayland
|
||||||
|
#cmakedefine _GLFW_WAYLAND
|
||||||
|
// Define this to 1 if building GLFW for OSMesa
|
||||||
|
#cmakedefine _GLFW_OSMESA
|
||||||
|
|
||||||
|
// Define this to 1 if building as a shared library / dynamic library / DLL
|
||||||
|
#cmakedefine _GLFW_BUILD_DLL
|
||||||
|
// Define this to 1 to use Vulkan loader linked statically into application
|
||||||
|
#cmakedefine _GLFW_VULKAN_STATIC
|
||||||
|
|
||||||
|
// Define this to 1 to force use of high-performance GPU on hybrid systems
|
||||||
|
#cmakedefine _GLFW_USE_HYBRID_HPG
|
||||||
|
|
||||||
|
// Define this to 1 if xkbcommon supports the compose key
|
||||||
|
#cmakedefine HAVE_XKBCOMMON_COMPOSE_H
|
||||||
|
// Define this to 1 if the libc supports memfd_create()
|
||||||
|
#cmakedefine HAVE_MEMFD_CREATE
|
||||||
|
|
|
@ -0,0 +1,698 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 GLX - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifndef GLXBadProfileARB
|
||||||
|
#define GLXBadProfileARB 13
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Returns the specified attribute of the specified GLXFBConfig
|
||||||
|
//
|
||||||
|
static int getGLXFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
|
||||||
|
{
|
||||||
|
int value;
|
||||||
|
glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the GLXFBConfig most closely matching the specified hints
|
||||||
|
//
|
||||||
|
static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
|
||||||
|
GLXFBConfig* result)
|
||||||
|
{
|
||||||
|
GLXFBConfig* nativeConfigs;
|
||||||
|
_GLFWfbconfig* usableConfigs;
|
||||||
|
const _GLFWfbconfig* closest;
|
||||||
|
int i, nativeCount, usableCount;
|
||||||
|
const char* vendor;
|
||||||
|
GLFWbool trustWindowBit = GLFW_TRUE;
|
||||||
|
|
||||||
|
// HACK: This is a (hopefully temporary) workaround for Chromium
|
||||||
|
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
|
||||||
|
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
|
||||||
|
if (vendor && strcmp(vendor, "Chromium") == 0)
|
||||||
|
trustWindowBit = GLFW_FALSE;
|
||||||
|
|
||||||
|
nativeConfigs =
|
||||||
|
glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
|
||||||
|
if (!nativeConfigs || !nativeCount)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
||||||
|
usableCount = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < nativeCount; i++)
|
||||||
|
{
|
||||||
|
const GLXFBConfig n = nativeConfigs[i];
|
||||||
|
_GLFWfbconfig* u = usableConfigs + usableCount;
|
||||||
|
|
||||||
|
// Only consider RGBA GLXFBConfigs
|
||||||
|
if (!(getGLXFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Only consider window GLXFBConfigs
|
||||||
|
if (!(getGLXFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT))
|
||||||
|
{
|
||||||
|
if (trustWindowBit)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desired->transparent)
|
||||||
|
{
|
||||||
|
XVisualInfo* vi = glXGetVisualFromFBConfig(_glfw.x11.display, n);
|
||||||
|
if (vi)
|
||||||
|
{
|
||||||
|
u->transparent = _glfwIsVisualTransparentX11(vi->visual);
|
||||||
|
XFree(vi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u->redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE);
|
||||||
|
u->greenBits = getGLXFBConfigAttrib(n, GLX_GREEN_SIZE);
|
||||||
|
u->blueBits = getGLXFBConfigAttrib(n, GLX_BLUE_SIZE);
|
||||||
|
|
||||||
|
u->alphaBits = getGLXFBConfigAttrib(n, GLX_ALPHA_SIZE);
|
||||||
|
u->depthBits = getGLXFBConfigAttrib(n, GLX_DEPTH_SIZE);
|
||||||
|
u->stencilBits = getGLXFBConfigAttrib(n, GLX_STENCIL_SIZE);
|
||||||
|
|
||||||
|
u->accumRedBits = getGLXFBConfigAttrib(n, GLX_ACCUM_RED_SIZE);
|
||||||
|
u->accumGreenBits = getGLXFBConfigAttrib(n, GLX_ACCUM_GREEN_SIZE);
|
||||||
|
u->accumBlueBits = getGLXFBConfigAttrib(n, GLX_ACCUM_BLUE_SIZE);
|
||||||
|
u->accumAlphaBits = getGLXFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE);
|
||||||
|
|
||||||
|
u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
|
||||||
|
|
||||||
|
if (getGLXFBConfigAttrib(n, GLX_STEREO))
|
||||||
|
u->stereo = GLFW_TRUE;
|
||||||
|
if (getGLXFBConfigAttrib(n, GLX_DOUBLEBUFFER))
|
||||||
|
u->doublebuffer = GLFW_TRUE;
|
||||||
|
|
||||||
|
if (_glfw.glx.ARB_multisample)
|
||||||
|
u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES);
|
||||||
|
|
||||||
|
if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB)
|
||||||
|
u->sRGB = getGLXFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
|
||||||
|
|
||||||
|
u->handle = (uintptr_t) n;
|
||||||
|
usableCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
|
||||||
|
if (closest)
|
||||||
|
*result = (GLXFBConfig) closest->handle;
|
||||||
|
|
||||||
|
XFree(nativeConfigs);
|
||||||
|
free(usableConfigs);
|
||||||
|
|
||||||
|
return closest != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the OpenGL context using legacy API
|
||||||
|
//
|
||||||
|
static GLXContext createLegacyContextGLX(_GLFWwindow* window,
|
||||||
|
GLXFBConfig fbconfig,
|
||||||
|
GLXContext share)
|
||||||
|
{
|
||||||
|
return glXCreateNewContext(_glfw.x11.display,
|
||||||
|
fbconfig,
|
||||||
|
GLX_RGBA_TYPE,
|
||||||
|
share,
|
||||||
|
True);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void makeContextCurrentGLX(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window)
|
||||||
|
{
|
||||||
|
if (!glXMakeCurrent(_glfw.x11.display,
|
||||||
|
window->context.glx.window,
|
||||||
|
window->context.glx.handle))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"GLX: Failed to make context current");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!glXMakeCurrent(_glfw.x11.display, None, NULL))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"GLX: Failed to clear current context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void swapBuffersGLX(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
glXSwapBuffers(_glfw.x11.display, window->context.glx.window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void swapIntervalGLX(int interval)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
|
|
||||||
|
if (_glfw.glx.EXT_swap_control)
|
||||||
|
{
|
||||||
|
_glfw.glx.SwapIntervalEXT(_glfw.x11.display,
|
||||||
|
window->context.glx.window,
|
||||||
|
interval);
|
||||||
|
}
|
||||||
|
else if (_glfw.glx.MESA_swap_control)
|
||||||
|
_glfw.glx.SwapIntervalMESA(interval);
|
||||||
|
else if (_glfw.glx.SGI_swap_control)
|
||||||
|
{
|
||||||
|
if (interval > 0)
|
||||||
|
_glfw.glx.SwapIntervalSGI(interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int extensionSupportedGLX(const char* extension)
|
||||||
|
{
|
||||||
|
const char* extensions =
|
||||||
|
glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen);
|
||||||
|
if (extensions)
|
||||||
|
{
|
||||||
|
if (_glfwStringInExtensionString(extension, extensions))
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLFWglproc getProcAddressGLX(const char* procname)
|
||||||
|
{
|
||||||
|
if (_glfw.glx.GetProcAddress)
|
||||||
|
return _glfw.glx.GetProcAddress((const GLubyte*) procname);
|
||||||
|
else if (_glfw.glx.GetProcAddressARB)
|
||||||
|
return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
|
||||||
|
else
|
||||||
|
return _glfw_dlsym(_glfw.glx.handle, procname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroyContextGLX(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window->context.glx.window)
|
||||||
|
{
|
||||||
|
glXDestroyWindow(_glfw.x11.display, window->context.glx.window);
|
||||||
|
window->context.glx.window = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->context.glx.handle)
|
||||||
|
{
|
||||||
|
glXDestroyContext(_glfw.x11.display, window->context.glx.handle);
|
||||||
|
window->context.glx.handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Initialize GLX
|
||||||
|
//
|
||||||
|
GLFWbool _glfwInitGLX(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char* sonames[] =
|
||||||
|
{
|
||||||
|
#if defined(_GLFW_GLX_LIBRARY)
|
||||||
|
_GLFW_GLX_LIBRARY,
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
|
"libGL-1.so",
|
||||||
|
#else
|
||||||
|
"libGL.so.1",
|
||||||
|
"libGL.so",
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_glfw.glx.handle)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
for (i = 0; sonames[i]; i++)
|
||||||
|
{
|
||||||
|
_glfw.glx.handle = _glfw_dlopen(sonames[i]);
|
||||||
|
if (_glfw.glx.handle)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_glfw.glx.handle)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to load GLX");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.glx.GetFBConfigs =
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigs");
|
||||||
|
_glfw.glx.GetFBConfigAttrib =
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib");
|
||||||
|
_glfw.glx.GetClientString =
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXGetClientString");
|
||||||
|
_glfw.glx.QueryExtension =
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXQueryExtension");
|
||||||
|
_glfw.glx.QueryVersion =
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXQueryVersion");
|
||||||
|
_glfw.glx.DestroyContext =
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXDestroyContext");
|
||||||
|
_glfw.glx.MakeCurrent =
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXMakeCurrent");
|
||||||
|
_glfw.glx.SwapBuffers =
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXSwapBuffers");
|
||||||
|
_glfw.glx.QueryExtensionsString =
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXQueryExtensionsString");
|
||||||
|
_glfw.glx.CreateNewContext =
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXCreateNewContext");
|
||||||
|
_glfw.glx.CreateWindow =
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXCreateWindow");
|
||||||
|
_glfw.glx.DestroyWindow =
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXDestroyWindow");
|
||||||
|
_glfw.glx.GetProcAddress =
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress");
|
||||||
|
_glfw.glx.GetProcAddressARB =
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
|
||||||
|
_glfw.glx.GetVisualFromFBConfig =
|
||||||
|
_glfw_dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
|
||||||
|
|
||||||
|
if (!_glfw.glx.GetFBConfigs ||
|
||||||
|
!_glfw.glx.GetFBConfigAttrib ||
|
||||||
|
!_glfw.glx.GetClientString ||
|
||||||
|
!_glfw.glx.QueryExtension ||
|
||||||
|
!_glfw.glx.QueryVersion ||
|
||||||
|
!_glfw.glx.DestroyContext ||
|
||||||
|
!_glfw.glx.MakeCurrent ||
|
||||||
|
!_glfw.glx.SwapBuffers ||
|
||||||
|
!_glfw.glx.QueryExtensionsString ||
|
||||||
|
!_glfw.glx.CreateNewContext ||
|
||||||
|
!_glfw.glx.CreateWindow ||
|
||||||
|
!_glfw.glx.DestroyWindow ||
|
||||||
|
!_glfw.glx.GetProcAddress ||
|
||||||
|
!_glfw.glx.GetProcAddressARB ||
|
||||||
|
!_glfw.glx.GetVisualFromFBConfig)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"GLX: Failed to load required entry points");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!glXQueryExtension(_glfw.x11.display,
|
||||||
|
&_glfw.glx.errorBase,
|
||||||
|
&_glfw.glx.eventBase))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: GLX extension not found");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!glXQueryVersion(_glfw.x11.display, &_glfw.glx.major, &_glfw.glx.minor))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"GLX: Failed to query GLX version");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.glx.major == 1 && _glfw.glx.minor < 3)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"GLX: GLX version 1.3 is required");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extensionSupportedGLX("GLX_EXT_swap_control"))
|
||||||
|
{
|
||||||
|
_glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)
|
||||||
|
getProcAddressGLX("glXSwapIntervalEXT");
|
||||||
|
|
||||||
|
if (_glfw.glx.SwapIntervalEXT)
|
||||||
|
_glfw.glx.EXT_swap_control = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extensionSupportedGLX("GLX_SGI_swap_control"))
|
||||||
|
{
|
||||||
|
_glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)
|
||||||
|
getProcAddressGLX("glXSwapIntervalSGI");
|
||||||
|
|
||||||
|
if (_glfw.glx.SwapIntervalSGI)
|
||||||
|
_glfw.glx.SGI_swap_control = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extensionSupportedGLX("GLX_MESA_swap_control"))
|
||||||
|
{
|
||||||
|
_glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)
|
||||||
|
getProcAddressGLX("glXSwapIntervalMESA");
|
||||||
|
|
||||||
|
if (_glfw.glx.SwapIntervalMESA)
|
||||||
|
_glfw.glx.MESA_swap_control = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extensionSupportedGLX("GLX_ARB_multisample"))
|
||||||
|
_glfw.glx.ARB_multisample = GLFW_TRUE;
|
||||||
|
|
||||||
|
if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB"))
|
||||||
|
_glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE;
|
||||||
|
|
||||||
|
if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB"))
|
||||||
|
_glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE;
|
||||||
|
|
||||||
|
if (extensionSupportedGLX("GLX_ARB_create_context"))
|
||||||
|
{
|
||||||
|
_glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
|
||||||
|
getProcAddressGLX("glXCreateContextAttribsARB");
|
||||||
|
|
||||||
|
if (_glfw.glx.CreateContextAttribsARB)
|
||||||
|
_glfw.glx.ARB_create_context = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extensionSupportedGLX("GLX_ARB_create_context_robustness"))
|
||||||
|
_glfw.glx.ARB_create_context_robustness = GLFW_TRUE;
|
||||||
|
|
||||||
|
if (extensionSupportedGLX("GLX_ARB_create_context_profile"))
|
||||||
|
_glfw.glx.ARB_create_context_profile = GLFW_TRUE;
|
||||||
|
|
||||||
|
if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
|
||||||
|
_glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE;
|
||||||
|
|
||||||
|
if (extensionSupportedGLX("GLX_ARB_create_context_no_error"))
|
||||||
|
_glfw.glx.ARB_create_context_no_error = GLFW_TRUE;
|
||||||
|
|
||||||
|
if (extensionSupportedGLX("GLX_ARB_context_flush_control"))
|
||||||
|
_glfw.glx.ARB_context_flush_control = GLFW_TRUE;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Terminate GLX
|
||||||
|
//
|
||||||
|
void _glfwTerminateGLX(void)
|
||||||
|
{
|
||||||
|
// NOTE: This function must not call any X11 functions, as it is called
|
||||||
|
// after XCloseDisplay (see _glfwPlatformTerminate for details)
|
||||||
|
|
||||||
|
if (_glfw.glx.handle)
|
||||||
|
{
|
||||||
|
_glfw_dlclose(_glfw.glx.handle);
|
||||||
|
_glfw.glx.handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define setAttrib(a, v) \
|
||||||
|
{ \
|
||||||
|
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||||
|
attribs[index++] = a; \
|
||||||
|
attribs[index++] = v; \
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the OpenGL or OpenGL ES context
|
||||||
|
//
|
||||||
|
GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig)
|
||||||
|
{
|
||||||
|
int attribs[40];
|
||||||
|
GLXFBConfig native = NULL;
|
||||||
|
GLXContext share = NULL;
|
||||||
|
|
||||||
|
if (ctxconfig->share)
|
||||||
|
share = ctxconfig->share->context.glx.handle;
|
||||||
|
|
||||||
|
if (!chooseGLXFBConfig(fbconfig, &native))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
|
"GLX: Failed to find a suitable GLXFBConfig");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
|
{
|
||||||
|
if (!_glfw.glx.ARB_create_context ||
|
||||||
|
!_glfw.glx.ARB_create_context_profile ||
|
||||||
|
!_glfw.glx.EXT_create_context_es2_profile)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"GLX: OpenGL ES requested but GLX_EXT_create_context_es2_profile is unavailable");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->forward)
|
||||||
|
{
|
||||||
|
if (!_glfw.glx.ARB_create_context)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"GLX: Forward compatibility requested but GLX_ARB_create_context_profile is unavailable");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->profile)
|
||||||
|
{
|
||||||
|
if (!_glfw.glx.ARB_create_context ||
|
||||||
|
!_glfw.glx.ARB_create_context_profile)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"GLX: An OpenGL profile requested but GLX_ARB_create_context_profile is unavailable");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwGrabErrorHandlerX11();
|
||||||
|
|
||||||
|
if (_glfw.glx.ARB_create_context)
|
||||||
|
{
|
||||||
|
int index = 0, mask = 0, flags = 0;
|
||||||
|
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
|
{
|
||||||
|
if (ctxconfig->forward)
|
||||||
|
flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
|
||||||
|
|
||||||
|
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
||||||
|
mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||||
|
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
||||||
|
mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
|
||||||
|
|
||||||
|
if (ctxconfig->debug)
|
||||||
|
flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
|
||||||
|
|
||||||
|
if (ctxconfig->robustness)
|
||||||
|
{
|
||||||
|
if (_glfw.glx.ARB_create_context_robustness)
|
||||||
|
{
|
||||||
|
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||||
|
{
|
||||||
|
setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||||
|
GLX_NO_RESET_NOTIFICATION_ARB);
|
||||||
|
}
|
||||||
|
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||||
|
{
|
||||||
|
setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||||
|
GLX_LOSE_CONTEXT_ON_RESET_ARB);
|
||||||
|
}
|
||||||
|
|
||||||
|
flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->release)
|
||||||
|
{
|
||||||
|
if (_glfw.glx.ARB_context_flush_control)
|
||||||
|
{
|
||||||
|
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||||
|
{
|
||||||
|
setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||||
|
GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||||
|
}
|
||||||
|
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||||
|
{
|
||||||
|
setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||||
|
GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->noerror)
|
||||||
|
{
|
||||||
|
if (_glfw.glx.ARB_create_context_no_error)
|
||||||
|
setAttrib(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Only request an explicitly versioned context when necessary, as
|
||||||
|
// explicitly requesting version 1.0 does not always return the
|
||||||
|
// highest version supported by the driver
|
||||||
|
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||||
|
{
|
||||||
|
setAttrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||||
|
setAttrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask)
|
||||||
|
setAttrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||||
|
|
||||||
|
if (flags)
|
||||||
|
setAttrib(GLX_CONTEXT_FLAGS_ARB, flags);
|
||||||
|
|
||||||
|
setAttrib(None, None);
|
||||||
|
|
||||||
|
window->context.glx.handle =
|
||||||
|
_glfw.glx.CreateContextAttribsARB(_glfw.x11.display,
|
||||||
|
native,
|
||||||
|
share,
|
||||||
|
True,
|
||||||
|
attribs);
|
||||||
|
|
||||||
|
// HACK: This is a fallback for broken versions of the Mesa
|
||||||
|
// implementation of GLX_ARB_create_context_profile that fail
|
||||||
|
// default 1.0 context creation with a GLXBadProfileARB error in
|
||||||
|
// violation of the extension spec
|
||||||
|
if (!window->context.glx.handle)
|
||||||
|
{
|
||||||
|
if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&
|
||||||
|
ctxconfig->client == GLFW_OPENGL_API &&
|
||||||
|
ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&
|
||||||
|
ctxconfig->forward == GLFW_FALSE)
|
||||||
|
{
|
||||||
|
window->context.glx.handle =
|
||||||
|
createLegacyContextGLX(window, native, share);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window->context.glx.handle =
|
||||||
|
createLegacyContextGLX(window, native, share);
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwReleaseErrorHandlerX11();
|
||||||
|
|
||||||
|
if (!window->context.glx.handle)
|
||||||
|
{
|
||||||
|
_glfwInputErrorX11(GLFW_VERSION_UNAVAILABLE, "GLX: Failed to create context");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->context.glx.window =
|
||||||
|
glXCreateWindow(_glfw.x11.display, native, window->x11.handle, NULL);
|
||||||
|
if (!window->context.glx.window)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to create window");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->context.makeCurrent = makeContextCurrentGLX;
|
||||||
|
window->context.swapBuffers = swapBuffersGLX;
|
||||||
|
window->context.swapInterval = swapIntervalGLX;
|
||||||
|
window->context.extensionSupported = extensionSupportedGLX;
|
||||||
|
window->context.getProcAddress = getProcAddressGLX;
|
||||||
|
window->context.destroy = destroyContextGLX;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef setAttrib
|
||||||
|
|
||||||
|
// Returns the Visual and depth of the chosen GLXFBConfig
|
||||||
|
//
|
||||||
|
GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig,
|
||||||
|
Visual** visual, int* depth)
|
||||||
|
{
|
||||||
|
GLXFBConfig native;
|
||||||
|
XVisualInfo* result;
|
||||||
|
|
||||||
|
if (!chooseGLXFBConfig(fbconfig, &native))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
|
"GLX: Failed to find a suitable GLXFBConfig");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = glXGetVisualFromFBConfig(_glfw.x11.display, native);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"GLX: Failed to retrieve Visual for GLXFBConfig");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*visual = result->visual;
|
||||||
|
*depth = result->depth;
|
||||||
|
|
||||||
|
XFree(result);
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW native API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (window->context.client == GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window->context.glx.handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(None);
|
||||||
|
|
||||||
|
if (window->context.client == GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window->context.glx.window;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,181 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 GLX - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#define GLX_VENDOR 1
|
||||||
|
#define GLX_RGBA_BIT 0x00000001
|
||||||
|
#define GLX_WINDOW_BIT 0x00000001
|
||||||
|
#define GLX_DRAWABLE_TYPE 0x8010
|
||||||
|
#define GLX_RENDER_TYPE 0x8011
|
||||||
|
#define GLX_RGBA_TYPE 0x8014
|
||||||
|
#define GLX_DOUBLEBUFFER 5
|
||||||
|
#define GLX_STEREO 6
|
||||||
|
#define GLX_AUX_BUFFERS 7
|
||||||
|
#define GLX_RED_SIZE 8
|
||||||
|
#define GLX_GREEN_SIZE 9
|
||||||
|
#define GLX_BLUE_SIZE 10
|
||||||
|
#define GLX_ALPHA_SIZE 11
|
||||||
|
#define GLX_DEPTH_SIZE 12
|
||||||
|
#define GLX_STENCIL_SIZE 13
|
||||||
|
#define GLX_ACCUM_RED_SIZE 14
|
||||||
|
#define GLX_ACCUM_GREEN_SIZE 15
|
||||||
|
#define GLX_ACCUM_BLUE_SIZE 16
|
||||||
|
#define GLX_ACCUM_ALPHA_SIZE 17
|
||||||
|
#define GLX_SAMPLES 0x186a1
|
||||||
|
#define GLX_VISUAL_ID 0x800b
|
||||||
|
|
||||||
|
#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20b2
|
||||||
|
#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
|
||||||
|
#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
|
||||||
|
#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
|
||||||
|
#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
|
||||||
|
#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
|
||||||
|
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||||
|
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||||
|
#define GLX_CONTEXT_FLAGS_ARB 0x2094
|
||||||
|
#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
|
||||||
|
#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
|
||||||
|
#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252
|
||||||
|
#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
|
||||||
|
#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261
|
||||||
|
#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
|
||||||
|
#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
|
||||||
|
#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
|
||||||
|
#define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
|
||||||
|
|
||||||
|
typedef XID GLXWindow;
|
||||||
|
typedef XID GLXDrawable;
|
||||||
|
typedef struct __GLXFBConfig* GLXFBConfig;
|
||||||
|
typedef struct __GLXcontext* GLXContext;
|
||||||
|
typedef void (*__GLXextproc)(void);
|
||||||
|
|
||||||
|
typedef int (*PFNGLXGETFBCONFIGATTRIBPROC)(Display*,GLXFBConfig,int,int*);
|
||||||
|
typedef const char* (*PFNGLXGETCLIENTSTRINGPROC)(Display*,int);
|
||||||
|
typedef Bool (*PFNGLXQUERYEXTENSIONPROC)(Display*,int*,int*);
|
||||||
|
typedef Bool (*PFNGLXQUERYVERSIONPROC)(Display*,int*,int*);
|
||||||
|
typedef void (*PFNGLXDESTROYCONTEXTPROC)(Display*,GLXContext);
|
||||||
|
typedef Bool (*PFNGLXMAKECURRENTPROC)(Display*,GLXDrawable,GLXContext);
|
||||||
|
typedef void (*PFNGLXSWAPBUFFERSPROC)(Display*,GLXDrawable);
|
||||||
|
typedef const char* (*PFNGLXQUERYEXTENSIONSSTRINGPROC)(Display*,int);
|
||||||
|
typedef GLXFBConfig* (*PFNGLXGETFBCONFIGSPROC)(Display*,int,int*);
|
||||||
|
typedef GLXContext (*PFNGLXCREATENEWCONTEXTPROC)(Display*,GLXFBConfig,int,GLXContext,Bool);
|
||||||
|
typedef __GLXextproc (* PFNGLXGETPROCADDRESSPROC)(const GLubyte *procName);
|
||||||
|
typedef void (*PFNGLXSWAPINTERVALEXTPROC)(Display*,GLXDrawable,int);
|
||||||
|
typedef XVisualInfo* (*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display*,GLXFBConfig);
|
||||||
|
typedef GLXWindow (*PFNGLXCREATEWINDOWPROC)(Display*,GLXFBConfig,Window,const int*);
|
||||||
|
typedef void (*PFNGLXDESTROYWINDOWPROC)(Display*,GLXWindow);
|
||||||
|
|
||||||
|
typedef int (*PFNGLXSWAPINTERVALMESAPROC)(int);
|
||||||
|
typedef int (*PFNGLXSWAPINTERVALSGIPROC)(int);
|
||||||
|
typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLXContext,Bool,const int*);
|
||||||
|
|
||||||
|
// libGL.so function pointer typedefs
|
||||||
|
#define glXGetFBConfigs _glfw.glx.GetFBConfigs
|
||||||
|
#define glXGetFBConfigAttrib _glfw.glx.GetFBConfigAttrib
|
||||||
|
#define glXGetClientString _glfw.glx.GetClientString
|
||||||
|
#define glXQueryExtension _glfw.glx.QueryExtension
|
||||||
|
#define glXQueryVersion _glfw.glx.QueryVersion
|
||||||
|
#define glXDestroyContext _glfw.glx.DestroyContext
|
||||||
|
#define glXMakeCurrent _glfw.glx.MakeCurrent
|
||||||
|
#define glXSwapBuffers _glfw.glx.SwapBuffers
|
||||||
|
#define glXQueryExtensionsString _glfw.glx.QueryExtensionsString
|
||||||
|
#define glXCreateNewContext _glfw.glx.CreateNewContext
|
||||||
|
#define glXGetVisualFromFBConfig _glfw.glx.GetVisualFromFBConfig
|
||||||
|
#define glXCreateWindow _glfw.glx.CreateWindow
|
||||||
|
#define glXDestroyWindow _glfw.glx.DestroyWindow
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX glx
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx
|
||||||
|
|
||||||
|
|
||||||
|
// GLX-specific per-context data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWcontextGLX
|
||||||
|
{
|
||||||
|
GLXContext handle;
|
||||||
|
GLXWindow window;
|
||||||
|
|
||||||
|
} _GLFWcontextGLX;
|
||||||
|
|
||||||
|
// GLX-specific global data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWlibraryGLX
|
||||||
|
{
|
||||||
|
int major, minor;
|
||||||
|
int eventBase;
|
||||||
|
int errorBase;
|
||||||
|
|
||||||
|
// dlopen handle for libGL.so.1
|
||||||
|
void* handle;
|
||||||
|
|
||||||
|
// GLX 1.3 functions
|
||||||
|
PFNGLXGETFBCONFIGSPROC GetFBConfigs;
|
||||||
|
PFNGLXGETFBCONFIGATTRIBPROC GetFBConfigAttrib;
|
||||||
|
PFNGLXGETCLIENTSTRINGPROC GetClientString;
|
||||||
|
PFNGLXQUERYEXTENSIONPROC QueryExtension;
|
||||||
|
PFNGLXQUERYVERSIONPROC QueryVersion;
|
||||||
|
PFNGLXDESTROYCONTEXTPROC DestroyContext;
|
||||||
|
PFNGLXMAKECURRENTPROC MakeCurrent;
|
||||||
|
PFNGLXSWAPBUFFERSPROC SwapBuffers;
|
||||||
|
PFNGLXQUERYEXTENSIONSSTRINGPROC QueryExtensionsString;
|
||||||
|
PFNGLXCREATENEWCONTEXTPROC CreateNewContext;
|
||||||
|
PFNGLXGETVISUALFROMFBCONFIGPROC GetVisualFromFBConfig;
|
||||||
|
PFNGLXCREATEWINDOWPROC CreateWindow;
|
||||||
|
PFNGLXDESTROYWINDOWPROC DestroyWindow;
|
||||||
|
|
||||||
|
// GLX 1.4 and extension functions
|
||||||
|
PFNGLXGETPROCADDRESSPROC GetProcAddress;
|
||||||
|
PFNGLXGETPROCADDRESSPROC GetProcAddressARB;
|
||||||
|
PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI;
|
||||||
|
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
|
||||||
|
PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
|
||||||
|
PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
||||||
|
GLFWbool SGI_swap_control;
|
||||||
|
GLFWbool EXT_swap_control;
|
||||||
|
GLFWbool MESA_swap_control;
|
||||||
|
GLFWbool ARB_multisample;
|
||||||
|
GLFWbool ARB_framebuffer_sRGB;
|
||||||
|
GLFWbool EXT_framebuffer_sRGB;
|
||||||
|
GLFWbool ARB_create_context;
|
||||||
|
GLFWbool ARB_create_context_profile;
|
||||||
|
GLFWbool ARB_create_context_robustness;
|
||||||
|
GLFWbool EXT_create_context_es2_profile;
|
||||||
|
GLFWbool ARB_create_context_no_error;
|
||||||
|
GLFWbool ARB_context_flush_control;
|
||||||
|
|
||||||
|
} _GLFWlibraryGLX;
|
||||||
|
|
||||||
|
GLFWbool _glfwInitGLX(void);
|
||||||
|
void _glfwTerminateGLX(void);
|
||||||
|
GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig);
|
||||||
|
void _glfwDestroyContextGLX(_GLFWwindow* window);
|
||||||
|
GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig,
|
||||||
|
Visual** visual, int* depth);
|
||||||
|
|
|
@ -0,0 +1,340 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
#include "mappings.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
// The global variables below comprise all mutable global data in GLFW
|
||||||
|
//
|
||||||
|
// Any other global variable is a bug
|
||||||
|
|
||||||
|
// Global state shared between compilation units of GLFW
|
||||||
|
//
|
||||||
|
_GLFWlibrary _glfw = { GLFW_FALSE };
|
||||||
|
|
||||||
|
// These are outside of _glfw so they can be used before initialization and
|
||||||
|
// after termination
|
||||||
|
//
|
||||||
|
static _GLFWerror _glfwMainThreadError;
|
||||||
|
static GLFWerrorfun _glfwErrorCallback;
|
||||||
|
static _GLFWinitconfig _glfwInitHints =
|
||||||
|
{
|
||||||
|
GLFW_TRUE, // hat buttons
|
||||||
|
{
|
||||||
|
GLFW_TRUE, // macOS menu bar
|
||||||
|
GLFW_TRUE // macOS bundle chdir
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Terminate the library
|
||||||
|
//
|
||||||
|
static void terminate(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
|
||||||
|
|
||||||
|
while (_glfw.windowListHead)
|
||||||
|
glfwDestroyWindow((GLFWwindow*) _glfw.windowListHead);
|
||||||
|
|
||||||
|
while (_glfw.cursorListHead)
|
||||||
|
glfwDestroyCursor((GLFWcursor*) _glfw.cursorListHead);
|
||||||
|
|
||||||
|
for (i = 0; i < _glfw.monitorCount; i++)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = _glfw.monitors[i];
|
||||||
|
if (monitor->originalRamp.size)
|
||||||
|
_glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
|
||||||
|
_glfwFreeMonitor(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(_glfw.monitors);
|
||||||
|
_glfw.monitors = NULL;
|
||||||
|
_glfw.monitorCount = 0;
|
||||||
|
|
||||||
|
free(_glfw.mappings);
|
||||||
|
_glfw.mappings = NULL;
|
||||||
|
_glfw.mappingCount = 0;
|
||||||
|
|
||||||
|
_glfwTerminateVulkan();
|
||||||
|
_glfwPlatformTerminate();
|
||||||
|
|
||||||
|
_glfw.initialized = GLFW_FALSE;
|
||||||
|
|
||||||
|
while (_glfw.errorListHead)
|
||||||
|
{
|
||||||
|
_GLFWerror* error = _glfw.errorListHead;
|
||||||
|
_glfw.errorListHead = error->next;
|
||||||
|
free(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPlatformDestroyTls(&_glfw.contextSlot);
|
||||||
|
_glfwPlatformDestroyTls(&_glfw.errorSlot);
|
||||||
|
_glfwPlatformDestroyMutex(&_glfw.errorLock);
|
||||||
|
|
||||||
|
memset(&_glfw, 0, sizeof(_glfw));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
char* _glfw_strdup(const char* source)
|
||||||
|
{
|
||||||
|
const size_t length = strlen(source);
|
||||||
|
char* result = calloc(length + 1, 1);
|
||||||
|
strcpy(result, source);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float _glfw_fminf(float a, float b)
|
||||||
|
{
|
||||||
|
if (a != a)
|
||||||
|
return b;
|
||||||
|
else if (b != b)
|
||||||
|
return a;
|
||||||
|
else if (a < b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
float _glfw_fmaxf(float a, float b)
|
||||||
|
{
|
||||||
|
if (a != a)
|
||||||
|
return b;
|
||||||
|
else if (b != b)
|
||||||
|
return a;
|
||||||
|
else if (a > b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW event API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Notifies shared code of an error
|
||||||
|
//
|
||||||
|
void _glfwInputError(int code, const char* format, ...)
|
||||||
|
{
|
||||||
|
_GLFWerror* error;
|
||||||
|
char description[_GLFW_MESSAGE_SIZE];
|
||||||
|
|
||||||
|
if (format)
|
||||||
|
{
|
||||||
|
va_list vl;
|
||||||
|
|
||||||
|
va_start(vl, format);
|
||||||
|
vsnprintf(description, sizeof(description), format, vl);
|
||||||
|
va_end(vl);
|
||||||
|
|
||||||
|
description[sizeof(description) - 1] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (code == GLFW_NOT_INITIALIZED)
|
||||||
|
strcpy(description, "The GLFW library is not initialized");
|
||||||
|
else if (code == GLFW_NO_CURRENT_CONTEXT)
|
||||||
|
strcpy(description, "There is no current context");
|
||||||
|
else if (code == GLFW_INVALID_ENUM)
|
||||||
|
strcpy(description, "Invalid argument for enum parameter");
|
||||||
|
else if (code == GLFW_INVALID_VALUE)
|
||||||
|
strcpy(description, "Invalid value for parameter");
|
||||||
|
else if (code == GLFW_OUT_OF_MEMORY)
|
||||||
|
strcpy(description, "Out of memory");
|
||||||
|
else if (code == GLFW_API_UNAVAILABLE)
|
||||||
|
strcpy(description, "The requested API is unavailable");
|
||||||
|
else if (code == GLFW_VERSION_UNAVAILABLE)
|
||||||
|
strcpy(description, "The requested API version is unavailable");
|
||||||
|
else if (code == GLFW_PLATFORM_ERROR)
|
||||||
|
strcpy(description, "A platform-specific error occurred");
|
||||||
|
else if (code == GLFW_FORMAT_UNAVAILABLE)
|
||||||
|
strcpy(description, "The requested format is unavailable");
|
||||||
|
else if (code == GLFW_NO_WINDOW_CONTEXT)
|
||||||
|
strcpy(description, "The specified window has no context");
|
||||||
|
else
|
||||||
|
strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.initialized)
|
||||||
|
{
|
||||||
|
error = _glfwPlatformGetTls(&_glfw.errorSlot);
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
error = calloc(1, sizeof(_GLFWerror));
|
||||||
|
_glfwPlatformSetTls(&_glfw.errorSlot, error);
|
||||||
|
_glfwPlatformLockMutex(&_glfw.errorLock);
|
||||||
|
error->next = _glfw.errorListHead;
|
||||||
|
_glfw.errorListHead = error;
|
||||||
|
_glfwPlatformUnlockMutex(&_glfw.errorLock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error = &_glfwMainThreadError;
|
||||||
|
|
||||||
|
error->code = code;
|
||||||
|
strcpy(error->description, description);
|
||||||
|
|
||||||
|
if (_glfwErrorCallback)
|
||||||
|
_glfwErrorCallback(code, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW public API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI int glfwInit(void)
|
||||||
|
{
|
||||||
|
if (_glfw.initialized)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
memset(&_glfw, 0, sizeof(_glfw));
|
||||||
|
_glfw.hints.init = _glfwInitHints;
|
||||||
|
|
||||||
|
if (!_glfwPlatformInit())
|
||||||
|
{
|
||||||
|
terminate();
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
|
||||||
|
!_glfwPlatformCreateTls(&_glfw.errorSlot) ||
|
||||||
|
!_glfwPlatformCreateTls(&_glfw.contextSlot))
|
||||||
|
{
|
||||||
|
terminate();
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
|
||||||
|
|
||||||
|
_glfw.initialized = GLFW_TRUE;
|
||||||
|
_glfw.timer.offset = _glfwPlatformGetTimerValue();
|
||||||
|
|
||||||
|
glfwDefaultWindowHints();
|
||||||
|
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; _glfwDefaultMappings[i]; i++)
|
||||||
|
{
|
||||||
|
if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i]))
|
||||||
|
{
|
||||||
|
terminate();
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwTerminate(void)
|
||||||
|
{
|
||||||
|
if (!_glfw.initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwInitHint(int hint, int value)
|
||||||
|
{
|
||||||
|
switch (hint)
|
||||||
|
{
|
||||||
|
case GLFW_JOYSTICK_HAT_BUTTONS:
|
||||||
|
_glfwInitHints.hatButtons = value;
|
||||||
|
return;
|
||||||
|
case GLFW_COCOA_CHDIR_RESOURCES:
|
||||||
|
_glfwInitHints.ns.chdir = value;
|
||||||
|
return;
|
||||||
|
case GLFW_COCOA_MENUBAR:
|
||||||
|
_glfwInitHints.ns.menubar = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
|
"Invalid init hint 0x%08X", hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
|
||||||
|
{
|
||||||
|
if (major != NULL)
|
||||||
|
*major = GLFW_VERSION_MAJOR;
|
||||||
|
if (minor != NULL)
|
||||||
|
*minor = GLFW_VERSION_MINOR;
|
||||||
|
if (rev != NULL)
|
||||||
|
*rev = GLFW_VERSION_REVISION;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const char* glfwGetVersionString(void)
|
||||||
|
{
|
||||||
|
return _glfwPlatformGetVersionString();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwGetError(const char** description)
|
||||||
|
{
|
||||||
|
_GLFWerror* error;
|
||||||
|
int code = GLFW_NO_ERROR;
|
||||||
|
|
||||||
|
if (description)
|
||||||
|
*description = NULL;
|
||||||
|
|
||||||
|
if (_glfw.initialized)
|
||||||
|
error = _glfwPlatformGetTls(&_glfw.errorSlot);
|
||||||
|
else
|
||||||
|
error = &_glfwMainThreadError;
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
code = error->code;
|
||||||
|
error->code = GLFW_NO_ERROR;
|
||||||
|
if (description && code)
|
||||||
|
*description = error->description;
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,778 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if defined(_GLFW_USE_CONFIG_H)
|
||||||
|
#include "glfw_config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GLFW_INCLUDE_GLCOREARB) || \
|
||||||
|
defined(GLFW_INCLUDE_ES1) || \
|
||||||
|
defined(GLFW_INCLUDE_ES2) || \
|
||||||
|
defined(GLFW_INCLUDE_ES3) || \
|
||||||
|
defined(GLFW_INCLUDE_ES31) || \
|
||||||
|
defined(GLFW_INCLUDE_ES32) || \
|
||||||
|
defined(GLFW_INCLUDE_NONE) || \
|
||||||
|
defined(GLFW_INCLUDE_GLEXT) || \
|
||||||
|
defined(GLFW_INCLUDE_GLU) || \
|
||||||
|
defined(GLFW_INCLUDE_VULKAN) || \
|
||||||
|
defined(GLFW_DLL)
|
||||||
|
#error "You must not define any header option macros when compiling GLFW"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define GLFW_INCLUDE_NONE
|
||||||
|
#include "../include/GLFW/glfw3.h"
|
||||||
|
|
||||||
|
#define _GLFW_INSERT_FIRST 0
|
||||||
|
#define _GLFW_INSERT_LAST 1
|
||||||
|
|
||||||
|
#define _GLFW_POLL_PRESENCE 0
|
||||||
|
#define _GLFW_POLL_AXES 1
|
||||||
|
#define _GLFW_POLL_BUTTONS 2
|
||||||
|
#define _GLFW_POLL_ALL (_GLFW_POLL_AXES | _GLFW_POLL_BUTTONS)
|
||||||
|
|
||||||
|
#define _GLFW_MESSAGE_SIZE 1024
|
||||||
|
|
||||||
|
typedef int GLFWbool;
|
||||||
|
|
||||||
|
typedef struct _GLFWerror _GLFWerror;
|
||||||
|
typedef struct _GLFWinitconfig _GLFWinitconfig;
|
||||||
|
typedef struct _GLFWwndconfig _GLFWwndconfig;
|
||||||
|
typedef struct _GLFWctxconfig _GLFWctxconfig;
|
||||||
|
typedef struct _GLFWfbconfig _GLFWfbconfig;
|
||||||
|
typedef struct _GLFWcontext _GLFWcontext;
|
||||||
|
typedef struct _GLFWwindow _GLFWwindow;
|
||||||
|
typedef struct _GLFWlibrary _GLFWlibrary;
|
||||||
|
typedef struct _GLFWmonitor _GLFWmonitor;
|
||||||
|
typedef struct _GLFWcursor _GLFWcursor;
|
||||||
|
typedef struct _GLFWmapelement _GLFWmapelement;
|
||||||
|
typedef struct _GLFWmapping _GLFWmapping;
|
||||||
|
typedef struct _GLFWjoystick _GLFWjoystick;
|
||||||
|
typedef struct _GLFWtls _GLFWtls;
|
||||||
|
typedef struct _GLFWmutex _GLFWmutex;
|
||||||
|
|
||||||
|
typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*);
|
||||||
|
typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*);
|
||||||
|
typedef void (* _GLFWswapintervalfun)(int);
|
||||||
|
typedef int (* _GLFWextensionsupportedfun)(const char*);
|
||||||
|
typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*);
|
||||||
|
typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
|
||||||
|
|
||||||
|
#define GL_VERSION 0x1f02
|
||||||
|
#define GL_NONE 0
|
||||||
|
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||||
|
#define GL_UNSIGNED_BYTE 0x1401
|
||||||
|
#define GL_EXTENSIONS 0x1f03
|
||||||
|
#define GL_NUM_EXTENSIONS 0x821d
|
||||||
|
#define GL_CONTEXT_FLAGS 0x821e
|
||||||
|
#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
|
||||||
|
#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
|
||||||
|
#define GL_CONTEXT_PROFILE_MASK 0x9126
|
||||||
|
#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
|
||||||
|
#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
|
||||||
|
#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
|
||||||
|
#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
|
||||||
|
#define GL_NO_RESET_NOTIFICATION_ARB 0x8261
|
||||||
|
#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82fb
|
||||||
|
#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82fc
|
||||||
|
#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008
|
||||||
|
|
||||||
|
typedef int GLint;
|
||||||
|
typedef unsigned int GLuint;
|
||||||
|
typedef unsigned int GLenum;
|
||||||
|
typedef unsigned int GLbitfield;
|
||||||
|
typedef unsigned char GLubyte;
|
||||||
|
|
||||||
|
typedef void (APIENTRY * PFNGLCLEARPROC)(GLbitfield);
|
||||||
|
typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGPROC)(GLenum);
|
||||||
|
typedef void (APIENTRY * PFNGLGETINTEGERVPROC)(GLenum,GLint*);
|
||||||
|
typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint);
|
||||||
|
|
||||||
|
#define VK_NULL_HANDLE 0
|
||||||
|
|
||||||
|
typedef void* VkInstance;
|
||||||
|
typedef void* VkPhysicalDevice;
|
||||||
|
typedef uint64_t VkSurfaceKHR;
|
||||||
|
typedef uint32_t VkFlags;
|
||||||
|
typedef uint32_t VkBool32;
|
||||||
|
|
||||||
|
typedef enum VkStructureType
|
||||||
|
{
|
||||||
|
VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000,
|
||||||
|
VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000,
|
||||||
|
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
|
||||||
|
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
|
||||||
|
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
|
||||||
|
VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000,
|
||||||
|
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
|
||||||
|
} VkStructureType;
|
||||||
|
|
||||||
|
typedef enum VkResult
|
||||||
|
{
|
||||||
|
VK_SUCCESS = 0,
|
||||||
|
VK_NOT_READY = 1,
|
||||||
|
VK_TIMEOUT = 2,
|
||||||
|
VK_EVENT_SET = 3,
|
||||||
|
VK_EVENT_RESET = 4,
|
||||||
|
VK_INCOMPLETE = 5,
|
||||||
|
VK_ERROR_OUT_OF_HOST_MEMORY = -1,
|
||||||
|
VK_ERROR_OUT_OF_DEVICE_MEMORY = -2,
|
||||||
|
VK_ERROR_INITIALIZATION_FAILED = -3,
|
||||||
|
VK_ERROR_DEVICE_LOST = -4,
|
||||||
|
VK_ERROR_MEMORY_MAP_FAILED = -5,
|
||||||
|
VK_ERROR_LAYER_NOT_PRESENT = -6,
|
||||||
|
VK_ERROR_EXTENSION_NOT_PRESENT = -7,
|
||||||
|
VK_ERROR_FEATURE_NOT_PRESENT = -8,
|
||||||
|
VK_ERROR_INCOMPATIBLE_DRIVER = -9,
|
||||||
|
VK_ERROR_TOO_MANY_OBJECTS = -10,
|
||||||
|
VK_ERROR_FORMAT_NOT_SUPPORTED = -11,
|
||||||
|
VK_ERROR_SURFACE_LOST_KHR = -1000000000,
|
||||||
|
VK_SUBOPTIMAL_KHR = 1000001003,
|
||||||
|
VK_ERROR_OUT_OF_DATE_KHR = -1000001004,
|
||||||
|
VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
|
||||||
|
VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001,
|
||||||
|
VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
|
||||||
|
VK_RESULT_MAX_ENUM = 0x7FFFFFFF
|
||||||
|
} VkResult;
|
||||||
|
|
||||||
|
typedef struct VkAllocationCallbacks VkAllocationCallbacks;
|
||||||
|
|
||||||
|
typedef struct VkExtensionProperties
|
||||||
|
{
|
||||||
|
char extensionName[256];
|
||||||
|
uint32_t specVersion;
|
||||||
|
} VkExtensionProperties;
|
||||||
|
|
||||||
|
typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
||||||
|
|
||||||
|
#if defined(_GLFW_VULKAN_STATIC)
|
||||||
|
PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance,const char*);
|
||||||
|
VkResult vkEnumerateInstanceExtensionProperties(const char*,uint32_t*,VkExtensionProperties*);
|
||||||
|
#else
|
||||||
|
typedef PFN_vkVoidFunction (APIENTRY * PFN_vkGetInstanceProcAddr)(VkInstance,const char*);
|
||||||
|
typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const char*,uint32_t*,VkExtensionProperties*);
|
||||||
|
#define vkEnumerateInstanceExtensionProperties _glfw.vk.EnumerateInstanceExtensionProperties
|
||||||
|
#define vkGetInstanceProcAddr _glfw.vk.GetInstanceProcAddr
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_GLFW_COCOA)
|
||||||
|
#include "cocoa_platform.h"
|
||||||
|
#elif defined(_GLFW_WIN32)
|
||||||
|
#include "win32_platform.h"
|
||||||
|
#elif defined(_GLFW_X11)
|
||||||
|
#include "x11_platform.h"
|
||||||
|
#elif defined(_GLFW_WAYLAND)
|
||||||
|
#include "wl_platform.h"
|
||||||
|
#elif defined(_GLFW_OSMESA)
|
||||||
|
#include "null_platform.h"
|
||||||
|
#else
|
||||||
|
#error "No supported window creation API selected"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Constructs a version number string from the public header macros
|
||||||
|
#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r
|
||||||
|
#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r)
|
||||||
|
#define _GLFW_VERSION_NUMBER _GLFW_MAKE_VERSION(GLFW_VERSION_MAJOR, \
|
||||||
|
GLFW_VERSION_MINOR, \
|
||||||
|
GLFW_VERSION_REVISION)
|
||||||
|
|
||||||
|
// Checks for whether the library has been initialized
|
||||||
|
#define _GLFW_REQUIRE_INIT() \
|
||||||
|
if (!_glfw.initialized) \
|
||||||
|
{ \
|
||||||
|
_glfwInputError(GLFW_NOT_INITIALIZED, NULL); \
|
||||||
|
return; \
|
||||||
|
}
|
||||||
|
#define _GLFW_REQUIRE_INIT_OR_RETURN(x) \
|
||||||
|
if (!_glfw.initialized) \
|
||||||
|
{ \
|
||||||
|
_glfwInputError(GLFW_NOT_INITIALIZED, NULL); \
|
||||||
|
return x; \
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swaps the provided pointers
|
||||||
|
#define _GLFW_SWAP_POINTERS(x, y) \
|
||||||
|
{ \
|
||||||
|
void* t; \
|
||||||
|
t = x; \
|
||||||
|
x = y; \
|
||||||
|
y = t; \
|
||||||
|
}
|
||||||
|
|
||||||
|
// Per-thread error structure
|
||||||
|
//
|
||||||
|
struct _GLFWerror
|
||||||
|
{
|
||||||
|
_GLFWerror* next;
|
||||||
|
int code;
|
||||||
|
char description[_GLFW_MESSAGE_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialization configuration
|
||||||
|
//
|
||||||
|
// Parameters relating to the initialization of the library
|
||||||
|
//
|
||||||
|
struct _GLFWinitconfig
|
||||||
|
{
|
||||||
|
GLFWbool hatButtons;
|
||||||
|
struct {
|
||||||
|
GLFWbool menubar;
|
||||||
|
GLFWbool chdir;
|
||||||
|
} ns;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Window configuration
|
||||||
|
//
|
||||||
|
// Parameters relating to the creation of the window but not directly related
|
||||||
|
// to the framebuffer. This is used to pass window creation parameters from
|
||||||
|
// shared code to the platform API.
|
||||||
|
//
|
||||||
|
struct _GLFWwndconfig
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
const char* title;
|
||||||
|
GLFWbool resizable;
|
||||||
|
GLFWbool visible;
|
||||||
|
GLFWbool decorated;
|
||||||
|
GLFWbool focused;
|
||||||
|
GLFWbool autoIconify;
|
||||||
|
GLFWbool floating;
|
||||||
|
GLFWbool maximized;
|
||||||
|
GLFWbool centerCursor;
|
||||||
|
GLFWbool focusOnShow;
|
||||||
|
GLFWbool scaleToMonitor;
|
||||||
|
struct {
|
||||||
|
GLFWbool retina;
|
||||||
|
char frameName[256];
|
||||||
|
} ns;
|
||||||
|
struct {
|
||||||
|
char className[256];
|
||||||
|
char instanceName[256];
|
||||||
|
} x11;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Context configuration
|
||||||
|
//
|
||||||
|
// Parameters relating to the creation of the context but not directly related
|
||||||
|
// to the framebuffer. This is used to pass context creation parameters from
|
||||||
|
// shared code to the platform API.
|
||||||
|
//
|
||||||
|
struct _GLFWctxconfig
|
||||||
|
{
|
||||||
|
int client;
|
||||||
|
int source;
|
||||||
|
int major;
|
||||||
|
int minor;
|
||||||
|
GLFWbool forward;
|
||||||
|
GLFWbool debug;
|
||||||
|
GLFWbool noerror;
|
||||||
|
int profile;
|
||||||
|
int robustness;
|
||||||
|
int release;
|
||||||
|
_GLFWwindow* share;
|
||||||
|
struct {
|
||||||
|
GLFWbool offline;
|
||||||
|
} nsgl;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Framebuffer configuration
|
||||||
|
//
|
||||||
|
// This describes buffers and their sizes. It also contains
|
||||||
|
// a platform-specific ID used to map back to the backend API object.
|
||||||
|
//
|
||||||
|
// It is used to pass framebuffer parameters from shared code to the platform
|
||||||
|
// API and also to enumerate and select available framebuffer configs.
|
||||||
|
//
|
||||||
|
struct _GLFWfbconfig
|
||||||
|
{
|
||||||
|
int redBits;
|
||||||
|
int greenBits;
|
||||||
|
int blueBits;
|
||||||
|
int alphaBits;
|
||||||
|
int depthBits;
|
||||||
|
int stencilBits;
|
||||||
|
int accumRedBits;
|
||||||
|
int accumGreenBits;
|
||||||
|
int accumBlueBits;
|
||||||
|
int accumAlphaBits;
|
||||||
|
int auxBuffers;
|
||||||
|
GLFWbool stereo;
|
||||||
|
int samples;
|
||||||
|
GLFWbool sRGB;
|
||||||
|
GLFWbool doublebuffer;
|
||||||
|
GLFWbool transparent;
|
||||||
|
uintptr_t handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Context structure
|
||||||
|
//
|
||||||
|
struct _GLFWcontext
|
||||||
|
{
|
||||||
|
int client;
|
||||||
|
int source;
|
||||||
|
int major, minor, revision;
|
||||||
|
GLFWbool forward, debug, noerror;
|
||||||
|
int profile;
|
||||||
|
int robustness;
|
||||||
|
int release;
|
||||||
|
|
||||||
|
PFNGLGETSTRINGIPROC GetStringi;
|
||||||
|
PFNGLGETINTEGERVPROC GetIntegerv;
|
||||||
|
PFNGLGETSTRINGPROC GetString;
|
||||||
|
|
||||||
|
_GLFWmakecontextcurrentfun makeCurrent;
|
||||||
|
_GLFWswapbuffersfun swapBuffers;
|
||||||
|
_GLFWswapintervalfun swapInterval;
|
||||||
|
_GLFWextensionsupportedfun extensionSupported;
|
||||||
|
_GLFWgetprocaddressfun getProcAddress;
|
||||||
|
_GLFWdestroycontextfun destroy;
|
||||||
|
|
||||||
|
// This is defined in the context API's context.h
|
||||||
|
_GLFW_PLATFORM_CONTEXT_STATE;
|
||||||
|
// This is defined in egl_context.h
|
||||||
|
_GLFW_EGL_CONTEXT_STATE;
|
||||||
|
// This is defined in osmesa_context.h
|
||||||
|
_GLFW_OSMESA_CONTEXT_STATE;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Window and context structure
|
||||||
|
//
|
||||||
|
struct _GLFWwindow
|
||||||
|
{
|
||||||
|
struct _GLFWwindow* next;
|
||||||
|
|
||||||
|
// Window settings and state
|
||||||
|
GLFWbool resizable;
|
||||||
|
GLFWbool decorated;
|
||||||
|
GLFWbool autoIconify;
|
||||||
|
GLFWbool floating;
|
||||||
|
GLFWbool focusOnShow;
|
||||||
|
GLFWbool shouldClose;
|
||||||
|
void* userPointer;
|
||||||
|
GLFWvidmode videoMode;
|
||||||
|
_GLFWmonitor* monitor;
|
||||||
|
_GLFWcursor* cursor;
|
||||||
|
|
||||||
|
int minwidth, minheight;
|
||||||
|
int maxwidth, maxheight;
|
||||||
|
int numer, denom;
|
||||||
|
|
||||||
|
GLFWbool stickyKeys;
|
||||||
|
GLFWbool stickyMouseButtons;
|
||||||
|
GLFWbool lockKeyMods;
|
||||||
|
int cursorMode;
|
||||||
|
char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
|
||||||
|
char keys[GLFW_KEY_LAST + 1];
|
||||||
|
// Virtual cursor position when cursor is disabled
|
||||||
|
double virtualCursorPosX, virtualCursorPosY;
|
||||||
|
GLFWbool rawMouseMotion;
|
||||||
|
|
||||||
|
_GLFWcontext context;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
GLFWwindowposfun pos;
|
||||||
|
GLFWwindowsizefun size;
|
||||||
|
GLFWwindowclosefun close;
|
||||||
|
GLFWwindowrefreshfun refresh;
|
||||||
|
GLFWwindowfocusfun focus;
|
||||||
|
GLFWwindowiconifyfun iconify;
|
||||||
|
GLFWwindowmaximizefun maximize;
|
||||||
|
GLFWframebuffersizefun fbsize;
|
||||||
|
GLFWwindowcontentscalefun scale;
|
||||||
|
GLFWmousebuttonfun mouseButton;
|
||||||
|
GLFWcursorposfun cursorPos;
|
||||||
|
GLFWcursorenterfun cursorEnter;
|
||||||
|
GLFWscrollfun scroll;
|
||||||
|
GLFWkeyfun key;
|
||||||
|
GLFWcharfun character;
|
||||||
|
GLFWcharmodsfun charmods;
|
||||||
|
GLFWdropfun drop;
|
||||||
|
} callbacks;
|
||||||
|
|
||||||
|
// This is defined in the window API's platform.h
|
||||||
|
_GLFW_PLATFORM_WINDOW_STATE;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Monitor structure
|
||||||
|
//
|
||||||
|
struct _GLFWmonitor
|
||||||
|
{
|
||||||
|
char* name;
|
||||||
|
void* userPointer;
|
||||||
|
|
||||||
|
// Physical dimensions in millimeters.
|
||||||
|
int widthMM, heightMM;
|
||||||
|
|
||||||
|
// The window whose video mode is current on this monitor
|
||||||
|
_GLFWwindow* window;
|
||||||
|
|
||||||
|
GLFWvidmode* modes;
|
||||||
|
int modeCount;
|
||||||
|
GLFWvidmode currentMode;
|
||||||
|
|
||||||
|
GLFWgammaramp originalRamp;
|
||||||
|
GLFWgammaramp currentRamp;
|
||||||
|
|
||||||
|
// This is defined in the window API's platform.h
|
||||||
|
_GLFW_PLATFORM_MONITOR_STATE;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cursor structure
|
||||||
|
//
|
||||||
|
struct _GLFWcursor
|
||||||
|
{
|
||||||
|
_GLFWcursor* next;
|
||||||
|
|
||||||
|
// This is defined in the window API's platform.h
|
||||||
|
_GLFW_PLATFORM_CURSOR_STATE;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gamepad mapping element structure
|
||||||
|
//
|
||||||
|
struct _GLFWmapelement
|
||||||
|
{
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t index;
|
||||||
|
int8_t axisScale;
|
||||||
|
int8_t axisOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gamepad mapping structure
|
||||||
|
//
|
||||||
|
struct _GLFWmapping
|
||||||
|
{
|
||||||
|
char name[128];
|
||||||
|
char guid[33];
|
||||||
|
_GLFWmapelement buttons[15];
|
||||||
|
_GLFWmapelement axes[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Joystick structure
|
||||||
|
//
|
||||||
|
struct _GLFWjoystick
|
||||||
|
{
|
||||||
|
GLFWbool present;
|
||||||
|
float* axes;
|
||||||
|
int axisCount;
|
||||||
|
unsigned char* buttons;
|
||||||
|
int buttonCount;
|
||||||
|
unsigned char* hats;
|
||||||
|
int hatCount;
|
||||||
|
char* name;
|
||||||
|
void* userPointer;
|
||||||
|
char guid[33];
|
||||||
|
_GLFWmapping* mapping;
|
||||||
|
|
||||||
|
// This is defined in the joystick API's joystick.h
|
||||||
|
_GLFW_PLATFORM_JOYSTICK_STATE;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Thread local storage structure
|
||||||
|
//
|
||||||
|
struct _GLFWtls
|
||||||
|
{
|
||||||
|
// This is defined in the platform's thread.h
|
||||||
|
_GLFW_PLATFORM_TLS_STATE;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mutex structure
|
||||||
|
//
|
||||||
|
struct _GLFWmutex
|
||||||
|
{
|
||||||
|
// This is defined in the platform's thread.h
|
||||||
|
_GLFW_PLATFORM_MUTEX_STATE;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Library global data
|
||||||
|
//
|
||||||
|
struct _GLFWlibrary
|
||||||
|
{
|
||||||
|
GLFWbool initialized;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
_GLFWinitconfig init;
|
||||||
|
_GLFWfbconfig framebuffer;
|
||||||
|
_GLFWwndconfig window;
|
||||||
|
_GLFWctxconfig context;
|
||||||
|
int refreshRate;
|
||||||
|
} hints;
|
||||||
|
|
||||||
|
_GLFWerror* errorListHead;
|
||||||
|
_GLFWcursor* cursorListHead;
|
||||||
|
_GLFWwindow* windowListHead;
|
||||||
|
|
||||||
|
_GLFWmonitor** monitors;
|
||||||
|
int monitorCount;
|
||||||
|
|
||||||
|
_GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1];
|
||||||
|
_GLFWmapping* mappings;
|
||||||
|
int mappingCount;
|
||||||
|
|
||||||
|
_GLFWtls errorSlot;
|
||||||
|
_GLFWtls contextSlot;
|
||||||
|
_GLFWmutex errorLock;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint64_t offset;
|
||||||
|
// This is defined in the platform's time.h
|
||||||
|
_GLFW_PLATFORM_LIBRARY_TIMER_STATE;
|
||||||
|
} timer;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
GLFWbool available;
|
||||||
|
void* handle;
|
||||||
|
char* extensions[2];
|
||||||
|
#if !defined(_GLFW_VULKAN_STATIC)
|
||||||
|
PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
|
||||||
|
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
|
||||||
|
#endif
|
||||||
|
GLFWbool KHR_surface;
|
||||||
|
#if defined(_GLFW_WIN32)
|
||||||
|
GLFWbool KHR_win32_surface;
|
||||||
|
#elif defined(_GLFW_COCOA)
|
||||||
|
GLFWbool MVK_macos_surface;
|
||||||
|
GLFWbool EXT_metal_surface;
|
||||||
|
#elif defined(_GLFW_X11)
|
||||||
|
GLFWbool KHR_xlib_surface;
|
||||||
|
GLFWbool KHR_xcb_surface;
|
||||||
|
#elif defined(_GLFW_WAYLAND)
|
||||||
|
GLFWbool KHR_wayland_surface;
|
||||||
|
#endif
|
||||||
|
} vk;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
GLFWmonitorfun monitor;
|
||||||
|
GLFWjoystickfun joystick;
|
||||||
|
} callbacks;
|
||||||
|
|
||||||
|
// This is defined in the window API's platform.h
|
||||||
|
_GLFW_PLATFORM_LIBRARY_WINDOW_STATE;
|
||||||
|
// This is defined in the context API's context.h
|
||||||
|
_GLFW_PLATFORM_LIBRARY_CONTEXT_STATE;
|
||||||
|
// This is defined in the platform's joystick.h
|
||||||
|
_GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE;
|
||||||
|
// This is defined in egl_context.h
|
||||||
|
_GLFW_EGL_LIBRARY_CONTEXT_STATE;
|
||||||
|
// This is defined in osmesa_context.h
|
||||||
|
_GLFW_OSMESA_LIBRARY_CONTEXT_STATE;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Global state shared between compilation units of GLFW
|
||||||
|
//
|
||||||
|
extern _GLFWlibrary _glfw;
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int _glfwPlatformInit(void);
|
||||||
|
void _glfwPlatformTerminate(void);
|
||||||
|
const char* _glfwPlatformGetVersionString(void);
|
||||||
|
|
||||||
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos);
|
||||||
|
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
||||||
|
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
|
||||||
|
void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled);
|
||||||
|
GLFWbool _glfwPlatformRawMouseMotionSupported(void);
|
||||||
|
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||||
|
const GLFWimage* image, int xhot, int yhot);
|
||||||
|
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape);
|
||||||
|
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
|
||||||
|
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
|
||||||
|
|
||||||
|
const char* _glfwPlatformGetScancodeName(int scancode);
|
||||||
|
int _glfwPlatformGetKeyScancode(int key);
|
||||||
|
|
||||||
|
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor);
|
||||||
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
|
||||||
|
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||||
|
float* xscale, float* yscale);
|
||||||
|
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height);
|
||||||
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
|
||||||
|
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
|
||||||
|
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
|
||||||
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
|
||||||
|
|
||||||
|
void _glfwPlatformSetClipboardString(const char* string);
|
||||||
|
const char* _glfwPlatformGetClipboardString(void);
|
||||||
|
|
||||||
|
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode);
|
||||||
|
void _glfwPlatformUpdateGamepadGUID(char* guid);
|
||||||
|
|
||||||
|
uint64_t _glfwPlatformGetTimerValue(void);
|
||||||
|
uint64_t _glfwPlatformGetTimerFrequency(void);
|
||||||
|
|
||||||
|
int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||||
|
const _GLFWwndconfig* wndconfig,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig);
|
||||||
|
void _glfwPlatformDestroyWindow(_GLFWwindow* window);
|
||||||
|
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title);
|
||||||
|
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
||||||
|
int count, const GLFWimage* images);
|
||||||
|
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos);
|
||||||
|
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos);
|
||||||
|
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height);
|
||||||
|
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height);
|
||||||
|
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||||
|
int minwidth, int minheight,
|
||||||
|
int maxwidth, int maxheight);
|
||||||
|
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
|
||||||
|
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
|
||||||
|
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||||
|
int* left, int* top,
|
||||||
|
int* right, int* bottom);
|
||||||
|
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
||||||
|
float* xscale, float* yscale);
|
||||||
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window);
|
||||||
|
void _glfwPlatformRestoreWindow(_GLFWwindow* window);
|
||||||
|
void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
|
||||||
|
void _glfwPlatformShowWindow(_GLFWwindow* window);
|
||||||
|
void _glfwPlatformHideWindow(_GLFWwindow* window);
|
||||||
|
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window);
|
||||||
|
void _glfwPlatformFocusWindow(_GLFWwindow* window);
|
||||||
|
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor,
|
||||||
|
int xpos, int ypos, int width, int height,
|
||||||
|
int refreshRate);
|
||||||
|
int _glfwPlatformWindowFocused(_GLFWwindow* window);
|
||||||
|
int _glfwPlatformWindowIconified(_GLFWwindow* window);
|
||||||
|
int _glfwPlatformWindowVisible(_GLFWwindow* window);
|
||||||
|
int _glfwPlatformWindowMaximized(_GLFWwindow* window);
|
||||||
|
int _glfwPlatformWindowHovered(_GLFWwindow* window);
|
||||||
|
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window);
|
||||||
|
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window);
|
||||||
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
|
||||||
|
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
|
||||||
|
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
|
||||||
|
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity);
|
||||||
|
|
||||||
|
void _glfwPlatformPollEvents(void);
|
||||||
|
void _glfwPlatformWaitEvents(void);
|
||||||
|
void _glfwPlatformWaitEventsTimeout(double timeout);
|
||||||
|
void _glfwPlatformPostEmptyEvent(void);
|
||||||
|
|
||||||
|
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions);
|
||||||
|
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||||
|
VkPhysicalDevice device,
|
||||||
|
uint32_t queuefamily);
|
||||||
|
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||||
|
_GLFWwindow* window,
|
||||||
|
const VkAllocationCallbacks* allocator,
|
||||||
|
VkSurfaceKHR* surface);
|
||||||
|
|
||||||
|
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls);
|
||||||
|
void _glfwPlatformDestroyTls(_GLFWtls* tls);
|
||||||
|
void* _glfwPlatformGetTls(_GLFWtls* tls);
|
||||||
|
void _glfwPlatformSetTls(_GLFWtls* tls, void* value);
|
||||||
|
|
||||||
|
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex);
|
||||||
|
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex);
|
||||||
|
void _glfwPlatformLockMutex(_GLFWmutex* mutex);
|
||||||
|
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex);
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW event API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused);
|
||||||
|
void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos);
|
||||||
|
void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
|
||||||
|
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
|
||||||
|
void _glfwInputWindowContentScale(_GLFWwindow* window,
|
||||||
|
float xscale, float yscale);
|
||||||
|
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified);
|
||||||
|
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized);
|
||||||
|
void _glfwInputWindowDamage(_GLFWwindow* window);
|
||||||
|
void _glfwInputWindowCloseRequest(_GLFWwindow* window);
|
||||||
|
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
|
||||||
|
|
||||||
|
void _glfwInputKey(_GLFWwindow* window,
|
||||||
|
int key, int scancode, int action, int mods);
|
||||||
|
void _glfwInputChar(_GLFWwindow* window,
|
||||||
|
unsigned int codepoint, int mods, GLFWbool plain);
|
||||||
|
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset);
|
||||||
|
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
||||||
|
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
||||||
|
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered);
|
||||||
|
void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
|
||||||
|
void _glfwInputJoystick(_GLFWjoystick* js, int event);
|
||||||
|
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value);
|
||||||
|
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value);
|
||||||
|
void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value);
|
||||||
|
|
||||||
|
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement);
|
||||||
|
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window);
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
void _glfwInputError(int code, const char* format, ...)
|
||||||
|
__attribute__((format(printf, 2, 3)));
|
||||||
|
#else
|
||||||
|
void _glfwInputError(int code, const char* format, ...);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions);
|
||||||
|
const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
||||||
|
const _GLFWfbconfig* alternatives,
|
||||||
|
unsigned int count);
|
||||||
|
GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig);
|
||||||
|
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);
|
||||||
|
|
||||||
|
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
|
||||||
|
const GLFWvidmode* desired);
|
||||||
|
int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second);
|
||||||
|
_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM);
|
||||||
|
void _glfwFreeMonitor(_GLFWmonitor* monitor);
|
||||||
|
void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size);
|
||||||
|
void _glfwFreeGammaArrays(GLFWgammaramp* ramp);
|
||||||
|
void _glfwSplitBPP(int bpp, int* red, int* green, int* blue);
|
||||||
|
|
||||||
|
_GLFWjoystick* _glfwAllocJoystick(const char* name,
|
||||||
|
const char* guid,
|
||||||
|
int axisCount,
|
||||||
|
int buttonCount,
|
||||||
|
int hatCount);
|
||||||
|
void _glfwFreeJoystick(_GLFWjoystick* js);
|
||||||
|
void _glfwCenterCursorInContentArea(_GLFWwindow* window);
|
||||||
|
|
||||||
|
GLFWbool _glfwInitVulkan(int mode);
|
||||||
|
void _glfwTerminateVulkan(void);
|
||||||
|
const char* _glfwGetVulkanResultString(VkResult result);
|
||||||
|
|
||||||
|
char* _glfw_strdup(const char* source);
|
||||||
|
float _glfw_fminf(float a, float b);
|
||||||
|
float _glfw_fmaxf(float a, float b);
|
||||||
|
|
|
@ -0,0 +1,433 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 Linux - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/inotify.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifndef SYN_DROPPED // < v2.6.39 kernel headers
|
||||||
|
// Workaround for CentOS-6, which is supported till 2020-11-30, but still on v2.6.32
|
||||||
|
#define SYN_DROPPED 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Apply an EV_KEY event to the specified joystick
|
||||||
|
//
|
||||||
|
static void handleKeyEvent(_GLFWjoystick* js, int code, int value)
|
||||||
|
{
|
||||||
|
_glfwInputJoystickButton(js,
|
||||||
|
js->linjs.keyMap[code - BTN_MISC],
|
||||||
|
value ? GLFW_PRESS : GLFW_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply an EV_ABS event to the specified joystick
|
||||||
|
//
|
||||||
|
static void handleAbsEvent(_GLFWjoystick* js, int code, int value)
|
||||||
|
{
|
||||||
|
const int index = js->linjs.absMap[code];
|
||||||
|
|
||||||
|
if (code >= ABS_HAT0X && code <= ABS_HAT3Y)
|
||||||
|
{
|
||||||
|
static const char stateMap[3][3] =
|
||||||
|
{
|
||||||
|
{ GLFW_HAT_CENTERED, GLFW_HAT_UP, GLFW_HAT_DOWN },
|
||||||
|
{ GLFW_HAT_LEFT, GLFW_HAT_LEFT_UP, GLFW_HAT_LEFT_DOWN },
|
||||||
|
{ GLFW_HAT_RIGHT, GLFW_HAT_RIGHT_UP, GLFW_HAT_RIGHT_DOWN },
|
||||||
|
};
|
||||||
|
|
||||||
|
const int hat = (code - ABS_HAT0X) / 2;
|
||||||
|
const int axis = (code - ABS_HAT0X) % 2;
|
||||||
|
int* state = js->linjs.hats[hat];
|
||||||
|
|
||||||
|
// NOTE: Looking at several input drivers, it seems all hat events use
|
||||||
|
// -1 for left / up, 0 for centered and 1 for right / down
|
||||||
|
if (value == 0)
|
||||||
|
state[axis] = 0;
|
||||||
|
else if (value < 0)
|
||||||
|
state[axis] = 1;
|
||||||
|
else if (value > 0)
|
||||||
|
state[axis] = 2;
|
||||||
|
|
||||||
|
_glfwInputJoystickHat(js, index, stateMap[state[0]][state[1]]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const struct input_absinfo* info = &js->linjs.absInfo[code];
|
||||||
|
float normalized = value;
|
||||||
|
|
||||||
|
const int range = info->maximum - info->minimum;
|
||||||
|
if (range)
|
||||||
|
{
|
||||||
|
// Normalize to 0.0 -> 1.0
|
||||||
|
normalized = (normalized - info->minimum) / range;
|
||||||
|
// Normalize to -1.0 -> 1.0
|
||||||
|
normalized = normalized * 2.0f - 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputJoystickAxis(js, index, normalized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Poll state of absolute axes
|
||||||
|
//
|
||||||
|
static void pollAbsState(_GLFWjoystick* js)
|
||||||
|
{
|
||||||
|
for (int code = 0; code < ABS_CNT; code++)
|
||||||
|
{
|
||||||
|
if (js->linjs.absMap[code] < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
struct input_absinfo* info = &js->linjs.absInfo[code];
|
||||||
|
|
||||||
|
if (ioctl(js->linjs.fd, EVIOCGABS(code), info) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
handleAbsEvent(js, code, info->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define isBitSet(bit, arr) (arr[(bit) / 8] & (1 << ((bit) % 8)))
|
||||||
|
|
||||||
|
// Attempt to open the specified joystick device
|
||||||
|
//
|
||||||
|
static GLFWbool openJoystickDevice(const char* path)
|
||||||
|
{
|
||||||
|
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
{
|
||||||
|
if (!_glfw.joysticks[jid].present)
|
||||||
|
continue;
|
||||||
|
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_GLFWjoystickLinux linjs = {0};
|
||||||
|
linjs.fd = open(path, O_RDONLY | O_NONBLOCK);
|
||||||
|
if (linjs.fd == -1)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
char evBits[(EV_CNT + 7) / 8] = {0};
|
||||||
|
char keyBits[(KEY_CNT + 7) / 8] = {0};
|
||||||
|
char absBits[(ABS_CNT + 7) / 8] = {0};
|
||||||
|
struct input_id id;
|
||||||
|
|
||||||
|
if (ioctl(linjs.fd, EVIOCGBIT(0, sizeof(evBits)), evBits) < 0 ||
|
||||||
|
ioctl(linjs.fd, EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits) < 0 ||
|
||||||
|
ioctl(linjs.fd, EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits) < 0 ||
|
||||||
|
ioctl(linjs.fd, EVIOCGID, &id) < 0)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Linux: Failed to query input device: %s",
|
||||||
|
strerror(errno));
|
||||||
|
close(linjs.fd);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure this device supports the events expected of a joystick
|
||||||
|
if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits))
|
||||||
|
{
|
||||||
|
close(linjs.fd);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
char name[256] = "";
|
||||||
|
|
||||||
|
if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0)
|
||||||
|
strncpy(name, "Unknown", sizeof(name));
|
||||||
|
|
||||||
|
char guid[33] = "";
|
||||||
|
|
||||||
|
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
||||||
|
if (id.vendor && id.product && id.version)
|
||||||
|
{
|
||||||
|
sprintf(guid, "%02x%02x0000%02x%02x0000%02x%02x0000%02x%02x0000",
|
||||||
|
id.bustype & 0xff, id.bustype >> 8,
|
||||||
|
id.vendor & 0xff, id.vendor >> 8,
|
||||||
|
id.product & 0xff, id.product >> 8,
|
||||||
|
id.version & 0xff, id.version >> 8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(guid, "%02x%02x0000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
|
||||||
|
id.bustype & 0xff, id.bustype >> 8,
|
||||||
|
name[0], name[1], name[2], name[3],
|
||||||
|
name[4], name[5], name[6], name[7],
|
||||||
|
name[8], name[9], name[10]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int axisCount = 0, buttonCount = 0, hatCount = 0;
|
||||||
|
|
||||||
|
for (int code = BTN_MISC; code < KEY_CNT; code++)
|
||||||
|
{
|
||||||
|
if (!isBitSet(code, keyBits))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
linjs.keyMap[code - BTN_MISC] = buttonCount;
|
||||||
|
buttonCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int code = 0; code < ABS_CNT; code++)
|
||||||
|
{
|
||||||
|
linjs.absMap[code] = -1;
|
||||||
|
if (!isBitSet(code, absBits))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (code >= ABS_HAT0X && code <= ABS_HAT3Y)
|
||||||
|
{
|
||||||
|
linjs.absMap[code] = hatCount;
|
||||||
|
hatCount++;
|
||||||
|
// Skip the Y axis
|
||||||
|
code++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ioctl(linjs.fd, EVIOCGABS(code), &linjs.absInfo[code]) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
linjs.absMap[code] = axisCount;
|
||||||
|
axisCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_GLFWjoystick* js =
|
||||||
|
_glfwAllocJoystick(name, guid, axisCount, buttonCount, hatCount);
|
||||||
|
if (!js)
|
||||||
|
{
|
||||||
|
close(linjs.fd);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(linjs.path, path, sizeof(linjs.path) - 1);
|
||||||
|
memcpy(&js->linjs, &linjs, sizeof(linjs));
|
||||||
|
|
||||||
|
pollAbsState(js);
|
||||||
|
|
||||||
|
_glfwInputJoystick(js, GLFW_CONNECTED);
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef isBitSet
|
||||||
|
|
||||||
|
// Frees all resources associated with the specified joystick
|
||||||
|
//
|
||||||
|
static void closeJoystick(_GLFWjoystick* js)
|
||||||
|
{
|
||||||
|
close(js->linjs.fd);
|
||||||
|
_glfwFreeJoystick(js);
|
||||||
|
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lexically compare joysticks by name; used by qsort
|
||||||
|
//
|
||||||
|
static int compareJoysticks(const void* fp, const void* sp)
|
||||||
|
{
|
||||||
|
const _GLFWjoystick* fj = fp;
|
||||||
|
const _GLFWjoystick* sj = sp;
|
||||||
|
return strcmp(fj->linjs.path, sj->linjs.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Initialize joystick interface
|
||||||
|
//
|
||||||
|
GLFWbool _glfwInitJoysticksLinux(void)
|
||||||
|
{
|
||||||
|
const char* dirname = "/dev/input";
|
||||||
|
|
||||||
|
_glfw.linjs.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||||
|
if (_glfw.linjs.inotify > 0)
|
||||||
|
{
|
||||||
|
// HACK: Register for IN_ATTRIB to get notified when udev is done
|
||||||
|
// This works well in practice but the true way is libudev
|
||||||
|
|
||||||
|
_glfw.linjs.watch = inotify_add_watch(_glfw.linjs.inotify,
|
||||||
|
dirname,
|
||||||
|
IN_CREATE | IN_ATTRIB | IN_DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue without device connection notifications if inotify fails
|
||||||
|
|
||||||
|
if (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) != 0)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
DIR* dir = opendir(dirname);
|
||||||
|
if (dir)
|
||||||
|
{
|
||||||
|
struct dirent* entry;
|
||||||
|
|
||||||
|
while ((entry = readdir(dir)))
|
||||||
|
{
|
||||||
|
regmatch_t match;
|
||||||
|
|
||||||
|
if (regexec(&_glfw.linjs.regex, entry->d_name, 1, &match, 0) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
char path[PATH_MAX];
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
|
||||||
|
|
||||||
|
if (openJoystickDevice(path))
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue with no joysticks if enumeration fails
|
||||||
|
|
||||||
|
qsort(_glfw.joysticks, count, sizeof(_GLFWjoystick), compareJoysticks);
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close all opened joystick handles
|
||||||
|
//
|
||||||
|
void _glfwTerminateJoysticksLinux(void)
|
||||||
|
{
|
||||||
|
int jid;
|
||||||
|
|
||||||
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
{
|
||||||
|
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||||
|
if (js->present)
|
||||||
|
closeJoystick(js);
|
||||||
|
}
|
||||||
|
|
||||||
|
regfree(&_glfw.linjs.regex);
|
||||||
|
|
||||||
|
if (_glfw.linjs.inotify > 0)
|
||||||
|
{
|
||||||
|
if (_glfw.linjs.watch > 0)
|
||||||
|
inotify_rm_watch(_glfw.linjs.inotify, _glfw.linjs.watch);
|
||||||
|
|
||||||
|
close(_glfw.linjs.inotify);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwDetectJoystickConnectionLinux(void)
|
||||||
|
{
|
||||||
|
if (_glfw.linjs.inotify <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ssize_t offset = 0;
|
||||||
|
char buffer[16384];
|
||||||
|
const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer));
|
||||||
|
|
||||||
|
while (size > offset)
|
||||||
|
{
|
||||||
|
regmatch_t match;
|
||||||
|
const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
|
||||||
|
|
||||||
|
offset += sizeof(struct inotify_event) + e->len;
|
||||||
|
|
||||||
|
if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
char path[PATH_MAX];
|
||||||
|
snprintf(path, sizeof(path), "/dev/input/%s", e->name);
|
||||||
|
|
||||||
|
if (e->mask & (IN_CREATE | IN_ATTRIB))
|
||||||
|
openJoystickDevice(path);
|
||||||
|
else if (e->mask & IN_DELETE)
|
||||||
|
{
|
||||||
|
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
{
|
||||||
|
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
||||||
|
{
|
||||||
|
closeJoystick(_glfw.joysticks + jid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||||
|
{
|
||||||
|
// Read all queued events (non-blocking)
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
struct input_event e;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
if (read(js->linjs.fd, &e, sizeof(e)) < 0)
|
||||||
|
{
|
||||||
|
// Reset the joystick slot if the device was disconnected
|
||||||
|
if (errno == ENODEV)
|
||||||
|
closeJoystick(js);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.type == EV_SYN)
|
||||||
|
{
|
||||||
|
if (e.code == SYN_DROPPED)
|
||||||
|
_glfw.linjs.dropped = GLFW_TRUE;
|
||||||
|
else if (e.code == SYN_REPORT)
|
||||||
|
{
|
||||||
|
_glfw.linjs.dropped = GLFW_FALSE;
|
||||||
|
pollAbsState(js);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.linjs.dropped)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (e.type == EV_KEY)
|
||||||
|
handleKeyEvent(js, e.code, e.value);
|
||||||
|
else if (e.type == EV_ABS)
|
||||||
|
handleAbsEvent(js, e.code, e.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return js->present;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 Linux - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <linux/limits.h>
|
||||||
|
#include <regex.h>
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickLinux linjs
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_MAPPING_NAME "Linux"
|
||||||
|
|
||||||
|
// Linux-specific joystick data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWjoystickLinux
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
int keyMap[KEY_CNT - BTN_MISC];
|
||||||
|
int absMap[ABS_CNT];
|
||||||
|
struct input_absinfo absInfo[ABS_CNT];
|
||||||
|
int hats[4][2];
|
||||||
|
} _GLFWjoystickLinux;
|
||||||
|
|
||||||
|
// Linux-specific joystick API data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWlibraryLinux
|
||||||
|
{
|
||||||
|
int inotify;
|
||||||
|
int watch;
|
||||||
|
regex_t regex;
|
||||||
|
GLFWbool dropped;
|
||||||
|
} _GLFWlibraryLinux;
|
||||||
|
|
||||||
|
|
||||||
|
GLFWbool _glfwInitJoysticksLinux(void);
|
||||||
|
void _glfwTerminateJoysticksLinux(void);
|
||||||
|
void _glfwDetectJoystickConnectionLinux(void);
|
||||||
|
|
|
@ -0,0 +1,477 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// As mappings.h.in, this file is used by CMake to produce the mappings.h
|
||||||
|
// header file. If you are adding a GLFW specific gamepad mapping, this is
|
||||||
|
// where to put it.
|
||||||
|
//========================================================================
|
||||||
|
// As mappings.h, this provides all pre-defined gamepad mappings, including
|
||||||
|
// all available in SDL_GameControllerDB. Do not edit this file. Any gamepad
|
||||||
|
// mappings not specific to GLFW should be submitted to SDL_GameControllerDB.
|
||||||
|
// This file can be re-generated from mappings.h.in and the upstream
|
||||||
|
// gamecontrollerdb.txt with the GenerateMappings.cmake script.
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
// All gamepad mappings not labeled GLFW are copied from the
|
||||||
|
// SDL_GameControllerDB project under the following license:
|
||||||
|
//
|
||||||
|
// Simple DirectMedia Layer
|
||||||
|
// Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the
|
||||||
|
// use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
const char* _glfwDefaultMappings[] =
|
||||||
|
{
|
||||||
|
"03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,",
|
||||||
|
"03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",
|
||||||
|
"03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",
|
||||||
|
"03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,",
|
||||||
|
"03000000a00500003232000000000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,",
|
||||||
|
"030000008f0e00001200000000000000,Acme,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,",
|
||||||
|
"03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows,",
|
||||||
|
"030000006b1400000055000000000000,bigben ps3padstreetnew,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
|
||||||
|
"0300000066f700000500000000000000,BrutalLegendTest,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,",
|
||||||
|
"03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
|
||||||
|
"030000005e0400008e02000000000000,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
|
||||||
|
"03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows,",
|
||||||
|
"03000000a306000022f6000000000000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000791d00000103000000000000,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
|
||||||
|
"030000004f04000023b3000000000000,Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000341a00000108000000000000,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00008500000000000000,Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00008400000000000000,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00008700000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows,",
|
||||||
|
"03000000260900002625000000000000,Gamecube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows,",
|
||||||
|
"030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000280400000140000000000000,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
|
||||||
|
"03000000451300000010000000000000,Generic USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
|
||||||
|
"03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00004900000000000000,Hatsune Miku Sho Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000d81400000862000000000000,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00005f00000000000000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00005e00000000000000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00004000000000000000,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00006e00000000000000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00006600000000000000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f0000ee00000000000000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00004d00000000000000,HORIPAD3 A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000250900000017000000000000,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows,",
|
||||||
|
"030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Windows,",
|
||||||
|
"03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
|
||||||
|
"03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
|
||||||
|
"03000000830500006020000000000000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Windows,",
|
||||||
|
"03000000b50700001403000000000000,IMPACT BLACK,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
|
||||||
|
"030000006f0e00002401000000000000,INJUSTICE FightStick for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000491900000204000000000000,Ipega PG-9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",
|
||||||
|
"030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows,",
|
||||||
|
"030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000006d04000018c2000000000000,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000006d04000019c2000000000000,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000380700005032000000000000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000380700005082000000000000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000380700008433000000000000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000380700008483000000000000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b6,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000380700008134000000000000,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000380700008184000000000000,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000380700008532000000000000,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000380700003888000000000000,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000380700001888000000000000,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
|
||||||
|
"03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000008305000031b0000000000000,MaxfireBlaze3,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
|
||||||
|
"03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,",
|
||||||
|
"03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000008f0e00001030000000000000,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows,",
|
||||||
|
"0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,",
|
||||||
|
"03000000790000000018000000000000,Mayflash WiiU Pro Dezl Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Windows,",
|
||||||
|
"03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,",
|
||||||
|
"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
|
||||||
|
"030000004b120000014d000000000000,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,leftx:h0.6,lefty:h0.12,rightshoulder:b5,rightstick:a2,righttrigger:b7,rightx:h0.9,righty:h0.4,start:b9,x:b2,y:b3,platform:Windows,",
|
||||||
|
"03000000362800000100000000000000,OUYA Dezl Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,",
|
||||||
|
"03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
|
||||||
|
"03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000008f0e00007530000000000000,PS (R) Gamepad,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000e30500009605000000000000,PS to USB convert cable,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,",
|
||||||
|
"03000000100800000100000000000000,PS1 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
|
||||||
|
"03000000100800000300000000000000,PS2 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
|
||||||
|
"03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,",
|
||||||
|
"03000000250900000500000000000000,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000100000008200000000000000,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000300f00000011000000000000,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000300f00001611000000000000,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000222c00000020000000000000,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000300f00001210000000000000,QanBa Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,",
|
||||||
|
"03000000341a00000104000000000000,QanBa Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows,",
|
||||||
|
"03000000222c00000223000000000000,Qanba Obsidian Arcade Joystick PS3 Mode,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000222c00000023000000000000,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00001100000000000000,REAL ARCADE PRO.3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00008b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00008a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00006b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00006a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00007000000000000000,REAL ARCADE PRO.4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00002200000000000000,REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00005c00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000000d0f00005b00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000790000001100000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,",
|
||||||
|
"0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,",
|
||||||
|
"0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,",
|
||||||
|
"030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000006f0e00001e01000000000000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000a306000023f6000000000000,Saitek Cyborg V.1 Dezl pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000300f00001201000000000000,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
|
||||||
|
"03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,x:b0,y:b1,platform:Windows,",
|
||||||
|
"03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000300f00001001000000000000,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
|
||||||
|
"03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000300f00001101000000000000,saitek rumble pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
|
||||||
|
"0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,",
|
||||||
|
"030000008f0e00000800000000000000,SpeedLink Strike FX Wireless,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
|
||||||
|
"03000000ff1100003133000000000000,SVEN X-PAD,a:b2,b:b3,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a4,start:b5,x:b0,y:b1,platform:Windows,",
|
||||||
|
"03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
|
||||||
|
"03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
|
||||||
|
"030000004f04000015b3000000000000,Thrustmaster Dual Analog 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,",
|
||||||
|
"030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows,",
|
||||||
|
"030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,",
|
||||||
|
"03000000666600000488000000000000,TigerGame PS/PS2 Dezl Controller Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,",
|
||||||
|
"03000000d90400000200000000000000,TwinShock PS2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
|
||||||
|
"03000000380700006652000000000000,UnKnown,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000632500002305000000000000,USB Vibration Joystick (BM),a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
|
||||||
|
"03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
|
||||||
|
"03000000450c00002043000000000000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
|
||||||
|
"03000000172700004431000000000000,XiaoMi Dezl Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,",
|
||||||
|
"03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
|
||||||
|
"03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000022000000090000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000102800000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,",
|
||||||
|
"030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000ad1b000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"030000000d0f00005f00000000010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000000d0f00005e00000000010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000000d0f00005f00000000000000,HORI Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000000d0f00005e00000000000000,HORI Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000000d0f00004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000000d0f00006e00000000010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000000d0f00006600000000010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000000d0f00006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X,",
|
||||||
|
"03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,",
|
||||||
|
"03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,",
|
||||||
|
"030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000006d04000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000006d04000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000006d0400001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"030000006d04000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000380700005032000000010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000380700005082000000010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X,",
|
||||||
|
"03000000790000000018000000000000,Mayflash WiiU Pro Dezl Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,",
|
||||||
|
"03000000d8140000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Mac OS X,",
|
||||||
|
"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,",
|
||||||
|
"030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,",
|
||||||
|
"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,",
|
||||||
|
"030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000321500000010000000010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
|
||||||
|
"03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
|
||||||
|
"030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X,",
|
||||||
|
"03000000b40400000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X,",
|
||||||
|
"030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,",
|
||||||
|
"030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"030000005e0400008e02000001000000,Steam Virtual GamePad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X,",
|
||||||
|
"030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000bd12000015d0000000010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
|
||||||
|
"03000000bd12000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
|
||||||
|
"03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X,",
|
||||||
|
"050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X,",
|
||||||
|
"050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X,",
|
||||||
|
"030000005e0400008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000c6240000045d000000000000,Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"030000005e040000e302000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"030000005e040000d102000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"030000005e040000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"030000005e040000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"030000005e040000fd02000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,",
|
||||||
|
"030000005e040000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"030000005e040000e002000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,",
|
||||||
|
"03000000172700004431000029010000,XiaoMi Dezl Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,",
|
||||||
|
"03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
|
||||||
|
"05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
|
||||||
|
"03000000022000000090000011010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
|
||||||
|
"05000000c82d00002038000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
|
||||||
|
"03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
|
||||||
|
"05000000c82d00003028000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,",
|
||||||
|
"05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,",
|
||||||
|
"03000000c82d000020ab000010010000,8Bitdo SNES30,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0",
|
||||||
|
"05000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,",
|
||||||
|
"05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,",
|
||||||
|
"030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,",
|
||||||
|
"03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",
|
||||||
|
"03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000a306000022f6000011010000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000b40400000a01000000010000,CYPRESS USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,",
|
||||||
|
"03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,",
|
||||||
|
"030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000006f0e00001304000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:a0,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:a3,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000006f0e00001f01000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000280400000140000000010000,Gravis GamePad Pro USB ,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000008f0e00000610000000010000,GreenAsia Electronics 4Axes 12Keys GamePad ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux,",
|
||||||
|
"030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
|
||||||
|
"0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
|
||||||
|
"06000000adde0000efbe000002010000,Hidromancer Dezl Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000c9110000f055000011010000,HJC Dezl GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux,",
|
||||||
|
"030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000000d0f00006a00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000000d0f00006b00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000000d0f00005f00000011010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000000d0f00005e00000011010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000000d0f00006e00000011010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000000d0f00006600000011010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000000d0f00006700000001010000,HORIPAD ONE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000008f0e00001330000010010000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Linux,",
|
||||||
|
"03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,",
|
||||||
|
"050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,",
|
||||||
|
"03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Dezl Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux,",
|
||||||
|
"030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux,",
|
||||||
|
"03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,",
|
||||||
|
"03000000ba2200002010000001010000,Jess Technology USB Dezl Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
|
||||||
|
"030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000006d04000015c2000010010000,Logitech Logitech Extreme 3D,a:b0,b:b4,back:b6,guide:b8,leftshoulder:b9,leftstick:h0.8,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:h0.2,start:b7,x:b2,y:b5,platform:Linux,",
|
||||||
|
"030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux,",
|
||||||
|
"05000000380700006652000025010000,Mad Catz C.T.R.L.R ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000380700005032000011010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000380700005082000011010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000380700008034000011010000,Mad Catz fightstick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000380700008084000011010000,Mad Catz fightstick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000380700008433000011010000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000380700008483000011010000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller (SFIV),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,",
|
||||||
|
"030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000005e0400008e02000062230000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000005e040000d102000001010000,Microsoft X-Box One pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000005e040000d102000003020000,Microsoft X-Box One pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",
|
||||||
|
"030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",
|
||||||
|
"05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Linux,",
|
||||||
|
"050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
|
||||||
|
"050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,",
|
||||||
|
"05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000000d0500000308000010010000,Nostromo n45 Dual Analog Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000005e0400000202000000010000,Old Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",
|
||||||
|
"05000000362800000100000002010000,OUYA Dezl Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,",
|
||||||
|
"05000000362800000100000003010000,OUYA Dezl Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,",
|
||||||
|
"03000000ff1100003133000010010000,PC Dezl Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",
|
||||||
|
"030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,",
|
||||||
|
"030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
|
||||||
|
"050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
|
||||||
|
"03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
|
||||||
|
"050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
|
||||||
|
"030000004c0500006802000010810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
|
||||||
|
"030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
|
||||||
|
"060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
|
||||||
|
"05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
|
||||||
|
"050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
|
||||||
|
"050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
|
||||||
|
"030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
|
||||||
|
"050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
|
||||||
|
"030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
|
||||||
|
"030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000300f00001211000011010000,QanBa Arcade JoyStick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux,",
|
||||||
|
"030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,",
|
||||||
|
"030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000321500000010000011010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000790000001100000010010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,",
|
||||||
|
"0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,",
|
||||||
|
"0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,",
|
||||||
|
"030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000a306000023f6000011010000,Saitek Cyborg V.1 Dezl Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,",
|
||||||
|
"03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,",
|
||||||
|
"03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux,",
|
||||||
|
"03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",
|
||||||
|
"03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,",
|
||||||
|
"030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,",
|
||||||
|
"030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,",
|
||||||
|
"030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,",
|
||||||
|
"030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux,",
|
||||||
|
"030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,",
|
||||||
|
"03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,",
|
||||||
|
"03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
|
||||||
|
"03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
|
||||||
|
"03000000790000001100000000010000,USB Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux,",
|
||||||
|
"05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000005e040000a102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux,",
|
||||||
|
"0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
|
||||||
|
"050000005e040000fd02000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",
|
||||||
|
"03000000450c00002043000010010000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
|
||||||
|
"05000000172700004431000029010000,XiaoMi Dezl Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux,",
|
||||||
|
"03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,",
|
||||||
|
"03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
|
||||||
|
"64633436313965656664373634323364,Microsoft X-Box 360 pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,",
|
||||||
|
"61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",
|
||||||
|
"4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",
|
||||||
|
"37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",
|
||||||
|
"35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,",
|
||||||
|
"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,",
|
||||||
|
"5477696e20555342204a6f7973746963,Twin USB Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android,",
|
||||||
|
"34356136633366613530316338376136,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android,",
|
||||||
|
"4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS,",
|
||||||
|
"4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS,",
|
||||||
|
"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS,",
|
||||||
|
|
||||||
|
"78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||||
|
"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||||
|
"78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||||
|
"78696e70757404000000000000000000,XInput Flight Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||||
|
"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||||
|
"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||||
|
"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// As mappings.h.in, this file is used by CMake to produce the mappings.h
|
||||||
|
// header file. If you are adding a GLFW specific gamepad mapping, this is
|
||||||
|
// where to put it.
|
||||||
|
//========================================================================
|
||||||
|
// As mappings.h, this provides all pre-defined gamepad mappings, including
|
||||||
|
// all available in SDL_GameControllerDB. Do not edit this file. Any gamepad
|
||||||
|
// mappings not specific to GLFW should be submitted to SDL_GameControllerDB.
|
||||||
|
// This file can be re-generated from mappings.h.in and the upstream
|
||||||
|
// gamecontrollerdb.txt with the GenerateMappings.cmake script.
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
// All gamepad mappings not labeled GLFW are copied from the
|
||||||
|
// SDL_GameControllerDB project under the following license:
|
||||||
|
//
|
||||||
|
// Simple DirectMedia Layer
|
||||||
|
// Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the
|
||||||
|
// use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
const char* _glfwDefaultMappings[] =
|
||||||
|
{
|
||||||
|
@GLFW_GAMEPAD_MAPPINGS@
|
||||||
|
"78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||||
|
"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||||
|
"78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||||
|
"78696e70757404000000000000000000,XInput Flight Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||||
|
"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||||
|
"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||||
|
"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,544 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Lexically compare video modes, used by qsort
|
||||||
|
//
|
||||||
|
static int compareVideoModes(const void* fp, const void* sp)
|
||||||
|
{
|
||||||
|
const GLFWvidmode* fm = fp;
|
||||||
|
const GLFWvidmode* sm = sp;
|
||||||
|
const int fbpp = fm->redBits + fm->greenBits + fm->blueBits;
|
||||||
|
const int sbpp = sm->redBits + sm->greenBits + sm->blueBits;
|
||||||
|
const int farea = fm->width * fm->height;
|
||||||
|
const int sarea = sm->width * sm->height;
|
||||||
|
|
||||||
|
// First sort on color bits per pixel
|
||||||
|
if (fbpp != sbpp)
|
||||||
|
return fbpp - sbpp;
|
||||||
|
|
||||||
|
// Then sort on screen area
|
||||||
|
if (farea != sarea)
|
||||||
|
return farea - sarea;
|
||||||
|
|
||||||
|
// Then sort on width
|
||||||
|
if (fm->width != sm->width)
|
||||||
|
return fm->width - sm->width;
|
||||||
|
|
||||||
|
// Lastly sort on refresh rate
|
||||||
|
return fm->refreshRate - sm->refreshRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieves the available modes for the specified monitor
|
||||||
|
//
|
||||||
|
static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
|
||||||
|
{
|
||||||
|
int modeCount;
|
||||||
|
GLFWvidmode* modes;
|
||||||
|
|
||||||
|
if (monitor->modes)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
modes = _glfwPlatformGetVideoModes(monitor, &modeCount);
|
||||||
|
if (!modes)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes);
|
||||||
|
|
||||||
|
free(monitor->modes);
|
||||||
|
monitor->modes = modes;
|
||||||
|
monitor->modeCount = modeCount;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW event API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Notifies shared code of a monitor connection or disconnection
|
||||||
|
//
|
||||||
|
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
|
||||||
|
{
|
||||||
|
if (action == GLFW_CONNECTED)
|
||||||
|
{
|
||||||
|
_glfw.monitorCount++;
|
||||||
|
_glfw.monitors =
|
||||||
|
realloc(_glfw.monitors, sizeof(_GLFWmonitor*) * _glfw.monitorCount);
|
||||||
|
|
||||||
|
if (placement == _GLFW_INSERT_FIRST)
|
||||||
|
{
|
||||||
|
memmove(_glfw.monitors + 1,
|
||||||
|
_glfw.monitors,
|
||||||
|
((size_t) _glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
|
||||||
|
_glfw.monitors[0] = monitor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_glfw.monitors[_glfw.monitorCount - 1] = monitor;
|
||||||
|
}
|
||||||
|
else if (action == GLFW_DISCONNECTED)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
_GLFWwindow* window;
|
||||||
|
|
||||||
|
for (window = _glfw.windowListHead; window; window = window->next)
|
||||||
|
{
|
||||||
|
if (window->monitor == monitor)
|
||||||
|
{
|
||||||
|
int width, height, xoff, yoff;
|
||||||
|
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||||
|
_glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0);
|
||||||
|
_glfwPlatformGetWindowFrameSize(window, &xoff, &yoff, NULL, NULL);
|
||||||
|
_glfwPlatformSetWindowPos(window, xoff, yoff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < _glfw.monitorCount; i++)
|
||||||
|
{
|
||||||
|
if (_glfw.monitors[i] == monitor)
|
||||||
|
{
|
||||||
|
_glfw.monitorCount--;
|
||||||
|
memmove(_glfw.monitors + i,
|
||||||
|
_glfw.monitors + i + 1,
|
||||||
|
((size_t) _glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.callbacks.monitor)
|
||||||
|
_glfw.callbacks.monitor((GLFWmonitor*) monitor, action);
|
||||||
|
|
||||||
|
if (action == GLFW_DISCONNECTED)
|
||||||
|
_glfwFreeMonitor(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notifies shared code that a full screen window has acquired or released
|
||||||
|
// a monitor
|
||||||
|
//
|
||||||
|
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
|
||||||
|
{
|
||||||
|
monitor->window = window;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Allocates and returns a monitor object with the specified name and dimensions
|
||||||
|
//
|
||||||
|
_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
|
||||||
|
monitor->widthMM = widthMM;
|
||||||
|
monitor->heightMM = heightMM;
|
||||||
|
|
||||||
|
if (name)
|
||||||
|
monitor->name = _glfw_strdup(name);
|
||||||
|
|
||||||
|
return monitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frees a monitor object and any data associated with it
|
||||||
|
//
|
||||||
|
void _glfwFreeMonitor(_GLFWmonitor* monitor)
|
||||||
|
{
|
||||||
|
if (monitor == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_glfwPlatformFreeMonitor(monitor);
|
||||||
|
|
||||||
|
_glfwFreeGammaArrays(&monitor->originalRamp);
|
||||||
|
_glfwFreeGammaArrays(&monitor->currentRamp);
|
||||||
|
|
||||||
|
free(monitor->modes);
|
||||||
|
free(monitor->name);
|
||||||
|
free(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocates red, green and blue value arrays of the specified size
|
||||||
|
//
|
||||||
|
void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
|
||||||
|
{
|
||||||
|
ramp->red = calloc(size, sizeof(unsigned short));
|
||||||
|
ramp->green = calloc(size, sizeof(unsigned short));
|
||||||
|
ramp->blue = calloc(size, sizeof(unsigned short));
|
||||||
|
ramp->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frees the red, green and blue value arrays and clears the struct
|
||||||
|
//
|
||||||
|
void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
|
||||||
|
{
|
||||||
|
free(ramp->red);
|
||||||
|
free(ramp->green);
|
||||||
|
free(ramp->blue);
|
||||||
|
|
||||||
|
memset(ramp, 0, sizeof(GLFWgammaramp));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chooses the video mode most closely matching the desired one
|
||||||
|
//
|
||||||
|
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
|
||||||
|
const GLFWvidmode* desired)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned int sizeDiff, leastSizeDiff = UINT_MAX;
|
||||||
|
unsigned int rateDiff, leastRateDiff = UINT_MAX;
|
||||||
|
unsigned int colorDiff, leastColorDiff = UINT_MAX;
|
||||||
|
const GLFWvidmode* current;
|
||||||
|
const GLFWvidmode* closest = NULL;
|
||||||
|
|
||||||
|
if (!refreshVideoModes(monitor))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < monitor->modeCount; i++)
|
||||||
|
{
|
||||||
|
current = monitor->modes + i;
|
||||||
|
|
||||||
|
colorDiff = 0;
|
||||||
|
|
||||||
|
if (desired->redBits != GLFW_DONT_CARE)
|
||||||
|
colorDiff += abs(current->redBits - desired->redBits);
|
||||||
|
if (desired->greenBits != GLFW_DONT_CARE)
|
||||||
|
colorDiff += abs(current->greenBits - desired->greenBits);
|
||||||
|
if (desired->blueBits != GLFW_DONT_CARE)
|
||||||
|
colorDiff += abs(current->blueBits - desired->blueBits);
|
||||||
|
|
||||||
|
sizeDiff = abs((current->width - desired->width) *
|
||||||
|
(current->width - desired->width) +
|
||||||
|
(current->height - desired->height) *
|
||||||
|
(current->height - desired->height));
|
||||||
|
|
||||||
|
if (desired->refreshRate != GLFW_DONT_CARE)
|
||||||
|
rateDiff = abs(current->refreshRate - desired->refreshRate);
|
||||||
|
else
|
||||||
|
rateDiff = UINT_MAX - current->refreshRate;
|
||||||
|
|
||||||
|
if ((colorDiff < leastColorDiff) ||
|
||||||
|
(colorDiff == leastColorDiff && sizeDiff < leastSizeDiff) ||
|
||||||
|
(colorDiff == leastColorDiff && sizeDiff == leastSizeDiff && rateDiff < leastRateDiff))
|
||||||
|
{
|
||||||
|
closest = current;
|
||||||
|
leastSizeDiff = sizeDiff;
|
||||||
|
leastRateDiff = rateDiff;
|
||||||
|
leastColorDiff = colorDiff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return closest;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Performs lexical comparison between two @ref GLFWvidmode structures
|
||||||
|
//
|
||||||
|
int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm)
|
||||||
|
{
|
||||||
|
return compareVideoModes(fm, sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Splits a color depth into red, green and blue bit depths
|
||||||
|
//
|
||||||
|
void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
|
||||||
|
{
|
||||||
|
int delta;
|
||||||
|
|
||||||
|
// We assume that by 32 the user really meant 24
|
||||||
|
if (bpp == 32)
|
||||||
|
bpp = 24;
|
||||||
|
|
||||||
|
// Convert "bits per pixel" to red, green & blue sizes
|
||||||
|
|
||||||
|
*red = *green = *blue = bpp / 3;
|
||||||
|
delta = bpp - (*red * 3);
|
||||||
|
if (delta >= 1)
|
||||||
|
*green = *green + 1;
|
||||||
|
|
||||||
|
if (delta == 2)
|
||||||
|
*red = *red + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW public API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
|
||||||
|
{
|
||||||
|
assert(count != NULL);
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
*count = _glfw.monitorCount;
|
||||||
|
return (GLFWmonitor**) _glfw.monitors;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (!_glfw.monitorCount)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return (GLFWmonitor*) _glfw.monitors[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
|
||||||
|
if (xpos)
|
||||||
|
*xpos = 0;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = 0;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
_glfwPlatformGetMonitorPos(monitor, xpos, ypos);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle,
|
||||||
|
int* xpos, int* ypos,
|
||||||
|
int* width, int* height)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
|
||||||
|
if (xpos)
|
||||||
|
*xpos = 0;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = 0;
|
||||||
|
if (width)
|
||||||
|
*width = 0;
|
||||||
|
if (height)
|
||||||
|
*height = 0;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
_glfwPlatformGetMonitorWorkarea(monitor, xpos, ypos, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
|
||||||
|
if (widthMM)
|
||||||
|
*widthMM = 0;
|
||||||
|
if (heightMM)
|
||||||
|
*heightMM = 0;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (widthMM)
|
||||||
|
*widthMM = monitor->widthMM;
|
||||||
|
if (heightMM)
|
||||||
|
*heightMM = monitor->heightMM;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle,
|
||||||
|
float* xscale, float* yscale)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
|
||||||
|
if (xscale)
|
||||||
|
*xscale = 0.f;
|
||||||
|
if (yscale)
|
||||||
|
*yscale = 0.f;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
_glfwPlatformGetMonitorContentScale(monitor, xscale, yscale);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
return monitor->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* handle, void* pointer)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
monitor->userPointer = pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* handle)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
return monitor->userPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(_glfw.callbacks.monitor, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
assert(count != NULL);
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (!refreshVideoModes(monitor))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*count = monitor->modeCount;
|
||||||
|
return monitor->modes;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
_glfwPlatformGetVideoMode(monitor, &monitor->currentMode);
|
||||||
|
return &monitor->currentMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
unsigned short* values;
|
||||||
|
GLFWgammaramp ramp;
|
||||||
|
const GLFWgammaramp* original;
|
||||||
|
assert(handle != NULL);
|
||||||
|
assert(gamma > 0.f);
|
||||||
|
assert(gamma <= FLT_MAX);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
original = glfwGetGammaRamp(handle);
|
||||||
|
if (!original)
|
||||||
|
return;
|
||||||
|
|
||||||
|
values = calloc(original->size, sizeof(unsigned short));
|
||||||
|
|
||||||
|
for (i = 0; i < original->size; i++)
|
||||||
|
{
|
||||||
|
float value;
|
||||||
|
|
||||||
|
// Calculate intensity
|
||||||
|
value = i / (float) (original->size - 1);
|
||||||
|
// Apply gamma curve
|
||||||
|
value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
|
||||||
|
// Clamp to value range
|
||||||
|
value = _glfw_fminf(value, 65535.f);
|
||||||
|
|
||||||
|
values[i] = (unsigned short) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ramp.red = values;
|
||||||
|
ramp.green = values;
|
||||||
|
ramp.blue = values;
|
||||||
|
ramp.size = original->size;
|
||||||
|
|
||||||
|
glfwSetGammaRamp(handle, &ramp);
|
||||||
|
free(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
_glfwFreeGammaArrays(&monitor->currentRamp);
|
||||||
|
if (!_glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &monitor->currentRamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
assert(ramp != NULL);
|
||||||
|
assert(ramp->size > 0);
|
||||||
|
assert(ramp->red != NULL);
|
||||||
|
assert(ramp->green != NULL);
|
||||||
|
assert(ramp->blue != NULL);
|
||||||
|
|
||||||
|
if (ramp->size <= 0)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Invalid gamma ramp size %i",
|
||||||
|
ramp->size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
if (!monitor->originalRamp.size)
|
||||||
|
{
|
||||||
|
if (!_glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPlatformSetGammaRamp(monitor, ramp);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 macOS - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
// NOTE: Many Cocoa enum values have been renamed and we need to build across
|
||||||
|
// SDK versions where one is unavailable or the other deprecated
|
||||||
|
// We use the newer names in code and these macros to handle compatibility
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101400
|
||||||
|
#define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval
|
||||||
|
#define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl
|
||||||
|
|
||||||
|
#include <stdatomic.h>
|
||||||
|
|
||||||
|
|
||||||
|
// NSGL-specific per-context data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWcontextNSGL
|
||||||
|
{
|
||||||
|
id pixelFormat;
|
||||||
|
id object;
|
||||||
|
|
||||||
|
} _GLFWcontextNSGL;
|
||||||
|
|
||||||
|
// NSGL-specific global data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWlibraryNSGL
|
||||||
|
{
|
||||||
|
// dlopen handle for OpenGL.framework (for glfwGetProcAddress)
|
||||||
|
CFBundleRef framework;
|
||||||
|
|
||||||
|
} _GLFWlibraryNSGL;
|
||||||
|
|
||||||
|
|
||||||
|
GLFWbool _glfwInitNSGL(void);
|
||||||
|
void _glfwTerminateNSGL(void);
|
||||||
|
GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig);
|
||||||
|
void _glfwDestroyContextNSGL(_GLFWwindow* window);
|
||||||
|
|
|
@ -0,0 +1,376 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 macOS - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
static void makeContextCurrentNSGL(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
|
if (window)
|
||||||
|
[window->context.nsgl.object makeCurrentContext];
|
||||||
|
else
|
||||||
|
[NSOpenGLContext clearCurrentContext];
|
||||||
|
|
||||||
|
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||||
|
|
||||||
|
} // autoreleasepool
|
||||||
|
}
|
||||||
|
|
||||||
|
static void swapBuffersNSGL(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
|
// HACK: Simulate vsync with usleep as NSGL swap interval does not apply to
|
||||||
|
// windows with a non-visible occlusion state
|
||||||
|
if (window->ns.occluded)
|
||||||
|
{
|
||||||
|
int interval = 0;
|
||||||
|
[window->context.nsgl.object getValues:&interval
|
||||||
|
forParameter:NSOpenGLContextParameterSwapInterval];
|
||||||
|
|
||||||
|
if (interval > 0)
|
||||||
|
{
|
||||||
|
const double framerate = 60.0;
|
||||||
|
const uint64_t frequency = _glfwPlatformGetTimerFrequency();
|
||||||
|
const uint64_t value = _glfwPlatformGetTimerValue();
|
||||||
|
|
||||||
|
const double elapsed = value / (double) frequency;
|
||||||
|
const double period = 1.0 / framerate;
|
||||||
|
const double delay = period - fmod(elapsed, period);
|
||||||
|
|
||||||
|
usleep(floorl(delay * 1e6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[window->context.nsgl.object flushBuffer];
|
||||||
|
|
||||||
|
} // autoreleasepool
|
||||||
|
}
|
||||||
|
|
||||||
|
static void swapIntervalNSGL(int interval)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
|
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
|
if (window)
|
||||||
|
{
|
||||||
|
[window->context.nsgl.object setValues:&interval
|
||||||
|
forParameter:NSOpenGLContextParameterSwapInterval];
|
||||||
|
}
|
||||||
|
|
||||||
|
} // autoreleasepool
|
||||||
|
}
|
||||||
|
|
||||||
|
static int extensionSupportedNSGL(const char* extension)
|
||||||
|
{
|
||||||
|
// There are no NSGL extensions
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLFWglproc getProcAddressNSGL(const char* procname)
|
||||||
|
{
|
||||||
|
CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault,
|
||||||
|
procname,
|
||||||
|
kCFStringEncodingASCII);
|
||||||
|
|
||||||
|
GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework,
|
||||||
|
symbolName);
|
||||||
|
|
||||||
|
CFRelease(symbolName);
|
||||||
|
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroyContextNSGL(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
|
[window->context.nsgl.pixelFormat release];
|
||||||
|
window->context.nsgl.pixelFormat = nil;
|
||||||
|
|
||||||
|
[window->context.nsgl.object release];
|
||||||
|
window->context.nsgl.object = nil;
|
||||||
|
|
||||||
|
} // autoreleasepool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Initialize OpenGL support
|
||||||
|
//
|
||||||
|
GLFWbool _glfwInitNSGL(void)
|
||||||
|
{
|
||||||
|
if (_glfw.nsgl.framework)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
_glfw.nsgl.framework =
|
||||||
|
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
|
||||||
|
if (_glfw.nsgl.framework == NULL)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"NSGL: Failed to locate OpenGL framework");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Terminate OpenGL support
|
||||||
|
//
|
||||||
|
void _glfwTerminateNSGL(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the OpenGL context
|
||||||
|
//
|
||||||
|
GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig)
|
||||||
|
{
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"NSGL: OpenGL ES is not available on macOS");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->major > 2)
|
||||||
|
{
|
||||||
|
if (ctxconfig->major == 3 && ctxconfig->minor < 2)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"NSGL: The targeted version of macOS does not support OpenGL 3.0 or 3.1 but may support 3.2 and above");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ctxconfig->forward || ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"NSGL: The targeted version of macOS only supports forward-compatible core profile contexts for OpenGL 3.2 and above");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Context robustness modes (GL_KHR_robustness) are not yet supported by
|
||||||
|
// macOS but are not a hard constraint, so ignore and continue
|
||||||
|
|
||||||
|
// Context release behaviors (GL_KHR_context_flush_control) are not yet
|
||||||
|
// supported by macOS but are not a hard constraint, so ignore and continue
|
||||||
|
|
||||||
|
// Debug contexts (GL_KHR_debug) are not yet supported by macOS but are not
|
||||||
|
// a hard constraint, so ignore and continue
|
||||||
|
|
||||||
|
// No-error contexts (GL_KHR_no_error) are not yet supported by macOS but
|
||||||
|
// are not a hard constraint, so ignore and continue
|
||||||
|
|
||||||
|
#define addAttrib(a) \
|
||||||
|
{ \
|
||||||
|
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||||
|
attribs[index++] = a; \
|
||||||
|
}
|
||||||
|
#define setAttrib(a, v) { addAttrib(a); addAttrib(v); }
|
||||||
|
|
||||||
|
NSOpenGLPixelFormatAttribute attribs[40];
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
addAttrib(NSOpenGLPFAAccelerated);
|
||||||
|
addAttrib(NSOpenGLPFAClosestPolicy);
|
||||||
|
|
||||||
|
if (ctxconfig->nsgl.offline)
|
||||||
|
{
|
||||||
|
addAttrib(NSOpenGLPFAAllowOfflineRenderers);
|
||||||
|
// NOTE: This replaces the NSSupportsAutomaticGraphicsSwitching key in
|
||||||
|
// Info.plist for unbundled applications
|
||||||
|
// HACK: This assumes that NSOpenGLPixelFormat will remain
|
||||||
|
// a straightforward wrapper of its CGL counterpart
|
||||||
|
addAttrib(kCGLPFASupportsAutomaticGraphicsSwitching);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
|
||||||
|
if (ctxconfig->major >= 4)
|
||||||
|
{
|
||||||
|
setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
||||||
|
if (ctxconfig->major >= 3)
|
||||||
|
{
|
||||||
|
setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->major <= 2)
|
||||||
|
{
|
||||||
|
if (fbconfig->auxBuffers != GLFW_DONT_CARE)
|
||||||
|
setAttrib(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
|
||||||
|
|
||||||
|
if (fbconfig->accumRedBits != GLFW_DONT_CARE &&
|
||||||
|
fbconfig->accumGreenBits != GLFW_DONT_CARE &&
|
||||||
|
fbconfig->accumBlueBits != GLFW_DONT_CARE &&
|
||||||
|
fbconfig->accumAlphaBits != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
const int accumBits = fbconfig->accumRedBits +
|
||||||
|
fbconfig->accumGreenBits +
|
||||||
|
fbconfig->accumBlueBits +
|
||||||
|
fbconfig->accumAlphaBits;
|
||||||
|
|
||||||
|
setAttrib(NSOpenGLPFAAccumSize, accumBits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fbconfig->redBits != GLFW_DONT_CARE &&
|
||||||
|
fbconfig->greenBits != GLFW_DONT_CARE &&
|
||||||
|
fbconfig->blueBits != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
int colorBits = fbconfig->redBits +
|
||||||
|
fbconfig->greenBits +
|
||||||
|
fbconfig->blueBits;
|
||||||
|
|
||||||
|
// macOS needs non-zero color size, so set reasonable values
|
||||||
|
if (colorBits == 0)
|
||||||
|
colorBits = 24;
|
||||||
|
else if (colorBits < 15)
|
||||||
|
colorBits = 15;
|
||||||
|
|
||||||
|
setAttrib(NSOpenGLPFAColorSize, colorBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fbconfig->alphaBits != GLFW_DONT_CARE)
|
||||||
|
setAttrib(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
|
||||||
|
|
||||||
|
if (fbconfig->depthBits != GLFW_DONT_CARE)
|
||||||
|
setAttrib(NSOpenGLPFADepthSize, fbconfig->depthBits);
|
||||||
|
|
||||||
|
if (fbconfig->stencilBits != GLFW_DONT_CARE)
|
||||||
|
setAttrib(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
|
||||||
|
|
||||||
|
if (fbconfig->stereo)
|
||||||
|
{
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
|
||||||
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
|
"NSGL: Stereo rendering is deprecated");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
#else
|
||||||
|
addAttrib(NSOpenGLPFAStereo);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fbconfig->doublebuffer)
|
||||||
|
addAttrib(NSOpenGLPFADoubleBuffer);
|
||||||
|
|
||||||
|
if (fbconfig->samples != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
if (fbconfig->samples == 0)
|
||||||
|
{
|
||||||
|
setAttrib(NSOpenGLPFASampleBuffers, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setAttrib(NSOpenGLPFASampleBuffers, 1);
|
||||||
|
setAttrib(NSOpenGLPFASamples, fbconfig->samples);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
|
||||||
|
// framebuffer, so there's no need (and no way) to request it
|
||||||
|
|
||||||
|
addAttrib(0);
|
||||||
|
|
||||||
|
#undef addAttrib
|
||||||
|
#undef setAttrib
|
||||||
|
|
||||||
|
window->context.nsgl.pixelFormat =
|
||||||
|
[[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
|
||||||
|
if (window->context.nsgl.pixelFormat == nil)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
|
"NSGL: Failed to find a suitable pixel format");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSOpenGLContext* share = nil;
|
||||||
|
|
||||||
|
if (ctxconfig->share)
|
||||||
|
share = ctxconfig->share->context.nsgl.object;
|
||||||
|
|
||||||
|
window->context.nsgl.object =
|
||||||
|
[[NSOpenGLContext alloc] initWithFormat:window->context.nsgl.pixelFormat
|
||||||
|
shareContext:share];
|
||||||
|
if (window->context.nsgl.object == nil)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"NSGL: Failed to create OpenGL context");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fbconfig->transparent)
|
||||||
|
{
|
||||||
|
GLint opaque = 0;
|
||||||
|
[window->context.nsgl.object setValues:&opaque
|
||||||
|
forParameter:NSOpenGLContextParameterSurfaceOpacity];
|
||||||
|
}
|
||||||
|
|
||||||
|
[window->ns.view setWantsBestResolutionOpenGLSurface:window->ns.retina];
|
||||||
|
|
||||||
|
[window->context.nsgl.object setView:window->ns.view];
|
||||||
|
|
||||||
|
window->context.makeCurrent = makeContextCurrentNSGL;
|
||||||
|
window->context.swapBuffers = swapBuffersNSGL;
|
||||||
|
window->context.swapInterval = swapIntervalNSGL;
|
||||||
|
window->context.extensionSupported = extensionSupportedNSGL;
|
||||||
|
window->context.getProcAddress = getProcAddressNSGL;
|
||||||
|
window->context.destroy = destroyContextNSGL;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW native API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(nil);
|
||||||
|
|
||||||
|
if (window->context.client == GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window->context.nsgl.object;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2016 Google Inc.
|
||||||
|
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int _glfwPlatformInit(void)
|
||||||
|
{
|
||||||
|
_glfwInitTimerPOSIX();
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformTerminate(void)
|
||||||
|
{
|
||||||
|
_glfwTerminateOSMesa();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
|
{
|
||||||
|
return _GLFW_VERSION_NUMBER " null OSMesa";
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_JOYSTICK_STATE struct { int dummyJoystick; }
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE struct { int dummyLibraryJoystick; }
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_MAPPING_NAME ""
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2016 Google Inc.
|
||||||
|
// Copyright (c) 2016-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||||
|
float* xscale, float* yscale)
|
||||||
|
{
|
||||||
|
if (xscale)
|
||||||
|
*xscale = 1.f;
|
||||||
|
if (yscale)
|
||||||
|
*yscale = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
|
||||||
|
int* xpos, int* ypos,
|
||||||
|
int* width, int* height)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2016 Google Inc.
|
||||||
|
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNull null
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_CONTEXT_STATE struct { int dummyContext; }
|
||||||
|
#define _GLFW_PLATFORM_MONITOR_STATE struct { int dummyMonitor; }
|
||||||
|
#define _GLFW_PLATFORM_CURSOR_STATE struct { int dummyCursor; }
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE struct { int dummyLibraryWindow; }
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE struct { int dummyLibraryContext; }
|
||||||
|
#define _GLFW_EGL_CONTEXT_STATE struct { int dummyEGLContext; }
|
||||||
|
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE struct { int dummyEGLLibraryContext; }
|
||||||
|
|
||||||
|
#include "osmesa_context.h"
|
||||||
|
#include "posix_time.h"
|
||||||
|
#include "posix_thread.h"
|
||||||
|
#include "null_joystick.h"
|
||||||
|
|
||||||
|
#if defined(_GLFW_WIN32)
|
||||||
|
#define _glfw_dlopen(name) LoadLibraryA(name)
|
||||||
|
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
|
||||||
|
#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
|
||||||
|
#else
|
||||||
|
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||||
|
#define _glfw_dlclose(handle) dlclose(handle)
|
||||||
|
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Null-specific per-window data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWwindowNull
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
} _GLFWwindowNull;
|
||||||
|
|
|
@ -0,0 +1,332 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2016 Google Inc.
|
||||||
|
// Copyright (c) 2016-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
static int createNativeWindow(_GLFWwindow* window,
|
||||||
|
const _GLFWwndconfig* wndconfig)
|
||||||
|
{
|
||||||
|
window->null.width = wndconfig->width;
|
||||||
|
window->null.height = wndconfig->height;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||||
|
const _GLFWwndconfig* wndconfig,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig)
|
||||||
|
{
|
||||||
|
if (!createNativeWindow(window, wndconfig))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (ctxconfig->client != GLFW_NO_API)
|
||||||
|
{
|
||||||
|
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API ||
|
||||||
|
ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
||||||
|
{
|
||||||
|
if (!_glfwInitOSMesa())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "Null: EGL not available");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window->context.destroy)
|
||||||
|
window->context.destroy(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count,
|
||||||
|
const GLFWimage* images)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||||
|
_GLFWmonitor* monitor,
|
||||||
|
int xpos, int ypos,
|
||||||
|
int width, int height,
|
||||||
|
int refreshRate)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
||||||
|
{
|
||||||
|
if (width)
|
||||||
|
*width = window->null.width;
|
||||||
|
if (height)
|
||||||
|
*height = window->null.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||||
|
{
|
||||||
|
window->null.width = width;
|
||||||
|
window->null.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||||
|
int minwidth, int minheight,
|
||||||
|
int maxwidth, int maxheight)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int n, int d)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
|
||||||
|
{
|
||||||
|
if (width)
|
||||||
|
*width = window->null.width;
|
||||||
|
if (height)
|
||||||
|
*height = window->null.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||||
|
int* left, int* top,
|
||||||
|
int* right, int* bottom)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
||||||
|
float* xscale, float* yscale)
|
||||||
|
{
|
||||||
|
if (xscale)
|
||||||
|
*xscale = 1.f;
|
||||||
|
if (yscale)
|
||||||
|
*yscale = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWbool _glfwPlatformRawMouseMotionSupported(void)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformPollEvents(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformWaitEvents(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformPostEmptyEvent(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||||
|
const GLFWimage* image,
|
||||||
|
int xhot, int yhot)
|
||||||
|
{
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||||
|
{
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetClipboardString(const char* string)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* _glfwPlatformGetClipboardString(void)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformGetKeyScancode(int key)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||||
|
VkPhysicalDevice device,
|
||||||
|
uint32_t queuefamily)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||||
|
_GLFWwindow* window,
|
||||||
|
const VkAllocationCallbacks* allocator,
|
||||||
|
VkSurfaceKHR* surface)
|
||||||
|
{
|
||||||
|
// This seems like the most appropriate error to return here
|
||||||
|
return VK_ERROR_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,372 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 OSMesa - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2016 Google Inc.
|
||||||
|
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void makeContextCurrentOSMesa(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window)
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
_glfwPlatformGetFramebufferSize(window, &width, &height);
|
||||||
|
|
||||||
|
// Check to see if we need to allocate a new buffer
|
||||||
|
if ((window->context.osmesa.buffer == NULL) ||
|
||||||
|
(width != window->context.osmesa.width) ||
|
||||||
|
(height != window->context.osmesa.height))
|
||||||
|
{
|
||||||
|
free(window->context.osmesa.buffer);
|
||||||
|
|
||||||
|
// Allocate the new buffer (width * height * 8-bit RGBA)
|
||||||
|
window->context.osmesa.buffer = calloc(4, (size_t) width * height);
|
||||||
|
window->context.osmesa.width = width;
|
||||||
|
window->context.osmesa.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!OSMesaMakeCurrent(window->context.osmesa.handle,
|
||||||
|
window->context.osmesa.buffer,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
|
width, height))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"OSMesa: Failed to make context current");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLFWglproc getProcAddressOSMesa(const char* procname)
|
||||||
|
{
|
||||||
|
return (GLFWglproc) OSMesaGetProcAddress(procname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroyContextOSMesa(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window->context.osmesa.handle)
|
||||||
|
{
|
||||||
|
OSMesaDestroyContext(window->context.osmesa.handle);
|
||||||
|
window->context.osmesa.handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->context.osmesa.buffer)
|
||||||
|
{
|
||||||
|
free(window->context.osmesa.buffer);
|
||||||
|
window->context.osmesa.width = 0;
|
||||||
|
window->context.osmesa.height = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void swapBuffersOSMesa(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
// No double buffering on OSMesa
|
||||||
|
}
|
||||||
|
|
||||||
|
static void swapIntervalOSMesa(int interval)
|
||||||
|
{
|
||||||
|
// No swap interval on OSMesa
|
||||||
|
}
|
||||||
|
|
||||||
|
static int extensionSupportedOSMesa(const char* extension)
|
||||||
|
{
|
||||||
|
// OSMesa does not have extensions
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWbool _glfwInitOSMesa(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char* sonames[] =
|
||||||
|
{
|
||||||
|
#if defined(_GLFW_OSMESA_LIBRARY)
|
||||||
|
_GLFW_OSMESA_LIBRARY,
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
"libOSMesa.dll",
|
||||||
|
"OSMesa.dll",
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
"libOSMesa.8.dylib",
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
|
"libOSMesa-8.so",
|
||||||
|
#else
|
||||||
|
"libOSMesa.so.8",
|
||||||
|
"libOSMesa.so.6",
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_glfw.osmesa.handle)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
for (i = 0; sonames[i]; i++)
|
||||||
|
{
|
||||||
|
_glfw.osmesa.handle = _glfw_dlopen(sonames[i]);
|
||||||
|
if (_glfw.osmesa.handle)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_glfw.osmesa.handle)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt)
|
||||||
|
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextExt");
|
||||||
|
_glfw.osmesa.CreateContextAttribs = (PFN_OSMesaCreateContextAttribs)
|
||||||
|
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextAttribs");
|
||||||
|
_glfw.osmesa.DestroyContext = (PFN_OSMesaDestroyContext)
|
||||||
|
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaDestroyContext");
|
||||||
|
_glfw.osmesa.MakeCurrent = (PFN_OSMesaMakeCurrent)
|
||||||
|
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaMakeCurrent");
|
||||||
|
_glfw.osmesa.GetColorBuffer = (PFN_OSMesaGetColorBuffer)
|
||||||
|
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetColorBuffer");
|
||||||
|
_glfw.osmesa.GetDepthBuffer = (PFN_OSMesaGetDepthBuffer)
|
||||||
|
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetDepthBuffer");
|
||||||
|
_glfw.osmesa.GetProcAddress = (PFN_OSMesaGetProcAddress)
|
||||||
|
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetProcAddress");
|
||||||
|
|
||||||
|
if (!_glfw.osmesa.CreateContextExt ||
|
||||||
|
!_glfw.osmesa.DestroyContext ||
|
||||||
|
!_glfw.osmesa.MakeCurrent ||
|
||||||
|
!_glfw.osmesa.GetColorBuffer ||
|
||||||
|
!_glfw.osmesa.GetDepthBuffer ||
|
||||||
|
!_glfw.osmesa.GetProcAddress)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"OSMesa: Failed to load required entry points");
|
||||||
|
|
||||||
|
_glfwTerminateOSMesa();
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwTerminateOSMesa(void)
|
||||||
|
{
|
||||||
|
if (_glfw.osmesa.handle)
|
||||||
|
{
|
||||||
|
_glfw_dlclose(_glfw.osmesa.handle);
|
||||||
|
_glfw.osmesa.handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define setAttrib(a, v) \
|
||||||
|
{ \
|
||||||
|
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||||
|
attribs[index++] = a; \
|
||||||
|
attribs[index++] = v; \
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig)
|
||||||
|
{
|
||||||
|
OSMesaContext share = NULL;
|
||||||
|
const int accumBits = fbconfig->accumRedBits +
|
||||||
|
fbconfig->accumGreenBits +
|
||||||
|
fbconfig->accumBlueBits +
|
||||||
|
fbconfig->accumAlphaBits;
|
||||||
|
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"OSMesa: OpenGL ES is not available on OSMesa");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->share)
|
||||||
|
share = ctxconfig->share->context.osmesa.handle;
|
||||||
|
|
||||||
|
if (OSMesaCreateContextAttribs)
|
||||||
|
{
|
||||||
|
int index = 0, attribs[40];
|
||||||
|
|
||||||
|
setAttrib(OSMESA_FORMAT, OSMESA_RGBA);
|
||||||
|
setAttrib(OSMESA_DEPTH_BITS, fbconfig->depthBits);
|
||||||
|
setAttrib(OSMESA_STENCIL_BITS, fbconfig->stencilBits);
|
||||||
|
setAttrib(OSMESA_ACCUM_BITS, accumBits);
|
||||||
|
|
||||||
|
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
||||||
|
{
|
||||||
|
setAttrib(OSMESA_PROFILE, OSMESA_CORE_PROFILE);
|
||||||
|
}
|
||||||
|
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
||||||
|
{
|
||||||
|
setAttrib(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||||
|
{
|
||||||
|
setAttrib(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major);
|
||||||
|
setAttrib(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->forward)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"OSMesa: Forward-compatible contexts not supported");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
setAttrib(0, 0);
|
||||||
|
|
||||||
|
window->context.osmesa.handle =
|
||||||
|
OSMesaCreateContextAttribs(attribs, share);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ctxconfig->profile)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"OSMesa: OpenGL profiles unavailable");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->context.osmesa.handle =
|
||||||
|
OSMesaCreateContextExt(OSMESA_RGBA,
|
||||||
|
fbconfig->depthBits,
|
||||||
|
fbconfig->stencilBits,
|
||||||
|
accumBits,
|
||||||
|
share);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->context.osmesa.handle == NULL)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"OSMesa: Failed to create context");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->context.makeCurrent = makeContextCurrentOSMesa;
|
||||||
|
window->context.swapBuffers = swapBuffersOSMesa;
|
||||||
|
window->context.swapInterval = swapIntervalOSMesa;
|
||||||
|
window->context.extensionSupported = extensionSupportedOSMesa;
|
||||||
|
window->context.getProcAddress = getProcAddressOSMesa;
|
||||||
|
window->context.destroy = destroyContextOSMesa;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef setAttrib
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW native API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
|
||||||
|
int* height, int* format, void** buffer)
|
||||||
|
{
|
||||||
|
void* mesaBuffer;
|
||||||
|
GLint mesaWidth, mesaHeight, mesaFormat;
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
|
||||||
|
if (!OSMesaGetColorBuffer(window->context.osmesa.handle,
|
||||||
|
&mesaWidth, &mesaHeight,
|
||||||
|
&mesaFormat, &mesaBuffer))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"OSMesa: Failed to retrieve color buffer");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width)
|
||||||
|
*width = mesaWidth;
|
||||||
|
if (height)
|
||||||
|
*height = mesaHeight;
|
||||||
|
if (format)
|
||||||
|
*format = mesaFormat;
|
||||||
|
if (buffer)
|
||||||
|
*buffer = mesaBuffer;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
|
||||||
|
int* width, int* height,
|
||||||
|
int* bytesPerValue,
|
||||||
|
void** buffer)
|
||||||
|
{
|
||||||
|
void* mesaBuffer;
|
||||||
|
GLint mesaWidth, mesaHeight, mesaBytes;
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
|
||||||
|
if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,
|
||||||
|
&mesaWidth, &mesaHeight,
|
||||||
|
&mesaBytes, &mesaBuffer))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"OSMesa: Failed to retrieve depth buffer");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width)
|
||||||
|
*width = mesaWidth;
|
||||||
|
if (height)
|
||||||
|
*height = mesaHeight;
|
||||||
|
if (bytesPerValue)
|
||||||
|
*bytesPerValue = mesaBytes;
|
||||||
|
if (buffer)
|
||||||
|
*buffer = mesaBuffer;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (window->context.client == GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window->context.osmesa.handle;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 OSMesa - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2016 Google Inc.
|
||||||
|
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#define OSMESA_RGBA 0x1908
|
||||||
|
#define OSMESA_FORMAT 0x22
|
||||||
|
#define OSMESA_DEPTH_BITS 0x30
|
||||||
|
#define OSMESA_STENCIL_BITS 0x31
|
||||||
|
#define OSMESA_ACCUM_BITS 0x32
|
||||||
|
#define OSMESA_PROFILE 0x33
|
||||||
|
#define OSMESA_CORE_PROFILE 0x34
|
||||||
|
#define OSMESA_COMPAT_PROFILE 0x35
|
||||||
|
#define OSMESA_CONTEXT_MAJOR_VERSION 0x36
|
||||||
|
#define OSMESA_CONTEXT_MINOR_VERSION 0x37
|
||||||
|
|
||||||
|
typedef void* OSMesaContext;
|
||||||
|
typedef void (*OSMESAproc)(void);
|
||||||
|
|
||||||
|
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextExt)(GLenum,GLint,GLint,GLint,OSMesaContext);
|
||||||
|
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextAttribs)(const int*,OSMesaContext);
|
||||||
|
typedef void (GLAPIENTRY * PFN_OSMesaDestroyContext)(OSMesaContext);
|
||||||
|
typedef int (GLAPIENTRY * PFN_OSMesaMakeCurrent)(OSMesaContext,void*,int,int,int);
|
||||||
|
typedef int (GLAPIENTRY * PFN_OSMesaGetColorBuffer)(OSMesaContext,int*,int*,int*,void**);
|
||||||
|
typedef int (GLAPIENTRY * PFN_OSMesaGetDepthBuffer)(OSMesaContext,int*,int*,int*,void**);
|
||||||
|
typedef GLFWglproc (GLAPIENTRY * PFN_OSMesaGetProcAddress)(const char*);
|
||||||
|
#define OSMesaCreateContextExt _glfw.osmesa.CreateContextExt
|
||||||
|
#define OSMesaCreateContextAttribs _glfw.osmesa.CreateContextAttribs
|
||||||
|
#define OSMesaDestroyContext _glfw.osmesa.DestroyContext
|
||||||
|
#define OSMesaMakeCurrent _glfw.osmesa.MakeCurrent
|
||||||
|
#define OSMesaGetColorBuffer _glfw.osmesa.GetColorBuffer
|
||||||
|
#define OSMesaGetDepthBuffer _glfw.osmesa.GetDepthBuffer
|
||||||
|
#define OSMesaGetProcAddress _glfw.osmesa.GetProcAddress
|
||||||
|
|
||||||
|
#define _GLFW_OSMESA_CONTEXT_STATE _GLFWcontextOSMesa osmesa
|
||||||
|
#define _GLFW_OSMESA_LIBRARY_CONTEXT_STATE _GLFWlibraryOSMesa osmesa
|
||||||
|
|
||||||
|
|
||||||
|
// OSMesa-specific per-context data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWcontextOSMesa
|
||||||
|
{
|
||||||
|
OSMesaContext handle;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
void* buffer;
|
||||||
|
|
||||||
|
} _GLFWcontextOSMesa;
|
||||||
|
|
||||||
|
// OSMesa-specific global data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWlibraryOSMesa
|
||||||
|
{
|
||||||
|
void* handle;
|
||||||
|
|
||||||
|
PFN_OSMesaCreateContextExt CreateContextExt;
|
||||||
|
PFN_OSMesaCreateContextAttribs CreateContextAttribs;
|
||||||
|
PFN_OSMesaDestroyContext DestroyContext;
|
||||||
|
PFN_OSMesaMakeCurrent MakeCurrent;
|
||||||
|
PFN_OSMesaGetColorBuffer GetColorBuffer;
|
||||||
|
PFN_OSMesaGetDepthBuffer GetDepthBuffer;
|
||||||
|
PFN_OSMesaGetProcAddress GetProcAddress;
|
||||||
|
|
||||||
|
} _GLFWlibraryOSMesa;
|
||||||
|
|
||||||
|
|
||||||
|
GLFWbool _glfwInitOSMesa(void);
|
||||||
|
void _glfwTerminateOSMesa(void);
|
||||||
|
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig);
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 POSIX - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
|
||||||
|
{
|
||||||
|
assert(tls->posix.allocated == GLFW_FALSE);
|
||||||
|
|
||||||
|
if (pthread_key_create(&tls->posix.key, NULL) != 0)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"POSIX: Failed to create context TLS");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
tls->posix.allocated = GLFW_TRUE;
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
||||||
|
{
|
||||||
|
if (tls->posix.allocated)
|
||||||
|
pthread_key_delete(tls->posix.key);
|
||||||
|
memset(tls, 0, sizeof(_GLFWtls));
|
||||||
|
}
|
||||||
|
|
||||||
|
void* _glfwPlatformGetTls(_GLFWtls* tls)
|
||||||
|
{
|
||||||
|
assert(tls->posix.allocated == GLFW_TRUE);
|
||||||
|
return pthread_getspecific(tls->posix.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
|
||||||
|
{
|
||||||
|
assert(tls->posix.allocated == GLFW_TRUE);
|
||||||
|
pthread_setspecific(tls->posix.key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
|
||||||
|
{
|
||||||
|
assert(mutex->posix.allocated == GLFW_FALSE);
|
||||||
|
|
||||||
|
if (pthread_mutex_init(&mutex->posix.handle, NULL) != 0)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "POSIX: Failed to create mutex");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mutex->posix.allocated = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
|
||||||
|
{
|
||||||
|
if (mutex->posix.allocated)
|
||||||
|
pthread_mutex_destroy(&mutex->posix.handle);
|
||||||
|
memset(mutex, 0, sizeof(_GLFWmutex));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformLockMutex(_GLFWmutex* mutex)
|
||||||
|
{
|
||||||
|
assert(mutex->posix.allocated == GLFW_TRUE);
|
||||||
|
pthread_mutex_lock(&mutex->posix.handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
|
||||||
|
{
|
||||||
|
assert(mutex->posix.allocated == GLFW_TRUE);
|
||||||
|
pthread_mutex_unlock(&mutex->posix.handle);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 POSIX - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsPOSIX posix
|
||||||
|
#define _GLFW_PLATFORM_MUTEX_STATE _GLFWmutexPOSIX posix
|
||||||
|
|
||||||
|
|
||||||
|
// POSIX-specific thread local storage data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWtlsPOSIX
|
||||||
|
{
|
||||||
|
GLFWbool allocated;
|
||||||
|
pthread_key_t key;
|
||||||
|
|
||||||
|
} _GLFWtlsPOSIX;
|
||||||
|
|
||||||
|
// POSIX-specific mutex data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWmutexPOSIX
|
||||||
|
{
|
||||||
|
GLFWbool allocated;
|
||||||
|
pthread_mutex_t handle;
|
||||||
|
|
||||||
|
} _GLFWmutexPOSIX;
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 POSIX - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Initialise timer
|
||||||
|
//
|
||||||
|
void _glfwInitTimerPOSIX(void)
|
||||||
|
{
|
||||||
|
#if defined(CLOCK_MONOTONIC)
|
||||||
|
struct timespec ts;
|
||||||
|
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
||||||
|
{
|
||||||
|
_glfw.timer.posix.monotonic = GLFW_TRUE;
|
||||||
|
_glfw.timer.posix.frequency = 1000000000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
_glfw.timer.posix.monotonic = GLFW_FALSE;
|
||||||
|
_glfw.timer.posix.frequency = 1000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
uint64_t _glfwPlatformGetTimerValue(void)
|
||||||
|
{
|
||||||
|
#if defined(CLOCK_MONOTONIC)
|
||||||
|
if (_glfw.timer.posix.monotonic)
|
||||||
|
{
|
||||||
|
struct timespec ts;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
|
return (uint64_t) ts.tv_sec * (uint64_t) 1000000000 + (uint64_t) ts.tv_nsec;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
return (uint64_t) tv.tv_sec * (uint64_t) 1000000 + (uint64_t) tv.tv_usec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t _glfwPlatformGetTimerFrequency(void)
|
||||||
|
{
|
||||||
|
return _glfw.timer.posix.frequency;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 POSIX - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerPOSIX posix
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
// POSIX-specific global timer data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWtimerPOSIX
|
||||||
|
{
|
||||||
|
GLFWbool monotonic;
|
||||||
|
uint64_t frequency;
|
||||||
|
|
||||||
|
} _GLFWtimerPOSIX;
|
||||||
|
|
||||||
|
|
||||||
|
void _glfwInitTimerPOSIX(void);
|
||||||
|
|
|
@ -0,0 +1,332 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define _GLFW_FIND_LOADER 1
|
||||||
|
#define _GLFW_REQUIRE_LOADER 2
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWbool _glfwInitVulkan(int mode)
|
||||||
|
{
|
||||||
|
VkResult err;
|
||||||
|
VkExtensionProperties* ep;
|
||||||
|
uint32_t i, count;
|
||||||
|
|
||||||
|
if (_glfw.vk.available)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
#if !defined(_GLFW_VULKAN_STATIC)
|
||||||
|
#if defined(_GLFW_VULKAN_LIBRARY)
|
||||||
|
_glfw.vk.handle = _glfw_dlopen(_GLFW_VULKAN_LIBRARY);
|
||||||
|
#elif defined(_GLFW_WIN32)
|
||||||
|
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
|
||||||
|
#elif defined(_GLFW_COCOA)
|
||||||
|
_glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
|
||||||
|
if (!_glfw.vk.handle)
|
||||||
|
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS();
|
||||||
|
#else
|
||||||
|
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
|
||||||
|
#endif
|
||||||
|
if (!_glfw.vk.handle)
|
||||||
|
{
|
||||||
|
if (mode == _GLFW_REQUIRE_LOADER)
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
|
||||||
|
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
|
||||||
|
_glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
|
||||||
|
if (!_glfw.vk.GetInstanceProcAddr)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"Vulkan: Loader does not export vkGetInstanceProcAddr");
|
||||||
|
|
||||||
|
_glfwTerminateVulkan();
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)
|
||||||
|
vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties");
|
||||||
|
if (!_glfw.vk.EnumerateInstanceExtensionProperties)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties");
|
||||||
|
|
||||||
|
_glfwTerminateVulkan();
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
#endif // _GLFW_VULKAN_STATIC
|
||||||
|
|
||||||
|
err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
// NOTE: This happens on systems with a loader but without any Vulkan ICD
|
||||||
|
if (mode == _GLFW_REQUIRE_LOADER)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"Vulkan: Failed to query instance extension count: %s",
|
||||||
|
_glfwGetVulkanResultString(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwTerminateVulkan();
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ep = calloc(count, sizeof(VkExtensionProperties));
|
||||||
|
|
||||||
|
err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"Vulkan: Failed to query instance extensions: %s",
|
||||||
|
_glfwGetVulkanResultString(err));
|
||||||
|
|
||||||
|
free(ep);
|
||||||
|
_glfwTerminateVulkan();
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
|
||||||
|
_glfw.vk.KHR_surface = GLFW_TRUE;
|
||||||
|
#if defined(_GLFW_WIN32)
|
||||||
|
else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
|
||||||
|
_glfw.vk.KHR_win32_surface = GLFW_TRUE;
|
||||||
|
#elif defined(_GLFW_COCOA)
|
||||||
|
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
|
||||||
|
_glfw.vk.MVK_macos_surface = GLFW_TRUE;
|
||||||
|
else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0)
|
||||||
|
_glfw.vk.EXT_metal_surface = GLFW_TRUE;
|
||||||
|
#elif defined(_GLFW_X11)
|
||||||
|
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
|
||||||
|
_glfw.vk.KHR_xlib_surface = GLFW_TRUE;
|
||||||
|
else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
|
||||||
|
_glfw.vk.KHR_xcb_surface = GLFW_TRUE;
|
||||||
|
#elif defined(_GLFW_WAYLAND)
|
||||||
|
else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
|
||||||
|
_glfw.vk.KHR_wayland_surface = GLFW_TRUE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ep);
|
||||||
|
|
||||||
|
_glfw.vk.available = GLFW_TRUE;
|
||||||
|
|
||||||
|
_glfwPlatformGetRequiredInstanceExtensions(_glfw.vk.extensions);
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwTerminateVulkan(void)
|
||||||
|
{
|
||||||
|
#if !defined(_GLFW_VULKAN_STATIC)
|
||||||
|
if (_glfw.vk.handle)
|
||||||
|
_glfw_dlclose(_glfw.vk.handle);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* _glfwGetVulkanResultString(VkResult result)
|
||||||
|
{
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case VK_SUCCESS:
|
||||||
|
return "Success";
|
||||||
|
case VK_NOT_READY:
|
||||||
|
return "A fence or query has not yet completed";
|
||||||
|
case VK_TIMEOUT:
|
||||||
|
return "A wait operation has not completed in the specified time";
|
||||||
|
case VK_EVENT_SET:
|
||||||
|
return "An event is signaled";
|
||||||
|
case VK_EVENT_RESET:
|
||||||
|
return "An event is unsignaled";
|
||||||
|
case VK_INCOMPLETE:
|
||||||
|
return "A return array was too small for the result";
|
||||||
|
case VK_ERROR_OUT_OF_HOST_MEMORY:
|
||||||
|
return "A host memory allocation has failed";
|
||||||
|
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
|
||||||
|
return "A device memory allocation has failed";
|
||||||
|
case VK_ERROR_INITIALIZATION_FAILED:
|
||||||
|
return "Initialization of an object could not be completed for implementation-specific reasons";
|
||||||
|
case VK_ERROR_DEVICE_LOST:
|
||||||
|
return "The logical or physical device has been lost";
|
||||||
|
case VK_ERROR_MEMORY_MAP_FAILED:
|
||||||
|
return "Mapping of a memory object has failed";
|
||||||
|
case VK_ERROR_LAYER_NOT_PRESENT:
|
||||||
|
return "A requested layer is not present or could not be loaded";
|
||||||
|
case VK_ERROR_EXTENSION_NOT_PRESENT:
|
||||||
|
return "A requested extension is not supported";
|
||||||
|
case VK_ERROR_FEATURE_NOT_PRESENT:
|
||||||
|
return "A requested feature is not supported";
|
||||||
|
case VK_ERROR_INCOMPATIBLE_DRIVER:
|
||||||
|
return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible";
|
||||||
|
case VK_ERROR_TOO_MANY_OBJECTS:
|
||||||
|
return "Too many objects of the type have already been created";
|
||||||
|
case VK_ERROR_FORMAT_NOT_SUPPORTED:
|
||||||
|
return "A requested format is not supported on this device";
|
||||||
|
case VK_ERROR_SURFACE_LOST_KHR:
|
||||||
|
return "A surface is no longer available";
|
||||||
|
case VK_SUBOPTIMAL_KHR:
|
||||||
|
return "A swapchain no longer matches the surface properties exactly, but can still be used";
|
||||||
|
case VK_ERROR_OUT_OF_DATE_KHR:
|
||||||
|
return "A surface has changed in such a way that it is no longer compatible with the swapchain";
|
||||||
|
case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
|
||||||
|
return "The display used by a swapchain does not use the same presentable image layout";
|
||||||
|
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
|
||||||
|
return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API";
|
||||||
|
case VK_ERROR_VALIDATION_FAILED_EXT:
|
||||||
|
return "A validation layer found an error";
|
||||||
|
default:
|
||||||
|
return "ERROR: UNKNOWN VULKAN ERROR";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW public API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI int glfwVulkanSupported(void)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
return _glfwInitVulkan(_GLFW_FIND_LOADER);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
|
||||||
|
{
|
||||||
|
assert(count != NULL);
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!_glfw.vk.extensions[0])
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*count = 2;
|
||||||
|
return (const char**) _glfw.vk.extensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
|
||||||
|
const char* procname)
|
||||||
|
{
|
||||||
|
GLFWvkproc proc;
|
||||||
|
assert(procname != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
|
||||||
|
#if defined(_GLFW_VULKAN_STATIC)
|
||||||
|
if (!proc)
|
||||||
|
{
|
||||||
|
if (strcmp(procname, "vkGetInstanceProcAddr") == 0)
|
||||||
|
return (GLFWvkproc) vkGetInstanceProcAddr;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (!proc)
|
||||||
|
proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return proc;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||||
|
VkPhysicalDevice device,
|
||||||
|
uint32_t queuefamily)
|
||||||
|
{
|
||||||
|
assert(instance != VK_NULL_HANDLE);
|
||||||
|
assert(device != VK_NULL_HANDLE);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
|
||||||
|
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (!_glfw.vk.extensions[0])
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"Vulkan: Window surface creation extensions not found");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _glfwPlatformGetPhysicalDevicePresentationSupport(instance,
|
||||||
|
device,
|
||||||
|
queuefamily);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
|
||||||
|
GLFWwindow* handle,
|
||||||
|
const VkAllocationCallbacks* allocator,
|
||||||
|
VkSurfaceKHR* surface)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(instance != VK_NULL_HANDLE);
|
||||||
|
assert(window != NULL);
|
||||||
|
assert(surface != NULL);
|
||||||
|
|
||||||
|
*surface = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
|
||||||
|
|
||||||
|
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||||
|
return VK_ERROR_INITIALIZATION_FAILED;
|
||||||
|
|
||||||
|
if (!_glfw.vk.extensions[0])
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"Vulkan: Window surface creation extensions not found");
|
||||||
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->context.client != GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"Vulkan: Window surface creation requires the window to have the client API set to GLFW_NO_API");
|
||||||
|
return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,796 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 WGL - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
// Return the value corresponding to the specified attribute
|
||||||
|
//
|
||||||
|
static int findPixelFormatAttribValue(const int* attribs,
|
||||||
|
int attribCount,
|
||||||
|
const int* values,
|
||||||
|
int attrib)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < attribCount; i++)
|
||||||
|
{
|
||||||
|
if (attribs[i] == attrib)
|
||||||
|
return values[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Unknown pixel format attribute requested");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define addAttrib(a) \
|
||||||
|
{ \
|
||||||
|
assert((size_t) attribCount < sizeof(attribs) / sizeof(attribs[0])); \
|
||||||
|
attribs[attribCount++] = a; \
|
||||||
|
}
|
||||||
|
#define findAttribValue(a) \
|
||||||
|
findPixelFormatAttribValue(attribs, attribCount, values, a)
|
||||||
|
|
||||||
|
// Return a list of available and usable framebuffer configs
|
||||||
|
//
|
||||||
|
static int choosePixelFormat(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig)
|
||||||
|
{
|
||||||
|
_GLFWfbconfig* usableConfigs;
|
||||||
|
const _GLFWfbconfig* closest;
|
||||||
|
int i, pixelFormat, nativeCount, usableCount = 0, attribCount = 0;
|
||||||
|
int attribs[40];
|
||||||
|
int values[sizeof(attribs) / sizeof(attribs[0])];
|
||||||
|
|
||||||
|
if (_glfw.wgl.ARB_pixel_format)
|
||||||
|
{
|
||||||
|
const int attrib = WGL_NUMBER_PIXEL_FORMATS_ARB;
|
||||||
|
|
||||||
|
if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc,
|
||||||
|
1, 0, 1, &attrib, &nativeCount))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to retrieve pixel format attribute");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
addAttrib(WGL_SUPPORT_OPENGL_ARB);
|
||||||
|
addAttrib(WGL_DRAW_TO_WINDOW_ARB);
|
||||||
|
addAttrib(WGL_PIXEL_TYPE_ARB);
|
||||||
|
addAttrib(WGL_ACCELERATION_ARB);
|
||||||
|
addAttrib(WGL_RED_BITS_ARB);
|
||||||
|
addAttrib(WGL_RED_SHIFT_ARB);
|
||||||
|
addAttrib(WGL_GREEN_BITS_ARB);
|
||||||
|
addAttrib(WGL_GREEN_SHIFT_ARB);
|
||||||
|
addAttrib(WGL_BLUE_BITS_ARB);
|
||||||
|
addAttrib(WGL_BLUE_SHIFT_ARB);
|
||||||
|
addAttrib(WGL_ALPHA_BITS_ARB);
|
||||||
|
addAttrib(WGL_ALPHA_SHIFT_ARB);
|
||||||
|
addAttrib(WGL_DEPTH_BITS_ARB);
|
||||||
|
addAttrib(WGL_STENCIL_BITS_ARB);
|
||||||
|
addAttrib(WGL_ACCUM_BITS_ARB);
|
||||||
|
addAttrib(WGL_ACCUM_RED_BITS_ARB);
|
||||||
|
addAttrib(WGL_ACCUM_GREEN_BITS_ARB);
|
||||||
|
addAttrib(WGL_ACCUM_BLUE_BITS_ARB);
|
||||||
|
addAttrib(WGL_ACCUM_ALPHA_BITS_ARB);
|
||||||
|
addAttrib(WGL_AUX_BUFFERS_ARB);
|
||||||
|
addAttrib(WGL_STEREO_ARB);
|
||||||
|
addAttrib(WGL_DOUBLE_BUFFER_ARB);
|
||||||
|
|
||||||
|
if (_glfw.wgl.ARB_multisample)
|
||||||
|
addAttrib(WGL_SAMPLES_ARB);
|
||||||
|
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
|
{
|
||||||
|
if (_glfw.wgl.ARB_framebuffer_sRGB || _glfw.wgl.EXT_framebuffer_sRGB)
|
||||||
|
addAttrib(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_glfw.wgl.EXT_colorspace)
|
||||||
|
addAttrib(WGL_COLORSPACE_EXT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nativeCount = DescribePixelFormat(window->context.wgl.dc,
|
||||||
|
1,
|
||||||
|
sizeof(PIXELFORMATDESCRIPTOR),
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
||||||
|
|
||||||
|
for (i = 0; i < nativeCount; i++)
|
||||||
|
{
|
||||||
|
_GLFWfbconfig* u = usableConfigs + usableCount;
|
||||||
|
pixelFormat = i + 1;
|
||||||
|
|
||||||
|
if (_glfw.wgl.ARB_pixel_format)
|
||||||
|
{
|
||||||
|
// Get pixel format attributes through "modern" extension
|
||||||
|
|
||||||
|
if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc,
|
||||||
|
pixelFormat, 0,
|
||||||
|
attribCount,
|
||||||
|
attribs, values))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to retrieve pixel format attributes");
|
||||||
|
|
||||||
|
free(usableConfigs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!findAttribValue(WGL_SUPPORT_OPENGL_ARB) ||
|
||||||
|
!findAttribValue(WGL_DRAW_TO_WINDOW_ARB))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (findAttribValue(WGL_PIXEL_TYPE_ARB) != WGL_TYPE_RGBA_ARB)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (findAttribValue(WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
u->redBits = findAttribValue(WGL_RED_BITS_ARB);
|
||||||
|
u->greenBits = findAttribValue(WGL_GREEN_BITS_ARB);
|
||||||
|
u->blueBits = findAttribValue(WGL_BLUE_BITS_ARB);
|
||||||
|
u->alphaBits = findAttribValue(WGL_ALPHA_BITS_ARB);
|
||||||
|
|
||||||
|
u->depthBits = findAttribValue(WGL_DEPTH_BITS_ARB);
|
||||||
|
u->stencilBits = findAttribValue(WGL_STENCIL_BITS_ARB);
|
||||||
|
|
||||||
|
u->accumRedBits = findAttribValue(WGL_ACCUM_RED_BITS_ARB);
|
||||||
|
u->accumGreenBits = findAttribValue(WGL_ACCUM_GREEN_BITS_ARB);
|
||||||
|
u->accumBlueBits = findAttribValue(WGL_ACCUM_BLUE_BITS_ARB);
|
||||||
|
u->accumAlphaBits = findAttribValue(WGL_ACCUM_ALPHA_BITS_ARB);
|
||||||
|
|
||||||
|
u->auxBuffers = findAttribValue(WGL_AUX_BUFFERS_ARB);
|
||||||
|
|
||||||
|
if (findAttribValue(WGL_STEREO_ARB))
|
||||||
|
u->stereo = GLFW_TRUE;
|
||||||
|
if (findAttribValue(WGL_DOUBLE_BUFFER_ARB))
|
||||||
|
u->doublebuffer = GLFW_TRUE;
|
||||||
|
|
||||||
|
if (_glfw.wgl.ARB_multisample)
|
||||||
|
u->samples = findAttribValue(WGL_SAMPLES_ARB);
|
||||||
|
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
|
{
|
||||||
|
if (_glfw.wgl.ARB_framebuffer_sRGB ||
|
||||||
|
_glfw.wgl.EXT_framebuffer_sRGB)
|
||||||
|
{
|
||||||
|
if (findAttribValue(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
|
||||||
|
u->sRGB = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_glfw.wgl.EXT_colorspace)
|
||||||
|
{
|
||||||
|
if (findAttribValue(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT)
|
||||||
|
u->sRGB = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Get pixel format attributes through legacy PFDs
|
||||||
|
|
||||||
|
PIXELFORMATDESCRIPTOR pfd;
|
||||||
|
|
||||||
|
if (!DescribePixelFormat(window->context.wgl.dc,
|
||||||
|
pixelFormat,
|
||||||
|
sizeof(PIXELFORMATDESCRIPTOR),
|
||||||
|
&pfd))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to describe pixel format");
|
||||||
|
|
||||||
|
free(usableConfigs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
|
||||||
|
!(pfd.dwFlags & PFD_SUPPORT_OPENGL))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) &&
|
||||||
|
(pfd.dwFlags & PFD_GENERIC_FORMAT))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pfd.iPixelType != PFD_TYPE_RGBA)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
u->redBits = pfd.cRedBits;
|
||||||
|
u->greenBits = pfd.cGreenBits;
|
||||||
|
u->blueBits = pfd.cBlueBits;
|
||||||
|
u->alphaBits = pfd.cAlphaBits;
|
||||||
|
|
||||||
|
u->depthBits = pfd.cDepthBits;
|
||||||
|
u->stencilBits = pfd.cStencilBits;
|
||||||
|
|
||||||
|
u->accumRedBits = pfd.cAccumRedBits;
|
||||||
|
u->accumGreenBits = pfd.cAccumGreenBits;
|
||||||
|
u->accumBlueBits = pfd.cAccumBlueBits;
|
||||||
|
u->accumAlphaBits = pfd.cAccumAlphaBits;
|
||||||
|
|
||||||
|
u->auxBuffers = pfd.cAuxBuffers;
|
||||||
|
|
||||||
|
if (pfd.dwFlags & PFD_STEREO)
|
||||||
|
u->stereo = GLFW_TRUE;
|
||||||
|
if (pfd.dwFlags & PFD_DOUBLEBUFFER)
|
||||||
|
u->doublebuffer = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
u->handle = pixelFormat;
|
||||||
|
usableCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!usableCount)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"WGL: The driver does not appear to support OpenGL");
|
||||||
|
|
||||||
|
free(usableConfigs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
|
||||||
|
if (!closest)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
|
"WGL: Failed to find a suitable pixel format");
|
||||||
|
|
||||||
|
free(usableConfigs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixelFormat = (int) closest->handle;
|
||||||
|
free(usableConfigs);
|
||||||
|
|
||||||
|
return pixelFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef addAttrib
|
||||||
|
#undef findAttribValue
|
||||||
|
|
||||||
|
static void makeContextCurrentWGL(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window)
|
||||||
|
{
|
||||||
|
if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
|
||||||
|
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to make context current");
|
||||||
|
_glfwPlatformSetTls(&_glfw.contextSlot, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!wglMakeCurrent(NULL, NULL))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to clear current context");
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPlatformSetTls(&_glfw.contextSlot, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void swapBuffersWGL(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (!window->monitor)
|
||||||
|
{
|
||||||
|
if (IsWindowsVistaOrGreater())
|
||||||
|
{
|
||||||
|
// DWM Composition is always enabled on Win8+
|
||||||
|
BOOL enabled = IsWindows8OrGreater();
|
||||||
|
|
||||||
|
// HACK: Use DwmFlush when desktop composition is enabled
|
||||||
|
if (enabled ||
|
||||||
|
(SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled))
|
||||||
|
{
|
||||||
|
int count = abs(window->context.wgl.interval);
|
||||||
|
while (count--)
|
||||||
|
DwmFlush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SwapBuffers(window->context.wgl.dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void swapIntervalWGL(int interval)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
|
|
||||||
|
window->context.wgl.interval = interval;
|
||||||
|
|
||||||
|
if (!window->monitor)
|
||||||
|
{
|
||||||
|
if (IsWindowsVistaOrGreater())
|
||||||
|
{
|
||||||
|
// DWM Composition is always enabled on Win8+
|
||||||
|
BOOL enabled = IsWindows8OrGreater();
|
||||||
|
|
||||||
|
// HACK: Disable WGL swap interval when desktop composition is enabled to
|
||||||
|
// avoid interfering with DWM vsync
|
||||||
|
if (enabled ||
|
||||||
|
(SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled))
|
||||||
|
interval = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.wgl.EXT_swap_control)
|
||||||
|
wglSwapIntervalEXT(interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int extensionSupportedWGL(const char* extension)
|
||||||
|
{
|
||||||
|
const char* extensions = NULL;
|
||||||
|
|
||||||
|
if (_glfw.wgl.GetExtensionsStringARB)
|
||||||
|
extensions = wglGetExtensionsStringARB(wglGetCurrentDC());
|
||||||
|
else if (_glfw.wgl.GetExtensionsStringEXT)
|
||||||
|
extensions = wglGetExtensionsStringEXT();
|
||||||
|
|
||||||
|
if (!extensions)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
return _glfwStringInExtensionString(extension, extensions);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLFWglproc getProcAddressWGL(const char* procname)
|
||||||
|
{
|
||||||
|
const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
|
||||||
|
if (proc)
|
||||||
|
return proc;
|
||||||
|
|
||||||
|
return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroyContextWGL(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window->context.wgl.handle)
|
||||||
|
{
|
||||||
|
wglDeleteContext(window->context.wgl.handle);
|
||||||
|
window->context.wgl.handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Initialize WGL
|
||||||
|
//
|
||||||
|
GLFWbool _glfwInitWGL(void)
|
||||||
|
{
|
||||||
|
PIXELFORMATDESCRIPTOR pfd;
|
||||||
|
HGLRC prc, rc;
|
||||||
|
HDC pdc, dc;
|
||||||
|
|
||||||
|
if (_glfw.wgl.instance)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
|
||||||
|
if (!_glfw.wgl.instance)
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to load opengl32.dll");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.wgl.CreateContext = (PFN_wglCreateContext)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
|
||||||
|
_glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
|
||||||
|
_glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
|
||||||
|
_glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
|
||||||
|
_glfw.wgl.GetCurrentContext = (PFN_wglGetCurrentContext)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentContext");
|
||||||
|
_glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
|
||||||
|
_glfw.wgl.ShareLists = (PFN_wglShareLists)
|
||||||
|
GetProcAddress(_glfw.wgl.instance, "wglShareLists");
|
||||||
|
|
||||||
|
// NOTE: A dummy context has to be created for opengl32.dll to load the
|
||||||
|
// OpenGL ICD, from which we can then query WGL extensions
|
||||||
|
// NOTE: This code will accept the Microsoft GDI ICD; accelerated context
|
||||||
|
// creation failure occurs during manual pixel format enumeration
|
||||||
|
|
||||||
|
dc = GetDC(_glfw.win32.helperWindowHandle);
|
||||||
|
|
||||||
|
ZeroMemory(&pfd, sizeof(pfd));
|
||||||
|
pfd.nSize = sizeof(pfd);
|
||||||
|
pfd.nVersion = 1;
|
||||||
|
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||||||
|
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||||
|
pfd.cColorBits = 24;
|
||||||
|
|
||||||
|
if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to set pixel format for dummy context");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = wglCreateContext(dc);
|
||||||
|
if (!rc)
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to create dummy context");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdc = wglGetCurrentDC();
|
||||||
|
prc = wglGetCurrentContext();
|
||||||
|
|
||||||
|
if (!wglMakeCurrent(dc, rc))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to make dummy context current");
|
||||||
|
wglMakeCurrent(pdc, prc);
|
||||||
|
wglDeleteContext(rc);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Functions must be loaded first as they're needed to retrieve the
|
||||||
|
// extension string that tells us whether the functions are supported
|
||||||
|
_glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
|
||||||
|
wglGetProcAddress("wglGetExtensionsStringEXT");
|
||||||
|
_glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
|
||||||
|
wglGetProcAddress("wglGetExtensionsStringARB");
|
||||||
|
_glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
|
||||||
|
wglGetProcAddress("wglCreateContextAttribsARB");
|
||||||
|
_glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
|
||||||
|
wglGetProcAddress("wglSwapIntervalEXT");
|
||||||
|
_glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
|
||||||
|
wglGetProcAddress("wglGetPixelFormatAttribivARB");
|
||||||
|
|
||||||
|
// NOTE: WGL_ARB_extensions_string and WGL_EXT_extensions_string are not
|
||||||
|
// checked below as we are already using them
|
||||||
|
_glfw.wgl.ARB_multisample =
|
||||||
|
extensionSupportedWGL("WGL_ARB_multisample");
|
||||||
|
_glfw.wgl.ARB_framebuffer_sRGB =
|
||||||
|
extensionSupportedWGL("WGL_ARB_framebuffer_sRGB");
|
||||||
|
_glfw.wgl.EXT_framebuffer_sRGB =
|
||||||
|
extensionSupportedWGL("WGL_EXT_framebuffer_sRGB");
|
||||||
|
_glfw.wgl.ARB_create_context =
|
||||||
|
extensionSupportedWGL("WGL_ARB_create_context");
|
||||||
|
_glfw.wgl.ARB_create_context_profile =
|
||||||
|
extensionSupportedWGL("WGL_ARB_create_context_profile");
|
||||||
|
_glfw.wgl.EXT_create_context_es2_profile =
|
||||||
|
extensionSupportedWGL("WGL_EXT_create_context_es2_profile");
|
||||||
|
_glfw.wgl.ARB_create_context_robustness =
|
||||||
|
extensionSupportedWGL("WGL_ARB_create_context_robustness");
|
||||||
|
_glfw.wgl.ARB_create_context_no_error =
|
||||||
|
extensionSupportedWGL("WGL_ARB_create_context_no_error");
|
||||||
|
_glfw.wgl.EXT_swap_control =
|
||||||
|
extensionSupportedWGL("WGL_EXT_swap_control");
|
||||||
|
_glfw.wgl.EXT_colorspace =
|
||||||
|
extensionSupportedWGL("WGL_EXT_colorspace");
|
||||||
|
_glfw.wgl.ARB_pixel_format =
|
||||||
|
extensionSupportedWGL("WGL_ARB_pixel_format");
|
||||||
|
_glfw.wgl.ARB_context_flush_control =
|
||||||
|
extensionSupportedWGL("WGL_ARB_context_flush_control");
|
||||||
|
|
||||||
|
wglMakeCurrent(pdc, prc);
|
||||||
|
wglDeleteContext(rc);
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Terminate WGL
|
||||||
|
//
|
||||||
|
void _glfwTerminateWGL(void)
|
||||||
|
{
|
||||||
|
if (_glfw.wgl.instance)
|
||||||
|
FreeLibrary(_glfw.wgl.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define setAttrib(a, v) \
|
||||||
|
{ \
|
||||||
|
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||||
|
attribs[index++] = a; \
|
||||||
|
attribs[index++] = v; \
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the OpenGL or OpenGL ES context
|
||||||
|
//
|
||||||
|
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig)
|
||||||
|
{
|
||||||
|
int attribs[40];
|
||||||
|
int pixelFormat;
|
||||||
|
PIXELFORMATDESCRIPTOR pfd;
|
||||||
|
HGLRC share = NULL;
|
||||||
|
|
||||||
|
if (ctxconfig->share)
|
||||||
|
share = ctxconfig->share->context.wgl.handle;
|
||||||
|
|
||||||
|
window->context.wgl.dc = GetDC(window->win32.handle);
|
||||||
|
if (!window->context.wgl.dc)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to retrieve DC for window");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig);
|
||||||
|
if (!pixelFormat)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (!DescribePixelFormat(window->context.wgl.dc,
|
||||||
|
pixelFormat, sizeof(pfd), &pfd))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to retrieve PFD for selected pixel format");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to set selected pixel format");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
|
{
|
||||||
|
if (ctxconfig->forward)
|
||||||
|
{
|
||||||
|
if (!_glfw.wgl.ARB_create_context)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->profile)
|
||||||
|
{
|
||||||
|
if (!_glfw.wgl.ARB_create_context_profile)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!_glfw.wgl.ARB_create_context ||
|
||||||
|
!_glfw.wgl.ARB_create_context_profile ||
|
||||||
|
!_glfw.wgl.EXT_create_context_es2_profile)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.wgl.ARB_create_context)
|
||||||
|
{
|
||||||
|
int index = 0, mask = 0, flags = 0;
|
||||||
|
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
|
{
|
||||||
|
if (ctxconfig->forward)
|
||||||
|
flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
|
||||||
|
|
||||||
|
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
||||||
|
mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||||
|
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
||||||
|
mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mask |= WGL_CONTEXT_ES2_PROFILE_BIT_EXT;
|
||||||
|
|
||||||
|
if (ctxconfig->debug)
|
||||||
|
flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
|
||||||
|
|
||||||
|
if (ctxconfig->robustness)
|
||||||
|
{
|
||||||
|
if (_glfw.wgl.ARB_create_context_robustness)
|
||||||
|
{
|
||||||
|
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||||
|
{
|
||||||
|
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||||
|
WGL_NO_RESET_NOTIFICATION_ARB);
|
||||||
|
}
|
||||||
|
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||||
|
{
|
||||||
|
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||||
|
WGL_LOSE_CONTEXT_ON_RESET_ARB);
|
||||||
|
}
|
||||||
|
|
||||||
|
flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->release)
|
||||||
|
{
|
||||||
|
if (_glfw.wgl.ARB_context_flush_control)
|
||||||
|
{
|
||||||
|
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||||
|
{
|
||||||
|
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||||
|
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||||
|
}
|
||||||
|
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||||
|
{
|
||||||
|
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||||
|
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxconfig->noerror)
|
||||||
|
{
|
||||||
|
if (_glfw.wgl.ARB_create_context_no_error)
|
||||||
|
setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Only request an explicitly versioned context when necessary, as
|
||||||
|
// explicitly requesting version 1.0 does not always return the
|
||||||
|
// highest version supported by the driver
|
||||||
|
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||||
|
{
|
||||||
|
setAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||||
|
setAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags)
|
||||||
|
setAttrib(WGL_CONTEXT_FLAGS_ARB, flags);
|
||||||
|
|
||||||
|
if (mask)
|
||||||
|
setAttrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||||
|
|
||||||
|
setAttrib(0, 0);
|
||||||
|
|
||||||
|
window->context.wgl.handle =
|
||||||
|
wglCreateContextAttribsARB(window->context.wgl.dc, share, attribs);
|
||||||
|
if (!window->context.wgl.handle)
|
||||||
|
{
|
||||||
|
const DWORD error = GetLastError();
|
||||||
|
|
||||||
|
if (error == (0xc0070000 | ERROR_INVALID_VERSION_ARB))
|
||||||
|
{
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"WGL: Driver does not support OpenGL version %i.%i",
|
||||||
|
ctxconfig->major,
|
||||||
|
ctxconfig->minor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"WGL: Driver does not support OpenGL ES version %i.%i",
|
||||||
|
ctxconfig->major,
|
||||||
|
ctxconfig->minor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (error == (0xc0070000 | ERROR_INVALID_PROFILE_ARB))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"WGL: Driver does not support the requested OpenGL profile");
|
||||||
|
}
|
||||||
|
else if (error == (0xc0070000 | ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
|
"WGL: The share context is not compatible with the requested context");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"WGL: Failed to create OpenGL context");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"WGL: Failed to create OpenGL ES context");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);
|
||||||
|
if (!window->context.wgl.handle)
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"WGL: Failed to create OpenGL context");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (share)
|
||||||
|
{
|
||||||
|
if (!wglShareLists(share, window->context.wgl.handle))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to enable sharing with specified OpenGL context");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window->context.makeCurrent = makeContextCurrentWGL;
|
||||||
|
window->context.swapBuffers = swapBuffersWGL;
|
||||||
|
window->context.swapInterval = swapIntervalWGL;
|
||||||
|
window->context.extensionSupported = extensionSupportedWGL;
|
||||||
|
window->context.getProcAddress = getProcAddressWGL;
|
||||||
|
window->context.destroy = destroyContextWGL;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef setAttrib
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW native API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (window->context.client == GLFW_NO_API)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window->context.wgl.handle;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 WGL - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
|
||||||
|
#define WGL_SUPPORT_OPENGL_ARB 0x2010
|
||||||
|
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
|
||||||
|
#define WGL_PIXEL_TYPE_ARB 0x2013
|
||||||
|
#define WGL_TYPE_RGBA_ARB 0x202b
|
||||||
|
#define WGL_ACCELERATION_ARB 0x2003
|
||||||
|
#define WGL_NO_ACCELERATION_ARB 0x2025
|
||||||
|
#define WGL_RED_BITS_ARB 0x2015
|
||||||
|
#define WGL_RED_SHIFT_ARB 0x2016
|
||||||
|
#define WGL_GREEN_BITS_ARB 0x2017
|
||||||
|
#define WGL_GREEN_SHIFT_ARB 0x2018
|
||||||
|
#define WGL_BLUE_BITS_ARB 0x2019
|
||||||
|
#define WGL_BLUE_SHIFT_ARB 0x201a
|
||||||
|
#define WGL_ALPHA_BITS_ARB 0x201b
|
||||||
|
#define WGL_ALPHA_SHIFT_ARB 0x201c
|
||||||
|
#define WGL_ACCUM_BITS_ARB 0x201d
|
||||||
|
#define WGL_ACCUM_RED_BITS_ARB 0x201e
|
||||||
|
#define WGL_ACCUM_GREEN_BITS_ARB 0x201f
|
||||||
|
#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
|
||||||
|
#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
|
||||||
|
#define WGL_DEPTH_BITS_ARB 0x2022
|
||||||
|
#define WGL_STENCIL_BITS_ARB 0x2023
|
||||||
|
#define WGL_AUX_BUFFERS_ARB 0x2024
|
||||||
|
#define WGL_STEREO_ARB 0x2012
|
||||||
|
#define WGL_DOUBLE_BUFFER_ARB 0x2011
|
||||||
|
#define WGL_SAMPLES_ARB 0x2042
|
||||||
|
#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9
|
||||||
|
#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
|
||||||
|
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
|
||||||
|
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
|
||||||
|
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
|
||||||
|
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
|
||||||
|
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||||
|
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||||
|
#define WGL_CONTEXT_FLAGS_ARB 0x2094
|
||||||
|
#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
|
||||||
|
#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
|
||||||
|
#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
|
||||||
|
#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
|
||||||
|
#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261
|
||||||
|
#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
|
||||||
|
#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
|
||||||
|
#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
|
||||||
|
#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
|
||||||
|
#define WGL_COLORSPACE_EXT 0x309d
|
||||||
|
#define WGL_COLORSPACE_SRGB_EXT 0x3089
|
||||||
|
|
||||||
|
#define ERROR_INVALID_VERSION_ARB 0x2095
|
||||||
|
#define ERROR_INVALID_PROFILE_ARB 0x2096
|
||||||
|
#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
|
||||||
|
|
||||||
|
// WGL extension pointer typedefs
|
||||||
|
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
|
||||||
|
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
|
||||||
|
typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void);
|
||||||
|
typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC);
|
||||||
|
typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC,HGLRC,const int*);
|
||||||
|
#define wglSwapIntervalEXT _glfw.wgl.SwapIntervalEXT
|
||||||
|
#define wglGetPixelFormatAttribivARB _glfw.wgl.GetPixelFormatAttribivARB
|
||||||
|
#define wglGetExtensionsStringEXT _glfw.wgl.GetExtensionsStringEXT
|
||||||
|
#define wglGetExtensionsStringARB _glfw.wgl.GetExtensionsStringARB
|
||||||
|
#define wglCreateContextAttribsARB _glfw.wgl.CreateContextAttribsARB
|
||||||
|
|
||||||
|
// opengl32.dll function pointer typedefs
|
||||||
|
typedef HGLRC (WINAPI * PFN_wglCreateContext)(HDC);
|
||||||
|
typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC);
|
||||||
|
typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR);
|
||||||
|
typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void);
|
||||||
|
typedef HGLRC (WINAPI * PFN_wglGetCurrentContext)(void);
|
||||||
|
typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC);
|
||||||
|
typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
|
||||||
|
#define wglCreateContext _glfw.wgl.CreateContext
|
||||||
|
#define wglDeleteContext _glfw.wgl.DeleteContext
|
||||||
|
#define wglGetProcAddress _glfw.wgl.GetProcAddress
|
||||||
|
#define wglGetCurrentDC _glfw.wgl.GetCurrentDC
|
||||||
|
#define wglGetCurrentContext _glfw.wgl.GetCurrentContext
|
||||||
|
#define wglMakeCurrent _glfw.wgl.MakeCurrent
|
||||||
|
#define wglShareLists _glfw.wgl.ShareLists
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL wgl
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl
|
||||||
|
|
||||||
|
|
||||||
|
// WGL-specific per-context data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWcontextWGL
|
||||||
|
{
|
||||||
|
HDC dc;
|
||||||
|
HGLRC handle;
|
||||||
|
int interval;
|
||||||
|
|
||||||
|
} _GLFWcontextWGL;
|
||||||
|
|
||||||
|
// WGL-specific global data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWlibraryWGL
|
||||||
|
{
|
||||||
|
HINSTANCE instance;
|
||||||
|
PFN_wglCreateContext CreateContext;
|
||||||
|
PFN_wglDeleteContext DeleteContext;
|
||||||
|
PFN_wglGetProcAddress GetProcAddress;
|
||||||
|
PFN_wglGetCurrentDC GetCurrentDC;
|
||||||
|
PFN_wglGetCurrentContext GetCurrentContext;
|
||||||
|
PFN_wglMakeCurrent MakeCurrent;
|
||||||
|
PFN_wglShareLists ShareLists;
|
||||||
|
|
||||||
|
PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;
|
||||||
|
PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB;
|
||||||
|
PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;
|
||||||
|
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
|
||||||
|
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
||||||
|
GLFWbool EXT_swap_control;
|
||||||
|
GLFWbool EXT_colorspace;
|
||||||
|
GLFWbool ARB_multisample;
|
||||||
|
GLFWbool ARB_framebuffer_sRGB;
|
||||||
|
GLFWbool EXT_framebuffer_sRGB;
|
||||||
|
GLFWbool ARB_pixel_format;
|
||||||
|
GLFWbool ARB_create_context;
|
||||||
|
GLFWbool ARB_create_context_profile;
|
||||||
|
GLFWbool EXT_create_context_es2_profile;
|
||||||
|
GLFWbool ARB_create_context_robustness;
|
||||||
|
GLFWbool ARB_create_context_no_error;
|
||||||
|
GLFWbool ARB_context_flush_control;
|
||||||
|
|
||||||
|
} _GLFWlibraryWGL;
|
||||||
|
|
||||||
|
|
||||||
|
GLFWbool _glfwInitWGL(void);
|
||||||
|
void _glfwTerminateWGL(void);
|
||||||
|
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig);
|
||||||
|
|
|
@ -0,0 +1,633 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 Win32 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
|
||||||
|
|
||||||
|
// Executables (but not DLLs) exporting this symbol with this value will be
|
||||||
|
// automatically directed to the high-performance GPU on Nvidia Optimus systems
|
||||||
|
// with up-to-date drivers
|
||||||
|
//
|
||||||
|
__declspec(dllexport) DWORD NvOptimusEnablement = 1;
|
||||||
|
|
||||||
|
// Executables (but not DLLs) exporting this symbol with this value will be
|
||||||
|
// automatically directed to the high-performance GPU on AMD PowerXpress systems
|
||||||
|
// with up-to-date drivers
|
||||||
|
//
|
||||||
|
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||||
|
|
||||||
|
#endif // _GLFW_USE_HYBRID_HPG
|
||||||
|
|
||||||
|
#if defined(_GLFW_BUILD_DLL)
|
||||||
|
|
||||||
|
// GLFW DLL entry point
|
||||||
|
//
|
||||||
|
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _GLFW_BUILD_DLL
|
||||||
|
|
||||||
|
// Load necessary libraries (DLLs)
|
||||||
|
//
|
||||||
|
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");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.win32.winmm.GetTime = (PFN_timeGetTime)
|
||||||
|
GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
|
||||||
|
|
||||||
|
_glfw.win32.user32.instance = LoadLibraryA("user32.dll");
|
||||||
|
if (!_glfw.win32.user32.instance)
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to load user32.dll");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware)
|
||||||
|
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
|
||||||
|
_glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx)
|
||||||
|
GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
|
||||||
|
_glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling)
|
||||||
|
GetProcAddress(_glfw.win32.user32.instance, "EnableNonClientDpiScaling");
|
||||||
|
_glfw.win32.user32.SetProcessDpiAwarenessContext_ = (PFN_SetProcessDpiAwarenessContext)
|
||||||
|
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDpiAwarenessContext");
|
||||||
|
_glfw.win32.user32.GetDpiForWindow_ = (PFN_GetDpiForWindow)
|
||||||
|
GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow");
|
||||||
|
_glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
|
||||||
|
GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
|
||||||
|
|
||||||
|
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
|
||||||
|
if (_glfw.win32.dinput8.instance)
|
||||||
|
{
|
||||||
|
_glfw.win32.dinput8.Create = (PFN_DirectInput8Create)
|
||||||
|
GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char* names[] =
|
||||||
|
{
|
||||||
|
"xinput1_4.dll",
|
||||||
|
"xinput1_3.dll",
|
||||||
|
"xinput9_1_0.dll",
|
||||||
|
"xinput1_2.dll",
|
||||||
|
"xinput1_1.dll",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i = 0; names[i]; i++)
|
||||||
|
{
|
||||||
|
_glfw.win32.xinput.instance = LoadLibraryA(names[i]);
|
||||||
|
if (_glfw.win32.xinput.instance)
|
||||||
|
{
|
||||||
|
_glfw.win32.xinput.GetCapabilities = (PFN_XInputGetCapabilities)
|
||||||
|
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities");
|
||||||
|
_glfw.win32.xinput.GetState = (PFN_XInputGetState)
|
||||||
|
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
|
||||||
|
if (_glfw.win32.dwmapi.instance)
|
||||||
|
{
|
||||||
|
_glfw.win32.dwmapi.IsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
|
||||||
|
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
|
||||||
|
_glfw.win32.dwmapi.Flush = (PFN_DwmFlush)
|
||||||
|
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
|
||||||
|
_glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)
|
||||||
|
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
|
||||||
|
_glfw.win32.dwmapi.GetColorizationColor = (PFN_DwmGetColorizationColor)
|
||||||
|
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmGetColorizationColor");
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
|
||||||
|
if (_glfw.win32.shcore.instance)
|
||||||
|
{
|
||||||
|
_glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness)
|
||||||
|
GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
|
||||||
|
_glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor)
|
||||||
|
GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor");
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.win32.ntdll.instance = LoadLibraryA("ntdll.dll");
|
||||||
|
if (_glfw.win32.ntdll.instance)
|
||||||
|
{
|
||||||
|
_glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo)
|
||||||
|
GetProcAddress(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo");
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unload used libraries (DLLs)
|
||||||
|
//
|
||||||
|
static void freeLibraries(void)
|
||||||
|
{
|
||||||
|
if (_glfw.win32.xinput.instance)
|
||||||
|
FreeLibrary(_glfw.win32.xinput.instance);
|
||||||
|
|
||||||
|
if (_glfw.win32.dinput8.instance)
|
||||||
|
FreeLibrary(_glfw.win32.dinput8.instance);
|
||||||
|
|
||||||
|
if (_glfw.win32.winmm.instance)
|
||||||
|
FreeLibrary(_glfw.win32.winmm.instance);
|
||||||
|
|
||||||
|
if (_glfw.win32.user32.instance)
|
||||||
|
FreeLibrary(_glfw.win32.user32.instance);
|
||||||
|
|
||||||
|
if (_glfw.win32.dwmapi.instance)
|
||||||
|
FreeLibrary(_glfw.win32.dwmapi.instance);
|
||||||
|
|
||||||
|
if (_glfw.win32.shcore.instance)
|
||||||
|
FreeLibrary(_glfw.win32.shcore.instance);
|
||||||
|
|
||||||
|
if (_glfw.win32.ntdll.instance)
|
||||||
|
FreeLibrary(_glfw.win32.ntdll.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create key code translation tables
|
||||||
|
//
|
||||||
|
static void createKeyTables(void)
|
||||||
|
{
|
||||||
|
int scancode;
|
||||||
|
|
||||||
|
memset(_glfw.win32.keycodes, -1, sizeof(_glfw.win32.keycodes));
|
||||||
|
memset(_glfw.win32.scancodes, -1, sizeof(_glfw.win32.scancodes));
|
||||||
|
|
||||||
|
_glfw.win32.keycodes[0x00B] = GLFW_KEY_0;
|
||||||
|
_glfw.win32.keycodes[0x002] = GLFW_KEY_1;
|
||||||
|
_glfw.win32.keycodes[0x003] = GLFW_KEY_2;
|
||||||
|
_glfw.win32.keycodes[0x004] = GLFW_KEY_3;
|
||||||
|
_glfw.win32.keycodes[0x005] = GLFW_KEY_4;
|
||||||
|
_glfw.win32.keycodes[0x006] = GLFW_KEY_5;
|
||||||
|
_glfw.win32.keycodes[0x007] = GLFW_KEY_6;
|
||||||
|
_glfw.win32.keycodes[0x008] = GLFW_KEY_7;
|
||||||
|
_glfw.win32.keycodes[0x009] = GLFW_KEY_8;
|
||||||
|
_glfw.win32.keycodes[0x00A] = GLFW_KEY_9;
|
||||||
|
_glfw.win32.keycodes[0x01E] = GLFW_KEY_A;
|
||||||
|
_glfw.win32.keycodes[0x030] = GLFW_KEY_B;
|
||||||
|
_glfw.win32.keycodes[0x02E] = GLFW_KEY_C;
|
||||||
|
_glfw.win32.keycodes[0x020] = GLFW_KEY_D;
|
||||||
|
_glfw.win32.keycodes[0x012] = GLFW_KEY_E;
|
||||||
|
_glfw.win32.keycodes[0x021] = GLFW_KEY_F;
|
||||||
|
_glfw.win32.keycodes[0x022] = GLFW_KEY_G;
|
||||||
|
_glfw.win32.keycodes[0x023] = GLFW_KEY_H;
|
||||||
|
_glfw.win32.keycodes[0x017] = GLFW_KEY_I;
|
||||||
|
_glfw.win32.keycodes[0x024] = GLFW_KEY_J;
|
||||||
|
_glfw.win32.keycodes[0x025] = GLFW_KEY_K;
|
||||||
|
_glfw.win32.keycodes[0x026] = GLFW_KEY_L;
|
||||||
|
_glfw.win32.keycodes[0x032] = GLFW_KEY_M;
|
||||||
|
_glfw.win32.keycodes[0x031] = GLFW_KEY_N;
|
||||||
|
_glfw.win32.keycodes[0x018] = GLFW_KEY_O;
|
||||||
|
_glfw.win32.keycodes[0x019] = GLFW_KEY_P;
|
||||||
|
_glfw.win32.keycodes[0x010] = GLFW_KEY_Q;
|
||||||
|
_glfw.win32.keycodes[0x013] = GLFW_KEY_R;
|
||||||
|
_glfw.win32.keycodes[0x01F] = GLFW_KEY_S;
|
||||||
|
_glfw.win32.keycodes[0x014] = GLFW_KEY_T;
|
||||||
|
_glfw.win32.keycodes[0x016] = GLFW_KEY_U;
|
||||||
|
_glfw.win32.keycodes[0x02F] = GLFW_KEY_V;
|
||||||
|
_glfw.win32.keycodes[0x011] = GLFW_KEY_W;
|
||||||
|
_glfw.win32.keycodes[0x02D] = GLFW_KEY_X;
|
||||||
|
_glfw.win32.keycodes[0x015] = GLFW_KEY_Y;
|
||||||
|
_glfw.win32.keycodes[0x02C] = GLFW_KEY_Z;
|
||||||
|
|
||||||
|
_glfw.win32.keycodes[0x028] = GLFW_KEY_APOSTROPHE;
|
||||||
|
_glfw.win32.keycodes[0x02B] = GLFW_KEY_BACKSLASH;
|
||||||
|
_glfw.win32.keycodes[0x033] = GLFW_KEY_COMMA;
|
||||||
|
_glfw.win32.keycodes[0x00D] = GLFW_KEY_EQUAL;
|
||||||
|
_glfw.win32.keycodes[0x029] = GLFW_KEY_GRAVE_ACCENT;
|
||||||
|
_glfw.win32.keycodes[0x01A] = GLFW_KEY_LEFT_BRACKET;
|
||||||
|
_glfw.win32.keycodes[0x00C] = GLFW_KEY_MINUS;
|
||||||
|
_glfw.win32.keycodes[0x034] = GLFW_KEY_PERIOD;
|
||||||
|
_glfw.win32.keycodes[0x01B] = GLFW_KEY_RIGHT_BRACKET;
|
||||||
|
_glfw.win32.keycodes[0x027] = GLFW_KEY_SEMICOLON;
|
||||||
|
_glfw.win32.keycodes[0x035] = GLFW_KEY_SLASH;
|
||||||
|
_glfw.win32.keycodes[0x056] = GLFW_KEY_WORLD_2;
|
||||||
|
|
||||||
|
_glfw.win32.keycodes[0x00E] = GLFW_KEY_BACKSPACE;
|
||||||
|
_glfw.win32.keycodes[0x153] = GLFW_KEY_DELETE;
|
||||||
|
_glfw.win32.keycodes[0x14F] = GLFW_KEY_END;
|
||||||
|
_glfw.win32.keycodes[0x01C] = GLFW_KEY_ENTER;
|
||||||
|
_glfw.win32.keycodes[0x001] = GLFW_KEY_ESCAPE;
|
||||||
|
_glfw.win32.keycodes[0x147] = GLFW_KEY_HOME;
|
||||||
|
_glfw.win32.keycodes[0x152] = GLFW_KEY_INSERT;
|
||||||
|
_glfw.win32.keycodes[0x15D] = GLFW_KEY_MENU;
|
||||||
|
_glfw.win32.keycodes[0x151] = GLFW_KEY_PAGE_DOWN;
|
||||||
|
_glfw.win32.keycodes[0x149] = GLFW_KEY_PAGE_UP;
|
||||||
|
_glfw.win32.keycodes[0x045] = GLFW_KEY_PAUSE;
|
||||||
|
_glfw.win32.keycodes[0x146] = GLFW_KEY_PAUSE;
|
||||||
|
_glfw.win32.keycodes[0x039] = GLFW_KEY_SPACE;
|
||||||
|
_glfw.win32.keycodes[0x00F] = GLFW_KEY_TAB;
|
||||||
|
_glfw.win32.keycodes[0x03A] = GLFW_KEY_CAPS_LOCK;
|
||||||
|
_glfw.win32.keycodes[0x145] = GLFW_KEY_NUM_LOCK;
|
||||||
|
_glfw.win32.keycodes[0x046] = GLFW_KEY_SCROLL_LOCK;
|
||||||
|
_glfw.win32.keycodes[0x03B] = GLFW_KEY_F1;
|
||||||
|
_glfw.win32.keycodes[0x03C] = GLFW_KEY_F2;
|
||||||
|
_glfw.win32.keycodes[0x03D] = GLFW_KEY_F3;
|
||||||
|
_glfw.win32.keycodes[0x03E] = GLFW_KEY_F4;
|
||||||
|
_glfw.win32.keycodes[0x03F] = GLFW_KEY_F5;
|
||||||
|
_glfw.win32.keycodes[0x040] = GLFW_KEY_F6;
|
||||||
|
_glfw.win32.keycodes[0x041] = GLFW_KEY_F7;
|
||||||
|
_glfw.win32.keycodes[0x042] = GLFW_KEY_F8;
|
||||||
|
_glfw.win32.keycodes[0x043] = GLFW_KEY_F9;
|
||||||
|
_glfw.win32.keycodes[0x044] = GLFW_KEY_F10;
|
||||||
|
_glfw.win32.keycodes[0x057] = GLFW_KEY_F11;
|
||||||
|
_glfw.win32.keycodes[0x058] = GLFW_KEY_F12;
|
||||||
|
_glfw.win32.keycodes[0x064] = GLFW_KEY_F13;
|
||||||
|
_glfw.win32.keycodes[0x065] = GLFW_KEY_F14;
|
||||||
|
_glfw.win32.keycodes[0x066] = GLFW_KEY_F15;
|
||||||
|
_glfw.win32.keycodes[0x067] = GLFW_KEY_F16;
|
||||||
|
_glfw.win32.keycodes[0x068] = GLFW_KEY_F17;
|
||||||
|
_glfw.win32.keycodes[0x069] = GLFW_KEY_F18;
|
||||||
|
_glfw.win32.keycodes[0x06A] = GLFW_KEY_F19;
|
||||||
|
_glfw.win32.keycodes[0x06B] = GLFW_KEY_F20;
|
||||||
|
_glfw.win32.keycodes[0x06C] = GLFW_KEY_F21;
|
||||||
|
_glfw.win32.keycodes[0x06D] = GLFW_KEY_F22;
|
||||||
|
_glfw.win32.keycodes[0x06E] = GLFW_KEY_F23;
|
||||||
|
_glfw.win32.keycodes[0x076] = GLFW_KEY_F24;
|
||||||
|
_glfw.win32.keycodes[0x038] = GLFW_KEY_LEFT_ALT;
|
||||||
|
_glfw.win32.keycodes[0x01D] = GLFW_KEY_LEFT_CONTROL;
|
||||||
|
_glfw.win32.keycodes[0x02A] = GLFW_KEY_LEFT_SHIFT;
|
||||||
|
_glfw.win32.keycodes[0x15B] = GLFW_KEY_LEFT_SUPER;
|
||||||
|
_glfw.win32.keycodes[0x137] = GLFW_KEY_PRINT_SCREEN;
|
||||||
|
_glfw.win32.keycodes[0x138] = GLFW_KEY_RIGHT_ALT;
|
||||||
|
_glfw.win32.keycodes[0x11D] = GLFW_KEY_RIGHT_CONTROL;
|
||||||
|
_glfw.win32.keycodes[0x036] = GLFW_KEY_RIGHT_SHIFT;
|
||||||
|
_glfw.win32.keycodes[0x15C] = GLFW_KEY_RIGHT_SUPER;
|
||||||
|
_glfw.win32.keycodes[0x150] = GLFW_KEY_DOWN;
|
||||||
|
_glfw.win32.keycodes[0x14B] = GLFW_KEY_LEFT;
|
||||||
|
_glfw.win32.keycodes[0x14D] = GLFW_KEY_RIGHT;
|
||||||
|
_glfw.win32.keycodes[0x148] = GLFW_KEY_UP;
|
||||||
|
|
||||||
|
_glfw.win32.keycodes[0x052] = GLFW_KEY_KP_0;
|
||||||
|
_glfw.win32.keycodes[0x04F] = GLFW_KEY_KP_1;
|
||||||
|
_glfw.win32.keycodes[0x050] = GLFW_KEY_KP_2;
|
||||||
|
_glfw.win32.keycodes[0x051] = GLFW_KEY_KP_3;
|
||||||
|
_glfw.win32.keycodes[0x04B] = GLFW_KEY_KP_4;
|
||||||
|
_glfw.win32.keycodes[0x04C] = GLFW_KEY_KP_5;
|
||||||
|
_glfw.win32.keycodes[0x04D] = GLFW_KEY_KP_6;
|
||||||
|
_glfw.win32.keycodes[0x047] = GLFW_KEY_KP_7;
|
||||||
|
_glfw.win32.keycodes[0x048] = GLFW_KEY_KP_8;
|
||||||
|
_glfw.win32.keycodes[0x049] = GLFW_KEY_KP_9;
|
||||||
|
_glfw.win32.keycodes[0x04E] = GLFW_KEY_KP_ADD;
|
||||||
|
_glfw.win32.keycodes[0x053] = GLFW_KEY_KP_DECIMAL;
|
||||||
|
_glfw.win32.keycodes[0x135] = GLFW_KEY_KP_DIVIDE;
|
||||||
|
_glfw.win32.keycodes[0x11C] = GLFW_KEY_KP_ENTER;
|
||||||
|
_glfw.win32.keycodes[0x059] = GLFW_KEY_KP_EQUAL;
|
||||||
|
_glfw.win32.keycodes[0x037] = GLFW_KEY_KP_MULTIPLY;
|
||||||
|
_glfw.win32.keycodes[0x04A] = GLFW_KEY_KP_SUBTRACT;
|
||||||
|
|
||||||
|
for (scancode = 0; scancode < 512; scancode++)
|
||||||
|
{
|
||||||
|
if (_glfw.win32.keycodes[scancode] > 0)
|
||||||
|
_glfw.win32.scancodes[_glfw.win32.keycodes[scancode]] = scancode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a dummy window for behind-the-scenes work
|
||||||
|
//
|
||||||
|
static GLFWbool createHelperWindow(void)
|
||||||
|
{
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
_glfw.win32.helperWindowHandle =
|
||||||
|
CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
|
||||||
|
_GLFW_WNDCLASSNAME,
|
||||||
|
L"GLFW message window",
|
||||||
|
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
|
||||||
|
0, 0, 1, 1,
|
||||||
|
NULL, NULL,
|
||||||
|
GetModuleHandleW(NULL),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (!_glfw.win32.helperWindowHandle)
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to create helper window");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK: The command to the first ShowWindow call is ignored if the parent
|
||||||
|
// process passed along a STARTUPINFO, so clear that with a no-op call
|
||||||
|
ShowWindow(_glfw.win32.helperWindowHandle, SW_HIDE);
|
||||||
|
|
||||||
|
// Register for HID device notifications
|
||||||
|
{
|
||||||
|
DEV_BROADCAST_DEVICEINTERFACE_W dbi;
|
||||||
|
ZeroMemory(&dbi, sizeof(dbi));
|
||||||
|
dbi.dbcc_size = sizeof(dbi);
|
||||||
|
dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
||||||
|
dbi.dbcc_classguid = GUID_DEVINTERFACE_HID;
|
||||||
|
|
||||||
|
_glfw.win32.deviceNotificationHandle =
|
||||||
|
RegisterDeviceNotificationW(_glfw.win32.helperWindowHandle,
|
||||||
|
(DEV_BROADCAST_HDR*) &dbi,
|
||||||
|
DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
|
||||||
|
{
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessageW(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Returns a wide string version of the specified UTF-8 string
|
||||||
|
//
|
||||||
|
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
|
||||||
|
{
|
||||||
|
WCHAR* target;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
count = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
|
||||||
|
if (!count)
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to convert string from UTF-8");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
target = calloc(count, sizeof(WCHAR));
|
||||||
|
|
||||||
|
if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, count))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to convert string from UTF-8");
|
||||||
|
free(target);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a UTF-8 string version of the specified wide string
|
||||||
|
//
|
||||||
|
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
|
||||||
|
{
|
||||||
|
char* target;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
|
||||||
|
if (!size)
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to convert string to UTF-8");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
target = calloc(size, 1);
|
||||||
|
|
||||||
|
if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to convert string to UTF-8");
|
||||||
|
free(target);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reports the specified error, appending information about the last Win32 error
|
||||||
|
//
|
||||||
|
void _glfwInputErrorWin32(int error, const char* description)
|
||||||
|
{
|
||||||
|
WCHAR buffer[_GLFW_MESSAGE_SIZE] = L"";
|
||||||
|
char message[_GLFW_MESSAGE_SIZE] = "";
|
||||||
|
|
||||||
|
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
|
FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||||
|
FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||||||
|
NULL,
|
||||||
|
GetLastError() & 0xffff,
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
buffer,
|
||||||
|
sizeof(buffer) / sizeof(WCHAR),
|
||||||
|
NULL);
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, buffer, -1, message, sizeof(message), NULL, NULL);
|
||||||
|
|
||||||
|
_glfwInputError(error, "%s: %s", description, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updates key names according to the current keyboard layout
|
||||||
|
//
|
||||||
|
void _glfwUpdateKeyNamesWin32(void)
|
||||||
|
{
|
||||||
|
int key;
|
||||||
|
BYTE state[256] = {0};
|
||||||
|
|
||||||
|
memset(_glfw.win32.keynames, 0, sizeof(_glfw.win32.keynames));
|
||||||
|
|
||||||
|
for (key = GLFW_KEY_SPACE; key <= GLFW_KEY_LAST; key++)
|
||||||
|
{
|
||||||
|
UINT vk;
|
||||||
|
int scancode, length;
|
||||||
|
WCHAR chars[16];
|
||||||
|
|
||||||
|
scancode = _glfw.win32.scancodes[key];
|
||||||
|
if (scancode == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD)
|
||||||
|
{
|
||||||
|
const UINT vks[] = {
|
||||||
|
VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,
|
||||||
|
VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
|
||||||
|
VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE,
|
||||||
|
VK_MULTIPLY, VK_SUBTRACT, VK_ADD
|
||||||
|
};
|
||||||
|
|
||||||
|
vk = vks[key - GLFW_KEY_KP_0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK);
|
||||||
|
|
||||||
|
length = ToUnicode(vk, scancode, state,
|
||||||
|
chars, sizeof(chars) / sizeof(WCHAR),
|
||||||
|
0);
|
||||||
|
|
||||||
|
if (length == -1)
|
||||||
|
{
|
||||||
|
length = ToUnicode(vk, scancode, state,
|
||||||
|
chars, sizeof(chars) / sizeof(WCHAR),
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length < 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, chars, 1,
|
||||||
|
_glfw.win32.keynames[key],
|
||||||
|
sizeof(_glfw.win32.keynames[key]),
|
||||||
|
NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h
|
||||||
|
//
|
||||||
|
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp)
|
||||||
|
{
|
||||||
|
OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, {0}, sp };
|
||||||
|
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
|
||||||
|
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
||||||
|
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
|
||||||
|
cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
|
||||||
|
// HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
|
||||||
|
// latter lies unless the user knew to embed a non-default manifest
|
||||||
|
// announcing support for Windows 10 via supportedOS GUID
|
||||||
|
return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks whether we are on at least the specified build of Windows 10
|
||||||
|
//
|
||||||
|
BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build)
|
||||||
|
{
|
||||||
|
OSVERSIONINFOEXW osvi = { sizeof(osvi), 10, 0, build };
|
||||||
|
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER;
|
||||||
|
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
||||||
|
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
|
||||||
|
cond = VerSetConditionMask(cond, VER_BUILDNUMBER, VER_GREATER_EQUAL);
|
||||||
|
// HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
|
||||||
|
// latter lies unless the user knew to embed a non-default manifest
|
||||||
|
// announcing support for Windows 10 via supportedOS GUID
|
||||||
|
return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int _glfwPlatformInit(void)
|
||||||
|
{
|
||||||
|
// To make SetForegroundWindow work as we want, we need to fiddle
|
||||||
|
// with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
|
||||||
|
// as possible in the hope of still being the foreground process)
|
||||||
|
SystemParametersInfoW(SPI_GETFOREGROUNDLOCKTIMEOUT, 0,
|
||||||
|
&_glfw.win32.foregroundLockTimeout, 0);
|
||||||
|
SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(0),
|
||||||
|
SPIF_SENDCHANGE);
|
||||||
|
|
||||||
|
if (!loadLibraries())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
createKeyTables();
|
||||||
|
_glfwUpdateKeyNamesWin32();
|
||||||
|
|
||||||
|
if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
|
||||||
|
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||||
|
else if (IsWindows8Point1OrGreater())
|
||||||
|
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||||
|
else if (IsWindowsVistaOrGreater())
|
||||||
|
SetProcessDPIAware();
|
||||||
|
|
||||||
|
if (!_glfwRegisterWindowClassWin32())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (!createHelperWindow())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
_glfwInitTimerWin32();
|
||||||
|
_glfwInitJoysticksWin32();
|
||||||
|
|
||||||
|
_glfwPollMonitorsWin32();
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformTerminate(void)
|
||||||
|
{
|
||||||
|
if (_glfw.win32.deviceNotificationHandle)
|
||||||
|
UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
|
||||||
|
|
||||||
|
if (_glfw.win32.helperWindowHandle)
|
||||||
|
DestroyWindow(_glfw.win32.helperWindowHandle);
|
||||||
|
|
||||||
|
_glfwUnregisterWindowClassWin32();
|
||||||
|
|
||||||
|
// Restore previous foreground lock timeout system setting
|
||||||
|
SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0,
|
||||||
|
UIntToPtr(_glfw.win32.foregroundLockTimeout),
|
||||||
|
SPIF_SENDCHANGE);
|
||||||
|
|
||||||
|
free(_glfw.win32.clipboardString);
|
||||||
|
free(_glfw.win32.rawInput);
|
||||||
|
|
||||||
|
_glfwTerminateWGL();
|
||||||
|
_glfwTerminateEGL();
|
||||||
|
|
||||||
|
_glfwTerminateJoysticksWin32();
|
||||||
|
|
||||||
|
freeLibraries();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
|
{
|
||||||
|
return _GLFW_VERSION_NUMBER " Win32 WGL EGL OSMesa"
|
||||||
|
#if defined(__MINGW32__)
|
||||||
|
" MinGW"
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
" VisualC"
|
||||||
|
#endif
|
||||||
|
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
|
||||||
|
" hybrid-GPU"
|
||||||
|
#endif
|
||||||
|
#if defined(_GLFW_BUILD_DLL)
|
||||||
|
" DLL"
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,755 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 Win32 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define _GLFW_TYPE_AXIS 0
|
||||||
|
#define _GLFW_TYPE_SLIDER 1
|
||||||
|
#define _GLFW_TYPE_BUTTON 2
|
||||||
|
#define _GLFW_TYPE_POV 3
|
||||||
|
|
||||||
|
// Data produced with DirectInput device object enumeration
|
||||||
|
//
|
||||||
|
typedef struct _GLFWobjenumWin32
|
||||||
|
{
|
||||||
|
IDirectInputDevice8W* device;
|
||||||
|
_GLFWjoyobjectWin32* objects;
|
||||||
|
int objectCount;
|
||||||
|
int axisCount;
|
||||||
|
int sliderCount;
|
||||||
|
int buttonCount;
|
||||||
|
int povCount;
|
||||||
|
} _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_POV =
|
||||||
|
{0xa36d02f2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||||
|
|
||||||
|
#define IID_IDirectInput8W _glfw_IID_IDirectInput8W
|
||||||
|
#define GUID_XAxis _glfw_GUID_XAxis
|
||||||
|
#define GUID_YAxis _glfw_GUID_YAxis
|
||||||
|
#define GUID_ZAxis _glfw_GUID_ZAxis
|
||||||
|
#define GUID_RxAxis _glfw_GUID_RxAxis
|
||||||
|
#define GUID_RyAxis _glfw_GUID_RyAxis
|
||||||
|
#define GUID_RzAxis _glfw_GUID_RzAxis
|
||||||
|
#define GUID_Slider _glfw_GUID_Slider
|
||||||
|
#define GUID_POV _glfw_GUID_POV
|
||||||
|
|
||||||
|
// Object data array for our clone of c_dfDIJoystick
|
||||||
|
// Generated with https://github.com/elmindreda/c_dfDIJoystick2
|
||||||
|
//
|
||||||
|
static DIOBJECTDATAFORMAT _glfwObjectDataFormats[] =
|
||||||
|
{
|
||||||
|
{ &GUID_XAxis,DIJOFS_X,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
||||||
|
{ &GUID_YAxis,DIJOFS_Y,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
||||||
|
{ &GUID_ZAxis,DIJOFS_Z,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
||||||
|
{ &GUID_RxAxis,DIJOFS_RX,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
||||||
|
{ &GUID_RyAxis,DIJOFS_RY,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
||||||
|
{ &GUID_RzAxis,DIJOFS_RZ,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
||||||
|
{ &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
||||||
|
{ &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
||||||
|
{ &GUID_POV,DIJOFS_POV(0),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ &GUID_POV,DIJOFS_POV(1),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ &GUID_POV,DIJOFS_POV(2),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ &GUID_POV,DIJOFS_POV(3),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(0),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(1),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(2),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(3),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(4),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(5),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(6),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(7),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(8),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(9),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(10),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(11),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(12),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(13),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(14),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(15),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(16),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(17),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(18),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(19),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(20),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(21),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(22),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(23),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(24),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(25),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(26),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(27),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(28),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(29),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(30),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
{ NULL,DIJOFS_BUTTON(31),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Our clone of c_dfDIJoystick
|
||||||
|
//
|
||||||
|
static const DIDATAFORMAT _glfwDataFormat =
|
||||||
|
{
|
||||||
|
sizeof(DIDATAFORMAT),
|
||||||
|
sizeof(DIOBJECTDATAFORMAT),
|
||||||
|
DIDFT_ABSAXIS,
|
||||||
|
sizeof(DIJOYSTATE),
|
||||||
|
sizeof(_glfwObjectDataFormats) / sizeof(DIOBJECTDATAFORMAT),
|
||||||
|
_glfwObjectDataFormats
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns a description fitting the specified XInput capabilities
|
||||||
|
//
|
||||||
|
static const char* getDeviceDescription(const XINPUT_CAPABILITIES* xic)
|
||||||
|
{
|
||||||
|
switch (xic->SubType)
|
||||||
|
{
|
||||||
|
case XINPUT_DEVSUBTYPE_WHEEL:
|
||||||
|
return "XInput Wheel";
|
||||||
|
case XINPUT_DEVSUBTYPE_ARCADE_STICK:
|
||||||
|
return "XInput Arcade Stick";
|
||||||
|
case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
|
||||||
|
return "XInput Flight Stick";
|
||||||
|
case XINPUT_DEVSUBTYPE_DANCE_PAD:
|
||||||
|
return "XInput Dance Pad";
|
||||||
|
case XINPUT_DEVSUBTYPE_GUITAR:
|
||||||
|
return "XInput Guitar";
|
||||||
|
case XINPUT_DEVSUBTYPE_DRUM_KIT:
|
||||||
|
return "XInput Drum Kit";
|
||||||
|
case XINPUT_DEVSUBTYPE_GAMEPAD:
|
||||||
|
{
|
||||||
|
if (xic->Flags & XINPUT_CAPS_WIRELESS)
|
||||||
|
return "Wireless Xbox Controller";
|
||||||
|
else
|
||||||
|
return "Xbox Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Unknown XInput Device";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lexically compare device objects
|
||||||
|
//
|
||||||
|
static int compareJoystickObjects(const void* first, const void* second)
|
||||||
|
{
|
||||||
|
const _GLFWjoyobjectWin32* fo = first;
|
||||||
|
const _GLFWjoyobjectWin32* so = second;
|
||||||
|
|
||||||
|
if (fo->type != so->type)
|
||||||
|
return fo->type - so->type;
|
||||||
|
|
||||||
|
return fo->offset - so->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks whether the specified device supports XInput
|
||||||
|
// Technique from FDInputJoystickManager::IsXInputDeviceFast in ZDoom
|
||||||
|
//
|
||||||
|
static GLFWbool supportsXInput(const GUID* guid)
|
||||||
|
{
|
||||||
|
UINT i, count = 0;
|
||||||
|
RAWINPUTDEVICELIST* ridl;
|
||||||
|
GLFWbool result = GLFW_FALSE;
|
||||||
|
|
||||||
|
if (GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)) != 0)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
ridl = calloc(count, sizeof(RAWINPUTDEVICELIST));
|
||||||
|
|
||||||
|
if (GetRawInputDeviceList(ridl, &count, sizeof(RAWINPUTDEVICELIST)) == (UINT) -1)
|
||||||
|
{
|
||||||
|
free(ridl);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
RID_DEVICE_INFO rdi;
|
||||||
|
char name[256];
|
||||||
|
UINT size;
|
||||||
|
|
||||||
|
if (ridl[i].dwType != RIM_TYPEHID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ZeroMemory(&rdi, sizeof(rdi));
|
||||||
|
rdi.cbSize = sizeof(rdi);
|
||||||
|
size = sizeof(rdi);
|
||||||
|
|
||||||
|
if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,
|
||||||
|
RIDI_DEVICEINFO,
|
||||||
|
&rdi, &size) == -1)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) != (LONG) guid->Data1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
memset(name, 0, sizeof(name));
|
||||||
|
size = sizeof(name);
|
||||||
|
|
||||||
|
if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,
|
||||||
|
RIDI_DEVICENAME,
|
||||||
|
name, &size) == -1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
name[sizeof(name) - 1] = '\0';
|
||||||
|
if (strstr(name, "IG_"))
|
||||||
|
{
|
||||||
|
result = GLFW_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ridl);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frees all resources associated with the specified joystick
|
||||||
|
//
|
||||||
|
static void closeJoystick(_GLFWjoystick* js)
|
||||||
|
{
|
||||||
|
if (js->win32.device)
|
||||||
|
{
|
||||||
|
IDirectInputDevice8_Unacquire(js->win32.device);
|
||||||
|
IDirectInputDevice8_Release(js->win32.device);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(js->win32.objects);
|
||||||
|
|
||||||
|
_glfwFreeJoystick(js);
|
||||||
|
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DirectInput device object enumeration callback
|
||||||
|
// Insights gleaned from SDL
|
||||||
|
//
|
||||||
|
static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
|
||||||
|
void* user)
|
||||||
|
{
|
||||||
|
_GLFWobjenumWin32* data = user;
|
||||||
|
_GLFWjoyobjectWin32* object = data->objects + data->objectCount;
|
||||||
|
|
||||||
|
if (DIDFT_GETTYPE(doi->dwType) & DIDFT_AXIS)
|
||||||
|
{
|
||||||
|
DIPROPRANGE dipr;
|
||||||
|
|
||||||
|
if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)
|
||||||
|
object->offset = DIJOFS_SLIDER(data->sliderCount);
|
||||||
|
else if (memcmp(&doi->guidType, &GUID_XAxis, sizeof(GUID)) == 0)
|
||||||
|
object->offset = DIJOFS_X;
|
||||||
|
else if (memcmp(&doi->guidType, &GUID_YAxis, sizeof(GUID)) == 0)
|
||||||
|
object->offset = DIJOFS_Y;
|
||||||
|
else if (memcmp(&doi->guidType, &GUID_ZAxis, sizeof(GUID)) == 0)
|
||||||
|
object->offset = DIJOFS_Z;
|
||||||
|
else if (memcmp(&doi->guidType, &GUID_RxAxis, sizeof(GUID)) == 0)
|
||||||
|
object->offset = DIJOFS_RX;
|
||||||
|
else if (memcmp(&doi->guidType, &GUID_RyAxis, sizeof(GUID)) == 0)
|
||||||
|
object->offset = DIJOFS_RY;
|
||||||
|
else if (memcmp(&doi->guidType, &GUID_RzAxis, sizeof(GUID)) == 0)
|
||||||
|
object->offset = DIJOFS_RZ;
|
||||||
|
else
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
|
||||||
|
ZeroMemory(&dipr, sizeof(dipr));
|
||||||
|
dipr.diph.dwSize = sizeof(dipr);
|
||||||
|
dipr.diph.dwHeaderSize = sizeof(dipr.diph);
|
||||||
|
dipr.diph.dwObj = doi->dwType;
|
||||||
|
dipr.diph.dwHow = DIPH_BYID;
|
||||||
|
dipr.lMin = -32768;
|
||||||
|
dipr.lMax = 32767;
|
||||||
|
|
||||||
|
if (FAILED(IDirectInputDevice8_SetProperty(data->device,
|
||||||
|
DIPROP_RANGE,
|
||||||
|
&dipr.diph)))
|
||||||
|
{
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)
|
||||||
|
{
|
||||||
|
object->type = _GLFW_TYPE_SLIDER;
|
||||||
|
data->sliderCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
object->type = _GLFW_TYPE_AXIS;
|
||||||
|
data->axisCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_BUTTON)
|
||||||
|
{
|
||||||
|
object->offset = DIJOFS_BUTTON(data->buttonCount);
|
||||||
|
object->type = _GLFW_TYPE_BUTTON;
|
||||||
|
data->buttonCount++;
|
||||||
|
}
|
||||||
|
else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_POV)
|
||||||
|
{
|
||||||
|
object->offset = DIJOFS_POV(data->povCount);
|
||||||
|
object->type = _GLFW_TYPE_POV;
|
||||||
|
data->povCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->objectCount++;
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DirectInput device enumeration callback
|
||||||
|
//
|
||||||
|
static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||||
|
{
|
||||||
|
int jid = 0;
|
||||||
|
DIDEVCAPS dc;
|
||||||
|
DIPROPDWORD dipd;
|
||||||
|
IDirectInputDevice8* device;
|
||||||
|
_GLFWobjenumWin32 data;
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
char guid[33];
|
||||||
|
char name[256];
|
||||||
|
|
||||||
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
{
|
||||||
|
js = _glfw.joysticks + jid;
|
||||||
|
if (js->present)
|
||||||
|
{
|
||||||
|
if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportsXInput(&di->guidProduct))
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
|
||||||
|
if (FAILED(IDirectInput8_CreateDevice(_glfw.win32.dinput8.api,
|
||||||
|
&di->guidInstance,
|
||||||
|
&device,
|
||||||
|
NULL)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create device");
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to set device data format");
|
||||||
|
|
||||||
|
IDirectInputDevice8_Release(device);
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMemory(&dc, sizeof(dc));
|
||||||
|
dc.dwSize = sizeof(dc);
|
||||||
|
|
||||||
|
if (FAILED(IDirectInputDevice8_GetCapabilities(device, &dc)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to query device capabilities");
|
||||||
|
|
||||||
|
IDirectInputDevice8_Release(device);
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMemory(&dipd, sizeof(dipd));
|
||||||
|
dipd.diph.dwSize = sizeof(dipd);
|
||||||
|
dipd.diph.dwHeaderSize = sizeof(dipd.diph);
|
||||||
|
dipd.diph.dwHow = DIPH_DEVICE;
|
||||||
|
dipd.dwData = DIPROPAXISMODE_ABS;
|
||||||
|
|
||||||
|
if (FAILED(IDirectInputDevice8_SetProperty(device,
|
||||||
|
DIPROP_AXISMODE,
|
||||||
|
&dipd.diph)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to set device axis mode");
|
||||||
|
|
||||||
|
IDirectInputDevice8_Release(device);
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&data, 0, sizeof(data));
|
||||||
|
data.device = device;
|
||||||
|
data.objects = calloc(dc.dwAxes + (size_t) dc.dwButtons + dc.dwPOVs,
|
||||||
|
sizeof(_GLFWjoyobjectWin32));
|
||||||
|
|
||||||
|
if (FAILED(IDirectInputDevice8_EnumObjects(device,
|
||||||
|
deviceObjectCallback,
|
||||||
|
&data,
|
||||||
|
DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to enumerate device objects");
|
||||||
|
|
||||||
|
IDirectInputDevice8_Release(device);
|
||||||
|
free(data.objects);
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
qsort(data.objects, data.objectCount,
|
||||||
|
sizeof(_GLFWjoyobjectWin32),
|
||||||
|
compareJoystickObjects);
|
||||||
|
|
||||||
|
if (!WideCharToMultiByte(CP_UTF8, 0,
|
||||||
|
di->tszInstanceName, -1,
|
||||||
|
name, sizeof(name),
|
||||||
|
NULL, NULL))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to convert joystick name to UTF-8");
|
||||||
|
|
||||||
|
IDirectInputDevice8_Release(device);
|
||||||
|
free(data.objects);
|
||||||
|
return DIENUM_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
||||||
|
if (memcmp(&di->guidProduct.Data4[2], "PIDVID", 6) == 0)
|
||||||
|
{
|
||||||
|
sprintf(guid, "03000000%02x%02x0000%02x%02x000000000000",
|
||||||
|
(uint8_t) di->guidProduct.Data1,
|
||||||
|
(uint8_t) (di->guidProduct.Data1 >> 8),
|
||||||
|
(uint8_t) (di->guidProduct.Data1 >> 16),
|
||||||
|
(uint8_t) (di->guidProduct.Data1 >> 24));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
|
||||||
|
name[0], name[1], name[2], name[3],
|
||||||
|
name[4], name[5], name[6], name[7],
|
||||||
|
name[8], name[9], name[10]);
|
||||||
|
}
|
||||||
|
|
||||||
|
js = _glfwAllocJoystick(name, guid,
|
||||||
|
data.axisCount + data.sliderCount,
|
||||||
|
data.buttonCount,
|
||||||
|
data.povCount);
|
||||||
|
if (!js)
|
||||||
|
{
|
||||||
|
IDirectInputDevice8_Release(device);
|
||||||
|
free(data.objects);
|
||||||
|
return DIENUM_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
js->win32.device = device;
|
||||||
|
js->win32.guid = di->guidInstance;
|
||||||
|
js->win32.objects = data.objects;
|
||||||
|
js->win32.objectCount = data.objectCount;
|
||||||
|
|
||||||
|
_glfwInputJoystick(js, GLFW_CONNECTED);
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Initialize joystick interface
|
||||||
|
//
|
||||||
|
void _glfwInitJoysticksWin32(void)
|
||||||
|
{
|
||||||
|
if (_glfw.win32.dinput8.instance)
|
||||||
|
{
|
||||||
|
if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
|
||||||
|
DIRECTINPUT_VERSION,
|
||||||
|
&IID_IDirectInput8W,
|
||||||
|
(void**) &_glfw.win32.dinput8.api,
|
||||||
|
NULL)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to create interface");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwDetectJoystickConnectionWin32();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close all opened joystick handles
|
||||||
|
//
|
||||||
|
void _glfwTerminateJoysticksWin32(void)
|
||||||
|
{
|
||||||
|
int jid;
|
||||||
|
|
||||||
|
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
closeJoystick(_glfw.joysticks + jid);
|
||||||
|
|
||||||
|
if (_glfw.win32.dinput8.api)
|
||||||
|
IDirectInput8_Release(_glfw.win32.dinput8.api);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks for new joysticks after DBT_DEVICEARRIVAL
|
||||||
|
//
|
||||||
|
void _glfwDetectJoystickConnectionWin32(void)
|
||||||
|
{
|
||||||
|
if (_glfw.win32.xinput.instance)
|
||||||
|
{
|
||||||
|
DWORD index;
|
||||||
|
|
||||||
|
for (index = 0; index < XUSER_MAX_COUNT; index++)
|
||||||
|
{
|
||||||
|
int jid;
|
||||||
|
char guid[33];
|
||||||
|
XINPUT_CAPABILITIES xic;
|
||||||
|
_GLFWjoystick* js;
|
||||||
|
|
||||||
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
{
|
||||||
|
if (_glfw.joysticks[jid].present &&
|
||||||
|
_glfw.joysticks[jid].win32.device == NULL &&
|
||||||
|
_glfw.joysticks[jid].win32.index == index)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jid <= GLFW_JOYSTICK_LAST)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
||||||
|
sprintf(guid, "78696e707574%02x000000000000000000",
|
||||||
|
xic.SubType & 0xff);
|
||||||
|
|
||||||
|
js = _glfwAllocJoystick(getDeviceDescription(&xic), guid, 6, 10, 1);
|
||||||
|
if (!js)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
js->win32.index = index;
|
||||||
|
|
||||||
|
_glfwInputJoystick(js, GLFW_CONNECTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.win32.dinput8.api)
|
||||||
|
{
|
||||||
|
if (FAILED(IDirectInput8_EnumDevices(_glfw.win32.dinput8.api,
|
||||||
|
DI8DEVCLASS_GAMECTRL,
|
||||||
|
deviceCallback,
|
||||||
|
NULL,
|
||||||
|
DIEDFL_ALLDEVICES)))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Failed to enumerate DirectInput8 devices");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks for joystick disconnection after DBT_DEVICEREMOVECOMPLETE
|
||||||
|
//
|
||||||
|
void _glfwDetectJoystickDisconnectionWin32(void)
|
||||||
|
{
|
||||||
|
int jid;
|
||||||
|
|
||||||
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
{
|
||||||
|
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||||
|
if (js->present)
|
||||||
|
_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||||
|
{
|
||||||
|
if (js->win32.device)
|
||||||
|
{
|
||||||
|
int i, ai = 0, bi = 0, pi = 0;
|
||||||
|
HRESULT result;
|
||||||
|
DIJOYSTATE state;
|
||||||
|
|
||||||
|
IDirectInputDevice8_Poll(js->win32.device);
|
||||||
|
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
|
||||||
|
sizeof(state),
|
||||||
|
&state);
|
||||||
|
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
|
||||||
|
{
|
||||||
|
IDirectInputDevice8_Acquire(js->win32.device);
|
||||||
|
IDirectInputDevice8_Poll(js->win32.device);
|
||||||
|
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
|
||||||
|
sizeof(state),
|
||||||
|
&state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
closeJoystick(js);
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == _GLFW_POLL_PRESENCE)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
for (i = 0; i < js->win32.objectCount; i++)
|
||||||
|
{
|
||||||
|
const void* data = (char*) &state + js->win32.objects[i].offset;
|
||||||
|
|
||||||
|
switch (js->win32.objects[i].type)
|
||||||
|
{
|
||||||
|
case _GLFW_TYPE_AXIS:
|
||||||
|
case _GLFW_TYPE_SLIDER:
|
||||||
|
{
|
||||||
|
const float value = (*((LONG*) data) + 0.5f) / 32767.5f;
|
||||||
|
_glfwInputJoystickAxis(js, ai, value);
|
||||||
|
ai++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _GLFW_TYPE_BUTTON:
|
||||||
|
{
|
||||||
|
const char value = (*((BYTE*) data) & 0x80) != 0;
|
||||||
|
_glfwInputJoystickButton(js, bi, value);
|
||||||
|
bi++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _GLFW_TYPE_POV:
|
||||||
|
{
|
||||||
|
const int states[9] =
|
||||||
|
{
|
||||||
|
GLFW_HAT_UP,
|
||||||
|
GLFW_HAT_RIGHT_UP,
|
||||||
|
GLFW_HAT_RIGHT,
|
||||||
|
GLFW_HAT_RIGHT_DOWN,
|
||||||
|
GLFW_HAT_DOWN,
|
||||||
|
GLFW_HAT_LEFT_DOWN,
|
||||||
|
GLFW_HAT_LEFT,
|
||||||
|
GLFW_HAT_LEFT_UP,
|
||||||
|
GLFW_HAT_CENTERED
|
||||||
|
};
|
||||||
|
|
||||||
|
// Screams of horror are appropriate at this point
|
||||||
|
int stateIndex = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
||||||
|
if (stateIndex < 0 || stateIndex > 8)
|
||||||
|
stateIndex = 8;
|
||||||
|
|
||||||
|
_glfwInputJoystickHat(js, pi, states[stateIndex]);
|
||||||
|
pi++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i, dpad = 0;
|
||||||
|
DWORD result;
|
||||||
|
XINPUT_STATE xis;
|
||||||
|
const WORD buttons[10] =
|
||||||
|
{
|
||||||
|
XINPUT_GAMEPAD_A,
|
||||||
|
XINPUT_GAMEPAD_B,
|
||||||
|
XINPUT_GAMEPAD_X,
|
||||||
|
XINPUT_GAMEPAD_Y,
|
||||||
|
XINPUT_GAMEPAD_LEFT_SHOULDER,
|
||||||
|
XINPUT_GAMEPAD_RIGHT_SHOULDER,
|
||||||
|
XINPUT_GAMEPAD_BACK,
|
||||||
|
XINPUT_GAMEPAD_START,
|
||||||
|
XINPUT_GAMEPAD_LEFT_THUMB,
|
||||||
|
XINPUT_GAMEPAD_RIGHT_THUMB
|
||||||
|
};
|
||||||
|
|
||||||
|
result = XInputGetState(js->win32.index, &xis);
|
||||||
|
if (result != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
if (result == ERROR_DEVICE_NOT_CONNECTED)
|
||||||
|
closeJoystick(js);
|
||||||
|
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == _GLFW_POLL_PRESENCE)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
_glfwInputJoystickAxis(js, 0, (xis.Gamepad.sThumbLX + 0.5f) / 32767.5f);
|
||||||
|
_glfwInputJoystickAxis(js, 1, -(xis.Gamepad.sThumbLY + 0.5f) / 32767.5f);
|
||||||
|
_glfwInputJoystickAxis(js, 2, (xis.Gamepad.sThumbRX + 0.5f) / 32767.5f);
|
||||||
|
_glfwInputJoystickAxis(js, 3, -(xis.Gamepad.sThumbRY + 0.5f) / 32767.5f);
|
||||||
|
_glfwInputJoystickAxis(js, 4, xis.Gamepad.bLeftTrigger / 127.5f - 1.f);
|
||||||
|
_glfwInputJoystickAxis(js, 5, xis.Gamepad.bRightTrigger / 127.5f - 1.f);
|
||||||
|
|
||||||
|
for (i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
||||||
|
_glfwInputJoystickButton(js, i, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
|
||||||
|
dpad |= GLFW_HAT_UP;
|
||||||
|
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
|
||||||
|
dpad |= GLFW_HAT_RIGHT;
|
||||||
|
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
|
||||||
|
dpad |= GLFW_HAT_DOWN;
|
||||||
|
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
|
||||||
|
dpad |= GLFW_HAT_LEFT;
|
||||||
|
|
||||||
|
_glfwInputJoystickHat(js, 0, dpad);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||||
|
{
|
||||||
|
if (strcmp(guid + 20, "504944564944") == 0)
|
||||||
|
{
|
||||||
|
char original[33];
|
||||||
|
strncpy(original, guid, sizeof(original) - 1);
|
||||||
|
sprintf(guid, "03000000%.4s0000%.4s000000000000",
|
||||||
|
original, original + 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 Win32 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickWin32 win32
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE struct { int dummyLibraryJoystick; }
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_MAPPING_NAME "Windows"
|
||||||
|
|
||||||
|
// Joystick element (axis, button or slider)
|
||||||
|
//
|
||||||
|
typedef struct _GLFWjoyobjectWin32
|
||||||
|
{
|
||||||
|
int offset;
|
||||||
|
int type;
|
||||||
|
} _GLFWjoyobjectWin32;
|
||||||
|
|
||||||
|
// Win32-specific per-joystick data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWjoystickWin32
|
||||||
|
{
|
||||||
|
_GLFWjoyobjectWin32* objects;
|
||||||
|
int objectCount;
|
||||||
|
IDirectInputDevice8W* device;
|
||||||
|
DWORD index;
|
||||||
|
GUID guid;
|
||||||
|
} _GLFWjoystickWin32;
|
||||||
|
|
||||||
|
|
||||||
|
void _glfwInitJoysticksWin32(void);
|
||||||
|
void _glfwTerminateJoysticksWin32(void);
|
||||||
|
void _glfwDetectJoystickConnectionWin32(void);
|
||||||
|
void _glfwDetectJoystickDisconnectionWin32(void);
|
||||||
|
|
|
@ -0,0 +1,537 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 Win32 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Callback for EnumDisplayMonitors in createMonitor
|
||||||
|
//
|
||||||
|
static BOOL CALLBACK monitorCallback(HMONITOR handle,
|
||||||
|
HDC dc,
|
||||||
|
RECT* rect,
|
||||||
|
LPARAM data)
|
||||||
|
{
|
||||||
|
MONITORINFOEXW mi;
|
||||||
|
ZeroMemory(&mi, sizeof(mi));
|
||||||
|
mi.cbSize = sizeof(mi);
|
||||||
|
|
||||||
|
if (GetMonitorInfoW(handle, (MONITORINFO*) &mi))
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) data;
|
||||||
|
if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0)
|
||||||
|
monitor->win32.handle = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create monitor from an adapter and (optionally) a display
|
||||||
|
//
|
||||||
|
static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
||||||
|
DISPLAY_DEVICEW* display)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor;
|
||||||
|
int widthMM, heightMM;
|
||||||
|
char* name;
|
||||||
|
HDC dc;
|
||||||
|
DEVMODEW dm;
|
||||||
|
RECT rect;
|
||||||
|
|
||||||
|
if (display)
|
||||||
|
name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString);
|
||||||
|
else
|
||||||
|
name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);
|
||||||
|
if (!name)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ZeroMemory(&dm, sizeof(dm));
|
||||||
|
dm.dmSize = sizeof(dm);
|
||||||
|
EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm);
|
||||||
|
|
||||||
|
dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
|
||||||
|
|
||||||
|
if (IsWindows8Point1OrGreater())
|
||||||
|
{
|
||||||
|
widthMM = GetDeviceCaps(dc, HORZSIZE);
|
||||||
|
heightMM = GetDeviceCaps(dc, VERTSIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
widthMM = (int) (dm.dmPelsWidth * 25.4f / GetDeviceCaps(dc, LOGPIXELSX));
|
||||||
|
heightMM = (int) (dm.dmPelsHeight * 25.4f / GetDeviceCaps(dc, LOGPIXELSY));
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteDC(dc);
|
||||||
|
|
||||||
|
monitor = _glfwAllocMonitor(name, widthMM, heightMM);
|
||||||
|
free(name);
|
||||||
|
|
||||||
|
if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED)
|
||||||
|
monitor->win32.modesPruned = GLFW_TRUE;
|
||||||
|
|
||||||
|
wcscpy(monitor->win32.adapterName, adapter->DeviceName);
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0,
|
||||||
|
adapter->DeviceName, -1,
|
||||||
|
monitor->win32.publicAdapterName,
|
||||||
|
sizeof(monitor->win32.publicAdapterName),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
if (display)
|
||||||
|
{
|
||||||
|
wcscpy(monitor->win32.displayName, display->DeviceName);
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0,
|
||||||
|
display->DeviceName, -1,
|
||||||
|
monitor->win32.publicDisplayName,
|
||||||
|
sizeof(monitor->win32.publicDisplayName),
|
||||||
|
NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
rect.left = dm.dmPosition.x;
|
||||||
|
rect.top = dm.dmPosition.y;
|
||||||
|
rect.right = dm.dmPosition.x + dm.dmPelsWidth;
|
||||||
|
rect.bottom = dm.dmPosition.y + dm.dmPelsHeight;
|
||||||
|
|
||||||
|
EnumDisplayMonitors(NULL, &rect, monitorCallback, (LPARAM) monitor);
|
||||||
|
return monitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Poll for changes in the set of connected monitors
|
||||||
|
//
|
||||||
|
void _glfwPollMonitorsWin32(void)
|
||||||
|
{
|
||||||
|
int i, disconnectedCount;
|
||||||
|
_GLFWmonitor** disconnected = NULL;
|
||||||
|
DWORD adapterIndex, displayIndex;
|
||||||
|
DISPLAY_DEVICEW adapter, display;
|
||||||
|
_GLFWmonitor* monitor;
|
||||||
|
|
||||||
|
disconnectedCount = _glfw.monitorCount;
|
||||||
|
if (disconnectedCount)
|
||||||
|
{
|
||||||
|
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
|
||||||
|
memcpy(disconnected,
|
||||||
|
_glfw.monitors,
|
||||||
|
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (adapterIndex = 0; ; adapterIndex++)
|
||||||
|
{
|
||||||
|
int type = _GLFW_INSERT_LAST;
|
||||||
|
|
||||||
|
ZeroMemory(&adapter, sizeof(adapter));
|
||||||
|
adapter.cb = sizeof(adapter);
|
||||||
|
|
||||||
|
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
|
||||||
|
type = _GLFW_INSERT_FIRST;
|
||||||
|
|
||||||
|
for (displayIndex = 0; ; displayIndex++)
|
||||||
|
{
|
||||||
|
ZeroMemory(&display, sizeof(display));
|
||||||
|
display.cb = sizeof(display);
|
||||||
|
|
||||||
|
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!(display.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (i = 0; i < disconnectedCount; i++)
|
||||||
|
{
|
||||||
|
if (disconnected[i] &&
|
||||||
|
wcscmp(disconnected[i]->win32.displayName,
|
||||||
|
display.DeviceName) == 0)
|
||||||
|
{
|
||||||
|
disconnected[i] = NULL;
|
||||||
|
// handle may have changed, update
|
||||||
|
EnumDisplayMonitors(NULL, NULL, monitorCallback, (LPARAM) _glfw.monitors[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < disconnectedCount)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
monitor = createMonitor(&adapter, &display);
|
||||||
|
if (!monitor)
|
||||||
|
{
|
||||||
|
free(disconnected);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
|
||||||
|
|
||||||
|
type = _GLFW_INSERT_LAST;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK: If an active adapter does not have any display devices
|
||||||
|
// (as sometimes happens), add it directly as a monitor
|
||||||
|
if (displayIndex == 0)
|
||||||
|
{
|
||||||
|
for (i = 0; i < disconnectedCount; i++)
|
||||||
|
{
|
||||||
|
if (disconnected[i] &&
|
||||||
|
wcscmp(disconnected[i]->win32.adapterName,
|
||||||
|
adapter.DeviceName) == 0)
|
||||||
|
{
|
||||||
|
disconnected[i] = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < disconnectedCount)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
monitor = createMonitor(&adapter, NULL);
|
||||||
|
if (!monitor)
|
||||||
|
{
|
||||||
|
free(disconnected);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < disconnectedCount; i++)
|
||||||
|
{
|
||||||
|
if (disconnected[i])
|
||||||
|
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(disconnected);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the current video mode
|
||||||
|
//
|
||||||
|
void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||||
|
{
|
||||||
|
GLFWvidmode current;
|
||||||
|
const GLFWvidmode* best;
|
||||||
|
DEVMODEW dm;
|
||||||
|
LONG result;
|
||||||
|
|
||||||
|
best = _glfwChooseVideoMode(monitor, desired);
|
||||||
|
_glfwPlatformGetVideoMode(monitor, ¤t);
|
||||||
|
if (_glfwCompareVideoModes(¤t, best) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ZeroMemory(&dm, sizeof(dm));
|
||||||
|
dm.dmSize = sizeof(dm);
|
||||||
|
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL |
|
||||||
|
DM_DISPLAYFREQUENCY;
|
||||||
|
dm.dmPelsWidth = best->width;
|
||||||
|
dm.dmPelsHeight = best->height;
|
||||||
|
dm.dmBitsPerPel = best->redBits + best->greenBits + best->blueBits;
|
||||||
|
dm.dmDisplayFrequency = best->refreshRate;
|
||||||
|
|
||||||
|
if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24)
|
||||||
|
dm.dmBitsPerPel = 32;
|
||||||
|
|
||||||
|
result = ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
||||||
|
&dm,
|
||||||
|
NULL,
|
||||||
|
CDS_FULLSCREEN,
|
||||||
|
NULL);
|
||||||
|
if (result == DISP_CHANGE_SUCCESSFUL)
|
||||||
|
monitor->win32.modeChanged = GLFW_TRUE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char* description = "Unknown error";
|
||||||
|
|
||||||
|
if (result == DISP_CHANGE_BADDUALVIEW)
|
||||||
|
description = "The system uses DualView";
|
||||||
|
else if (result == DISP_CHANGE_BADFLAGS)
|
||||||
|
description = "Invalid flags";
|
||||||
|
else if (result == DISP_CHANGE_BADMODE)
|
||||||
|
description = "Graphics mode not supported";
|
||||||
|
else if (result == DISP_CHANGE_BADPARAM)
|
||||||
|
description = "Invalid parameter";
|
||||||
|
else if (result == DISP_CHANGE_FAILED)
|
||||||
|
description = "Graphics mode failed";
|
||||||
|
else if (result == DISP_CHANGE_NOTUPDATED)
|
||||||
|
description = "Failed to write to registry";
|
||||||
|
else if (result == DISP_CHANGE_RESTART)
|
||||||
|
description = "Computer restart required";
|
||||||
|
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to set video mode: %s",
|
||||||
|
description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore the previously saved (original) video mode
|
||||||
|
//
|
||||||
|
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor)
|
||||||
|
{
|
||||||
|
if (monitor->win32.modeChanged)
|
||||||
|
{
|
||||||
|
ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
||||||
|
NULL, NULL, CDS_FULLSCREEN, NULL);
|
||||||
|
monitor->win32.modeChanged = GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale)
|
||||||
|
{
|
||||||
|
UINT xdpi, ydpi;
|
||||||
|
|
||||||
|
if (IsWindows8Point1OrGreater())
|
||||||
|
GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const HDC dc = GetDC(NULL);
|
||||||
|
xdpi = GetDeviceCaps(dc, LOGPIXELSX);
|
||||||
|
ydpi = GetDeviceCaps(dc, LOGPIXELSY);
|
||||||
|
ReleaseDC(NULL, dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xscale)
|
||||||
|
*xscale = xdpi / (float) USER_DEFAULT_SCREEN_DPI;
|
||||||
|
if (yscale)
|
||||||
|
*yscale = ydpi / (float) USER_DEFAULT_SCREEN_DPI;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||||
|
{
|
||||||
|
DEVMODEW dm;
|
||||||
|
ZeroMemory(&dm, sizeof(dm));
|
||||||
|
dm.dmSize = sizeof(dm);
|
||||||
|
|
||||||
|
EnumDisplaySettingsExW(monitor->win32.adapterName,
|
||||||
|
ENUM_CURRENT_SETTINGS,
|
||||||
|
&dm,
|
||||||
|
EDS_ROTATEDMODE);
|
||||||
|
|
||||||
|
if (xpos)
|
||||||
|
*xpos = dm.dmPosition.x;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = dm.dmPosition.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||||
|
float* xscale, float* yscale)
|
||||||
|
{
|
||||||
|
_glfwGetMonitorContentScaleWin32(monitor->win32.handle, xscale, yscale);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
|
||||||
|
int* xpos, int* ypos,
|
||||||
|
int* width, int* height)
|
||||||
|
{
|
||||||
|
MONITORINFO mi = { sizeof(mi) };
|
||||||
|
GetMonitorInfo(monitor->win32.handle, &mi);
|
||||||
|
|
||||||
|
if (xpos)
|
||||||
|
*xpos = mi.rcWork.left;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = mi.rcWork.top;
|
||||||
|
if (width)
|
||||||
|
*width = mi.rcWork.right - mi.rcWork.left;
|
||||||
|
if (height)
|
||||||
|
*height = mi.rcWork.bottom - mi.rcWork.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||||
|
{
|
||||||
|
int modeIndex = 0, size = 0;
|
||||||
|
GLFWvidmode* result = NULL;
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
GLFWvidmode mode;
|
||||||
|
DEVMODEW dm;
|
||||||
|
|
||||||
|
ZeroMemory(&dm, sizeof(dm));
|
||||||
|
dm.dmSize = sizeof(dm);
|
||||||
|
|
||||||
|
if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm))
|
||||||
|
break;
|
||||||
|
|
||||||
|
modeIndex++;
|
||||||
|
|
||||||
|
// Skip modes with less than 15 BPP
|
||||||
|
if (dm.dmBitsPerPel < 15)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
mode.width = dm.dmPelsWidth;
|
||||||
|
mode.height = dm.dmPelsHeight;
|
||||||
|
mode.refreshRate = dm.dmDisplayFrequency;
|
||||||
|
_glfwSplitBPP(dm.dmBitsPerPel,
|
||||||
|
&mode.redBits,
|
||||||
|
&mode.greenBits,
|
||||||
|
&mode.blueBits);
|
||||||
|
|
||||||
|
for (i = 0; i < *count; i++)
|
||||||
|
{
|
||||||
|
if (_glfwCompareVideoModes(result + i, &mode) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip duplicate modes
|
||||||
|
if (i < *count)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (monitor->win32.modesPruned)
|
||||||
|
{
|
||||||
|
// Skip modes not supported by the connected displays
|
||||||
|
if (ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
||||||
|
&dm,
|
||||||
|
NULL,
|
||||||
|
CDS_TEST,
|
||||||
|
NULL) != DISP_CHANGE_SUCCESSFUL)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*count == size)
|
||||||
|
{
|
||||||
|
size += 128;
|
||||||
|
result = (GLFWvidmode*) realloc(result, size * sizeof(GLFWvidmode));
|
||||||
|
}
|
||||||
|
|
||||||
|
(*count)++;
|
||||||
|
result[*count - 1] = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*count)
|
||||||
|
{
|
||||||
|
// HACK: Report the current mode if no valid modes were found
|
||||||
|
result = calloc(1, sizeof(GLFWvidmode));
|
||||||
|
_glfwPlatformGetVideoMode(monitor, result);
|
||||||
|
*count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||||
|
{
|
||||||
|
DEVMODEW dm;
|
||||||
|
ZeroMemory(&dm, sizeof(dm));
|
||||||
|
dm.dmSize = sizeof(dm);
|
||||||
|
|
||||||
|
EnumDisplaySettingsW(monitor->win32.adapterName, ENUM_CURRENT_SETTINGS, &dm);
|
||||||
|
|
||||||
|
mode->width = dm.dmPelsWidth;
|
||||||
|
mode->height = dm.dmPelsHeight;
|
||||||
|
mode->refreshRate = dm.dmDisplayFrequency;
|
||||||
|
_glfwSplitBPP(dm.dmBitsPerPel,
|
||||||
|
&mode->redBits,
|
||||||
|
&mode->greenBits,
|
||||||
|
&mode->blueBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||||
|
{
|
||||||
|
HDC dc;
|
||||||
|
WORD values[3][256];
|
||||||
|
|
||||||
|
dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
|
||||||
|
GetDeviceGammaRamp(dc, values);
|
||||||
|
DeleteDC(dc);
|
||||||
|
|
||||||
|
_glfwAllocGammaArrays(ramp, 256);
|
||||||
|
|
||||||
|
memcpy(ramp->red, values[0], sizeof(values[0]));
|
||||||
|
memcpy(ramp->green, values[1], sizeof(values[1]));
|
||||||
|
memcpy(ramp->blue, values[2], sizeof(values[2]));
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||||
|
{
|
||||||
|
HDC dc;
|
||||||
|
WORD values[3][256];
|
||||||
|
|
||||||
|
if (ramp->size != 256)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Gamma ramp size must be 256");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(values[0], ramp->red, sizeof(values[0]));
|
||||||
|
memcpy(values[1], ramp->green, sizeof(values[1]));
|
||||||
|
memcpy(values[2], ramp->blue, sizeof(values[2]));
|
||||||
|
|
||||||
|
dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
|
||||||
|
SetDeviceGammaRamp(dc, values);
|
||||||
|
DeleteDC(dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW native API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* handle)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
return monitor->win32.publicAdapterName;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
return monitor->win32.publicDisplayName;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,469 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 Win32 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
// We don't need all the fancy stuff
|
||||||
|
#ifndef NOMINMAX
|
||||||
|
#define NOMINMAX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef VC_EXTRALEAN
|
||||||
|
#define VC_EXTRALEAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
|
||||||
|
// example to allow applications to correctly declare a GL_ARB_debug_output
|
||||||
|
// callback) but windows.h assumes no one will define APIENTRY before it does
|
||||||
|
#undef APIENTRY
|
||||||
|
|
||||||
|
// GLFW on Windows is Unicode only and does not work in MBCS mode
|
||||||
|
#ifndef UNICODE
|
||||||
|
#define UNICODE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// GLFW requires Windows XP or later
|
||||||
|
#if WINVER < 0x0501
|
||||||
|
#undef WINVER
|
||||||
|
#define WINVER 0x0501
|
||||||
|
#endif
|
||||||
|
#if _WIN32_WINNT < 0x0501
|
||||||
|
#undef _WIN32_WINNT
|
||||||
|
#define _WIN32_WINNT 0x0501
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// GLFW uses DirectInput8 interfaces
|
||||||
|
#define DIRECTINPUT_VERSION 0x0800
|
||||||
|
|
||||||
|
// GLFW uses OEM cursor resources
|
||||||
|
#define OEMRESOURCE
|
||||||
|
|
||||||
|
#include <wctype.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <dinput.h>
|
||||||
|
#include <xinput.h>
|
||||||
|
#include <dbt.h>
|
||||||
|
|
||||||
|
// HACK: Define macros that some windows.h variants don't
|
||||||
|
#ifndef WM_MOUSEHWHEEL
|
||||||
|
#define WM_MOUSEHWHEEL 0x020E
|
||||||
|
#endif
|
||||||
|
#ifndef WM_DWMCOMPOSITIONCHANGED
|
||||||
|
#define WM_DWMCOMPOSITIONCHANGED 0x031E
|
||||||
|
#endif
|
||||||
|
#ifndef WM_DWMCOLORIZATIONCOLORCHANGED
|
||||||
|
#define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320
|
||||||
|
#endif
|
||||||
|
#ifndef WM_COPYGLOBALDATA
|
||||||
|
#define WM_COPYGLOBALDATA 0x0049
|
||||||
|
#endif
|
||||||
|
#ifndef WM_UNICHAR
|
||||||
|
#define WM_UNICHAR 0x0109
|
||||||
|
#endif
|
||||||
|
#ifndef UNICODE_NOCHAR
|
||||||
|
#define UNICODE_NOCHAR 0xFFFF
|
||||||
|
#endif
|
||||||
|
#ifndef WM_DPICHANGED
|
||||||
|
#define WM_DPICHANGED 0x02E0
|
||||||
|
#endif
|
||||||
|
#ifndef GET_XBUTTON_WPARAM
|
||||||
|
#define GET_XBUTTON_WPARAM(w) (HIWORD(w))
|
||||||
|
#endif
|
||||||
|
#ifndef EDS_ROTATEDMODE
|
||||||
|
#define EDS_ROTATEDMODE 0x00000004
|
||||||
|
#endif
|
||||||
|
#ifndef DISPLAY_DEVICE_ACTIVE
|
||||||
|
#define DISPLAY_DEVICE_ACTIVE 0x00000001
|
||||||
|
#endif
|
||||||
|
#ifndef _WIN32_WINNT_WINBLUE
|
||||||
|
#define _WIN32_WINNT_WINBLUE 0x0603
|
||||||
|
#endif
|
||||||
|
#ifndef _WIN32_WINNT_WIN8
|
||||||
|
#define _WIN32_WINNT_WIN8 0x0602
|
||||||
|
#endif
|
||||||
|
#ifndef WM_GETDPISCALEDSIZE
|
||||||
|
#define WM_GETDPISCALEDSIZE 0x02e4
|
||||||
|
#endif
|
||||||
|
#ifndef USER_DEFAULT_SCREEN_DPI
|
||||||
|
#define USER_DEFAULT_SCREEN_DPI 96
|
||||||
|
#endif
|
||||||
|
#ifndef OCR_HAND
|
||||||
|
#define OCR_HAND 32649
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if WINVER < 0x0601
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
DWORD cbSize;
|
||||||
|
DWORD ExtStatus;
|
||||||
|
} CHANGEFILTERSTRUCT;
|
||||||
|
#ifndef MSGFLT_ALLOW
|
||||||
|
#define MSGFLT_ALLOW 1
|
||||||
|
#endif
|
||||||
|
#endif /*Windows 7*/
|
||||||
|
|
||||||
|
#if WINVER < 0x0600
|
||||||
|
#define DWM_BB_ENABLE 0x00000001
|
||||||
|
#define DWM_BB_BLURREGION 0x00000002
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
DWORD dwFlags;
|
||||||
|
BOOL fEnable;
|
||||||
|
HRGN hRgnBlur;
|
||||||
|
BOOL fTransitionOnMaximized;
|
||||||
|
} DWM_BLURBEHIND;
|
||||||
|
#else
|
||||||
|
#include <dwmapi.h>
|
||||||
|
#endif /*Windows Vista*/
|
||||||
|
|
||||||
|
#ifndef DPI_ENUMS_DECLARED
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
PROCESS_DPI_UNAWARE = 0,
|
||||||
|
PROCESS_SYSTEM_DPI_AWARE = 1,
|
||||||
|
PROCESS_PER_MONITOR_DPI_AWARE = 2
|
||||||
|
} PROCESS_DPI_AWARENESS;
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MDT_EFFECTIVE_DPI = 0,
|
||||||
|
MDT_ANGULAR_DPI = 1,
|
||||||
|
MDT_RAW_DPI = 2,
|
||||||
|
MDT_DEFAULT = MDT_EFFECTIVE_DPI
|
||||||
|
} MONITOR_DPI_TYPE;
|
||||||
|
#endif /*DPI_ENUMS_DECLARED*/
|
||||||
|
|
||||||
|
#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
|
||||||
|
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE) -4)
|
||||||
|
#endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/
|
||||||
|
|
||||||
|
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
|
||||||
|
#define IsWindowsXPOrGreater() \
|
||||||
|
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP), \
|
||||||
|
LOBYTE(_WIN32_WINNT_WINXP), 0)
|
||||||
|
#define IsWindowsVistaOrGreater() \
|
||||||
|
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_VISTA), \
|
||||||
|
LOBYTE(_WIN32_WINNT_VISTA), 0)
|
||||||
|
#define IsWindows7OrGreater() \
|
||||||
|
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN7), \
|
||||||
|
LOBYTE(_WIN32_WINNT_WIN7), 0)
|
||||||
|
#define IsWindows8OrGreater() \
|
||||||
|
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN8), \
|
||||||
|
LOBYTE(_WIN32_WINNT_WIN8), 0)
|
||||||
|
#define IsWindows8Point1OrGreater() \
|
||||||
|
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINBLUE), \
|
||||||
|
LOBYTE(_WIN32_WINNT_WINBLUE), 0)
|
||||||
|
|
||||||
|
#define _glfwIsWindows10AnniversaryUpdateOrGreaterWin32() \
|
||||||
|
_glfwIsWindows10BuildOrGreaterWin32(14393)
|
||||||
|
#define _glfwIsWindows10CreatorsUpdateOrGreaterWin32() \
|
||||||
|
_glfwIsWindows10BuildOrGreaterWin32(15063)
|
||||||
|
|
||||||
|
// HACK: Define macros that some xinput.h variants don't
|
||||||
|
#ifndef XINPUT_CAPS_WIRELESS
|
||||||
|
#define XINPUT_CAPS_WIRELESS 0x0002
|
||||||
|
#endif
|
||||||
|
#ifndef XINPUT_DEVSUBTYPE_WHEEL
|
||||||
|
#define XINPUT_DEVSUBTYPE_WHEEL 0x02
|
||||||
|
#endif
|
||||||
|
#ifndef XINPUT_DEVSUBTYPE_ARCADE_STICK
|
||||||
|
#define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
|
||||||
|
#endif
|
||||||
|
#ifndef XINPUT_DEVSUBTYPE_FLIGHT_STICK
|
||||||
|
#define XINPUT_DEVSUBTYPE_FLIGHT_STICK 0x04
|
||||||
|
#endif
|
||||||
|
#ifndef XINPUT_DEVSUBTYPE_DANCE_PAD
|
||||||
|
#define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
|
||||||
|
#endif
|
||||||
|
#ifndef XINPUT_DEVSUBTYPE_GUITAR
|
||||||
|
#define XINPUT_DEVSUBTYPE_GUITAR 0x06
|
||||||
|
#endif
|
||||||
|
#ifndef XINPUT_DEVSUBTYPE_DRUM_KIT
|
||||||
|
#define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
|
||||||
|
#endif
|
||||||
|
#ifndef XINPUT_DEVSUBTYPE_ARCADE_PAD
|
||||||
|
#define XINPUT_DEVSUBTYPE_ARCADE_PAD 0x13
|
||||||
|
#endif
|
||||||
|
#ifndef XUSER_MAX_COUNT
|
||||||
|
#define XUSER_MAX_COUNT 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// HACK: Define macros that some dinput.h variants don't
|
||||||
|
#ifndef DIDFT_OPTIONAL
|
||||||
|
#define DIDFT_OPTIONAL 0x80000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// winmm.dll function pointer typedefs
|
||||||
|
typedef DWORD (WINAPI * PFN_timeGetTime)(void);
|
||||||
|
#define timeGetTime _glfw.win32.winmm.GetTime
|
||||||
|
|
||||||
|
// xinput.dll function pointer typedefs
|
||||||
|
typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*);
|
||||||
|
typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
|
||||||
|
#define XInputGetCapabilities _glfw.win32.xinput.GetCapabilities
|
||||||
|
#define XInputGetState _glfw.win32.xinput.GetState
|
||||||
|
|
||||||
|
// dinput8.dll function pointer typedefs
|
||||||
|
typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
|
||||||
|
#define DirectInput8Create _glfw.win32.dinput8.Create
|
||||||
|
|
||||||
|
// user32.dll function pointer typedefs
|
||||||
|
typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
|
||||||
|
typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,CHANGEFILTERSTRUCT*);
|
||||||
|
typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND);
|
||||||
|
typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE);
|
||||||
|
typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
|
||||||
|
typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
|
||||||
|
#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
|
||||||
|
#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
|
||||||
|
#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
|
||||||
|
#define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
|
||||||
|
#define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
|
||||||
|
#define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_
|
||||||
|
|
||||||
|
// dwmapi.dll function pointer typedefs
|
||||||
|
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
||||||
|
typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
|
||||||
|
typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*);
|
||||||
|
typedef HRESULT (WINAPI * PFN_DwmGetColorizationColor)(DWORD*,BOOL*);
|
||||||
|
#define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
|
||||||
|
#define DwmFlush _glfw.win32.dwmapi.Flush
|
||||||
|
#define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow
|
||||||
|
#define DwmGetColorizationColor _glfw.win32.dwmapi.GetColorizationColor
|
||||||
|
|
||||||
|
// shcore.dll function pointer typedefs
|
||||||
|
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
||||||
|
typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);
|
||||||
|
#define SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness_
|
||||||
|
#define GetDpiForMonitor _glfw.win32.shcore.GetDpiForMonitor_
|
||||||
|
|
||||||
|
// ntdll.dll function pointer typedefs
|
||||||
|
typedef LONG (WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*,ULONG,ULONGLONG);
|
||||||
|
#define RtlVerifyVersionInfo _glfw.win32.ntdll.RtlVerifyVersionInfo_
|
||||||
|
|
||||||
|
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
|
||||||
|
|
||||||
|
typedef struct VkWin32SurfaceCreateInfoKHR
|
||||||
|
{
|
||||||
|
VkStructureType sType;
|
||||||
|
const void* pNext;
|
||||||
|
VkWin32SurfaceCreateFlagsKHR flags;
|
||||||
|
HINSTANCE hinstance;
|
||||||
|
HWND hwnd;
|
||||||
|
} VkWin32SurfaceCreateInfoKHR;
|
||||||
|
|
||||||
|
typedef VkResult (APIENTRY *PFN_vkCreateWin32SurfaceKHR)(VkInstance,const VkWin32SurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||||
|
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t);
|
||||||
|
|
||||||
|
#include "win32_joystick.h"
|
||||||
|
#include "wgl_context.h"
|
||||||
|
#include "egl_context.h"
|
||||||
|
#include "osmesa_context.h"
|
||||||
|
|
||||||
|
#if !defined(_GLFW_WNDCLASSNAME)
|
||||||
|
#define _GLFW_WNDCLASSNAME L"GLFW30"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _glfw_dlopen(name) LoadLibraryA(name)
|
||||||
|
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
|
||||||
|
#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
|
||||||
|
|
||||||
|
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->win32.handle)
|
||||||
|
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerWin32 win32
|
||||||
|
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32
|
||||||
|
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32
|
||||||
|
#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsWin32 win32
|
||||||
|
#define _GLFW_PLATFORM_MUTEX_STATE _GLFWmutexWin32 win32
|
||||||
|
|
||||||
|
|
||||||
|
// Win32-specific per-window data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWwindowWin32
|
||||||
|
{
|
||||||
|
HWND handle;
|
||||||
|
HICON bigIcon;
|
||||||
|
HICON smallIcon;
|
||||||
|
|
||||||
|
GLFWbool cursorTracked;
|
||||||
|
GLFWbool frameAction;
|
||||||
|
GLFWbool iconified;
|
||||||
|
GLFWbool maximized;
|
||||||
|
// Whether to enable framebuffer transparency on DWM
|
||||||
|
GLFWbool transparent;
|
||||||
|
GLFWbool scaleToMonitor;
|
||||||
|
|
||||||
|
// Cached size used to filter out duplicate events
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
// The last received cursor position, regardless of source
|
||||||
|
int lastCursorPosX, lastCursorPosY;
|
||||||
|
// The last recevied high surrogate when decoding pairs of UTF-16 messages
|
||||||
|
WCHAR highSurrogate;
|
||||||
|
|
||||||
|
} _GLFWwindowWin32;
|
||||||
|
|
||||||
|
// Win32-specific global data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWlibraryWin32
|
||||||
|
{
|
||||||
|
HWND helperWindowHandle;
|
||||||
|
HDEVNOTIFY deviceNotificationHandle;
|
||||||
|
DWORD foregroundLockTimeout;
|
||||||
|
int acquiredMonitorCount;
|
||||||
|
char* clipboardString;
|
||||||
|
short int keycodes[512];
|
||||||
|
short int scancodes[GLFW_KEY_LAST + 1];
|
||||||
|
char keynames[GLFW_KEY_LAST + 1][5];
|
||||||
|
// Where to place the cursor when re-enabled
|
||||||
|
double restoreCursorPosX, restoreCursorPosY;
|
||||||
|
// The window whose disabled cursor mode is active
|
||||||
|
_GLFWwindow* disabledCursorWindow;
|
||||||
|
RAWINPUT* rawInput;
|
||||||
|
int rawInputSize;
|
||||||
|
UINT mouseTrailSize;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
PFN_timeGetTime GetTime;
|
||||||
|
} winmm;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
PFN_DirectInput8Create Create;
|
||||||
|
IDirectInput8W* api;
|
||||||
|
} dinput8;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
PFN_XInputGetCapabilities GetCapabilities;
|
||||||
|
PFN_XInputGetState GetState;
|
||||||
|
} xinput;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
PFN_SetProcessDPIAware SetProcessDPIAware_;
|
||||||
|
PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_;
|
||||||
|
PFN_EnableNonClientDpiScaling EnableNonClientDpiScaling_;
|
||||||
|
PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
|
||||||
|
PFN_GetDpiForWindow GetDpiForWindow_;
|
||||||
|
PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_;
|
||||||
|
} user32;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
PFN_DwmIsCompositionEnabled IsCompositionEnabled;
|
||||||
|
PFN_DwmFlush Flush;
|
||||||
|
PFN_DwmEnableBlurBehindWindow EnableBlurBehindWindow;
|
||||||
|
PFN_DwmGetColorizationColor GetColorizationColor;
|
||||||
|
} dwmapi;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
PFN_SetProcessDpiAwareness SetProcessDpiAwareness_;
|
||||||
|
PFN_GetDpiForMonitor GetDpiForMonitor_;
|
||||||
|
} shcore;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HINSTANCE instance;
|
||||||
|
PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_;
|
||||||
|
} ntdll;
|
||||||
|
|
||||||
|
} _GLFWlibraryWin32;
|
||||||
|
|
||||||
|
// Win32-specific per-monitor data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWmonitorWin32
|
||||||
|
{
|
||||||
|
HMONITOR handle;
|
||||||
|
// This size matches the static size of DISPLAY_DEVICE.DeviceName
|
||||||
|
WCHAR adapterName[32];
|
||||||
|
WCHAR displayName[32];
|
||||||
|
char publicAdapterName[32];
|
||||||
|
char publicDisplayName[32];
|
||||||
|
GLFWbool modesPruned;
|
||||||
|
GLFWbool modeChanged;
|
||||||
|
|
||||||
|
} _GLFWmonitorWin32;
|
||||||
|
|
||||||
|
// Win32-specific per-cursor data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWcursorWin32
|
||||||
|
{
|
||||||
|
HCURSOR handle;
|
||||||
|
|
||||||
|
} _GLFWcursorWin32;
|
||||||
|
|
||||||
|
// Win32-specific global timer data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWtimerWin32
|
||||||
|
{
|
||||||
|
GLFWbool hasPC;
|
||||||
|
uint64_t frequency;
|
||||||
|
|
||||||
|
} _GLFWtimerWin32;
|
||||||
|
|
||||||
|
// Win32-specific thread local storage data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWtlsWin32
|
||||||
|
{
|
||||||
|
GLFWbool allocated;
|
||||||
|
DWORD index;
|
||||||
|
|
||||||
|
} _GLFWtlsWin32;
|
||||||
|
|
||||||
|
// Win32-specific mutex data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWmutexWin32
|
||||||
|
{
|
||||||
|
GLFWbool allocated;
|
||||||
|
CRITICAL_SECTION section;
|
||||||
|
|
||||||
|
} _GLFWmutexWin32;
|
||||||
|
|
||||||
|
|
||||||
|
GLFWbool _glfwRegisterWindowClassWin32(void);
|
||||||
|
void _glfwUnregisterWindowClassWin32(void);
|
||||||
|
|
||||||
|
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
|
||||||
|
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
|
||||||
|
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp);
|
||||||
|
BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build);
|
||||||
|
void _glfwInputErrorWin32(int error, const char* description);
|
||||||
|
void _glfwUpdateKeyNamesWin32(void);
|
||||||
|
|
||||||
|
void _glfwInitTimerWin32(void);
|
||||||
|
|
||||||
|
void _glfwPollMonitorsWin32(void);
|
||||||
|
void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||||
|
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
|
||||||
|
void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale);
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 Win32 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
|
||||||
|
{
|
||||||
|
assert(tls->win32.allocated == GLFW_FALSE);
|
||||||
|
|
||||||
|
tls->win32.index = TlsAlloc();
|
||||||
|
if (tls->win32.index == TLS_OUT_OF_INDEXES)
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to allocate TLS index");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
tls->win32.allocated = GLFW_TRUE;
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
||||||
|
{
|
||||||
|
if (tls->win32.allocated)
|
||||||
|
TlsFree(tls->win32.index);
|
||||||
|
memset(tls, 0, sizeof(_GLFWtls));
|
||||||
|
}
|
||||||
|
|
||||||
|
void* _glfwPlatformGetTls(_GLFWtls* tls)
|
||||||
|
{
|
||||||
|
assert(tls->win32.allocated == GLFW_TRUE);
|
||||||
|
return TlsGetValue(tls->win32.index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
|
||||||
|
{
|
||||||
|
assert(tls->win32.allocated == GLFW_TRUE);
|
||||||
|
TlsSetValue(tls->win32.index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
|
||||||
|
{
|
||||||
|
assert(mutex->win32.allocated == GLFW_FALSE);
|
||||||
|
InitializeCriticalSection(&mutex->win32.section);
|
||||||
|
return mutex->win32.allocated = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
|
||||||
|
{
|
||||||
|
if (mutex->win32.allocated)
|
||||||
|
DeleteCriticalSection(&mutex->win32.section);
|
||||||
|
memset(mutex, 0, sizeof(_GLFWmutex));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformLockMutex(_GLFWmutex* mutex)
|
||||||
|
{
|
||||||
|
assert(mutex->win32.allocated == GLFW_TRUE);
|
||||||
|
EnterCriticalSection(&mutex->win32.section);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
|
||||||
|
{
|
||||||
|
assert(mutex->win32.allocated == GLFW_TRUE);
|
||||||
|
LeaveCriticalSection(&mutex->win32.section);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 Win32 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Initialise timer
|
||||||
|
//
|
||||||
|
void _glfwInitTimerWin32(void)
|
||||||
|
{
|
||||||
|
uint64_t frequency;
|
||||||
|
|
||||||
|
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
|
||||||
|
{
|
||||||
|
_glfw.timer.win32.hasPC = GLFW_TRUE;
|
||||||
|
_glfw.timer.win32.frequency = frequency;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfw.timer.win32.hasPC = GLFW_FALSE;
|
||||||
|
_glfw.timer.win32.frequency = 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
uint64_t _glfwPlatformGetTimerValue(void)
|
||||||
|
{
|
||||||
|
if (_glfw.timer.win32.hasPC)
|
||||||
|
{
|
||||||
|
uint64_t value;
|
||||||
|
QueryPerformanceCounter((LARGE_INTEGER*) &value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return (uint64_t) timeGetTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t _glfwPlatformGetTimerFrequency(void)
|
||||||
|
{
|
||||||
|
return _glfw.timer.win32.frequency;
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,233 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 Wayland - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
|
static void outputHandleGeometry(void* data,
|
||||||
|
struct wl_output* output,
|
||||||
|
int32_t x,
|
||||||
|
int32_t y,
|
||||||
|
int32_t physicalWidth,
|
||||||
|
int32_t physicalHeight,
|
||||||
|
int32_t subpixel,
|
||||||
|
const char* make,
|
||||||
|
const char* model,
|
||||||
|
int32_t transform)
|
||||||
|
{
|
||||||
|
struct _GLFWmonitor *monitor = data;
|
||||||
|
char name[1024];
|
||||||
|
|
||||||
|
monitor->wl.x = x;
|
||||||
|
monitor->wl.y = y;
|
||||||
|
monitor->widthMM = physicalWidth;
|
||||||
|
monitor->heightMM = physicalHeight;
|
||||||
|
|
||||||
|
snprintf(name, sizeof(name), "%s %s", make, model);
|
||||||
|
monitor->name = _glfw_strdup(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void outputHandleMode(void* data,
|
||||||
|
struct wl_output* output,
|
||||||
|
uint32_t flags,
|
||||||
|
int32_t width,
|
||||||
|
int32_t height,
|
||||||
|
int32_t refresh)
|
||||||
|
{
|
||||||
|
struct _GLFWmonitor *monitor = data;
|
||||||
|
GLFWvidmode mode;
|
||||||
|
|
||||||
|
mode.width = width;
|
||||||
|
mode.height = height;
|
||||||
|
mode.redBits = 8;
|
||||||
|
mode.greenBits = 8;
|
||||||
|
mode.blueBits = 8;
|
||||||
|
mode.refreshRate = (int) round(refresh / 1000.0);
|
||||||
|
|
||||||
|
monitor->modeCount++;
|
||||||
|
monitor->modes =
|
||||||
|
realloc(monitor->modes, monitor->modeCount * sizeof(GLFWvidmode));
|
||||||
|
monitor->modes[monitor->modeCount - 1] = mode;
|
||||||
|
|
||||||
|
if (flags & WL_OUTPUT_MODE_CURRENT)
|
||||||
|
monitor->wl.currentMode = monitor->modeCount - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void outputHandleDone(void* data, struct wl_output* output)
|
||||||
|
{
|
||||||
|
struct _GLFWmonitor *monitor = data;
|
||||||
|
|
||||||
|
if (monitor->widthMM <= 0 || monitor->heightMM <= 0)
|
||||||
|
{
|
||||||
|
// If Wayland does not provide a physical size, assume the default 96 DPI
|
||||||
|
const GLFWvidmode* mode = &monitor->modes[monitor->wl.currentMode];
|
||||||
|
monitor->widthMM = (int) (mode->width * 25.4f / 96.f);
|
||||||
|
monitor->heightMM = (int) (mode->height * 25.4f / 96.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void outputHandleScale(void* data,
|
||||||
|
struct wl_output* output,
|
||||||
|
int32_t factor)
|
||||||
|
{
|
||||||
|
struct _GLFWmonitor *monitor = data;
|
||||||
|
|
||||||
|
monitor->wl.scale = factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_output_listener outputListener = {
|
||||||
|
outputHandleGeometry,
|
||||||
|
outputHandleMode,
|
||||||
|
outputHandleDone,
|
||||||
|
outputHandleScale,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void _glfwAddOutputWayland(uint32_t name, uint32_t version)
|
||||||
|
{
|
||||||
|
_GLFWmonitor *monitor;
|
||||||
|
struct wl_output *output;
|
||||||
|
|
||||||
|
if (version < 2)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: Unsupported output interface version");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The actual name of this output will be set in the geometry handler.
|
||||||
|
monitor = _glfwAllocMonitor(NULL, 0, 0);
|
||||||
|
|
||||||
|
output = wl_registry_bind(_glfw.wl.registry,
|
||||||
|
name,
|
||||||
|
&wl_output_interface,
|
||||||
|
2);
|
||||||
|
if (!output)
|
||||||
|
{
|
||||||
|
_glfwFreeMonitor(monitor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor->wl.scale = 1;
|
||||||
|
monitor->wl.output = output;
|
||||||
|
monitor->wl.name = name;
|
||||||
|
|
||||||
|
wl_output_add_listener(output, &outputListener, monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
|
||||||
|
{
|
||||||
|
if (monitor->wl.output)
|
||||||
|
wl_output_destroy(monitor->wl.output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||||
|
{
|
||||||
|
if (xpos)
|
||||||
|
*xpos = monitor->wl.x;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = monitor->wl.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||||
|
float* xscale, float* yscale)
|
||||||
|
{
|
||||||
|
if (xscale)
|
||||||
|
*xscale = (float) monitor->wl.scale;
|
||||||
|
if (yscale)
|
||||||
|
*yscale = (float) monitor->wl.scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
|
||||||
|
int* xpos, int* ypos,
|
||||||
|
int* width, int* height)
|
||||||
|
{
|
||||||
|
if (xpos)
|
||||||
|
*xpos = monitor->wl.x;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = monitor->wl.y;
|
||||||
|
if (width)
|
||||||
|
*width = monitor->modes[monitor->wl.currentMode].width;
|
||||||
|
if (height)
|
||||||
|
*height = monitor->modes[monitor->wl.currentMode].height;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||||
|
{
|
||||||
|
*found = monitor->modeCount;
|
||||||
|
return monitor->modes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||||
|
{
|
||||||
|
*mode = monitor->modes[monitor->wl.currentMode];
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: Gamma ramp access is not available");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor,
|
||||||
|
const GLFWgammaramp* ramp)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: Gamma ramp access is not available");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW native API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
return monitor->wl.output;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,359 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 Wayland - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||||
|
#include <xkbcommon/xkbcommon-compose.h>
|
||||||
|
#endif
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
|
||||||
|
|
||||||
|
typedef struct VkWaylandSurfaceCreateInfoKHR
|
||||||
|
{
|
||||||
|
VkStructureType sType;
|
||||||
|
const void* pNext;
|
||||||
|
VkWaylandSurfaceCreateFlagsKHR flags;
|
||||||
|
struct wl_display* display;
|
||||||
|
struct wl_surface* surface;
|
||||||
|
} VkWaylandSurfaceCreateInfoKHR;
|
||||||
|
|
||||||
|
typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWaylandSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||||
|
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
|
||||||
|
|
||||||
|
#include "posix_thread.h"
|
||||||
|
#include "posix_time.h"
|
||||||
|
#ifdef __linux__
|
||||||
|
#include "linux_joystick.h"
|
||||||
|
#else
|
||||||
|
#include "null_joystick.h"
|
||||||
|
#endif
|
||||||
|
#include "xkb_unicode.h"
|
||||||
|
#include "egl_context.h"
|
||||||
|
#include "osmesa_context.h"
|
||||||
|
|
||||||
|
#include "wayland-xdg-shell-client-protocol.h"
|
||||||
|
#include "wayland-xdg-decoration-client-protocol.h"
|
||||||
|
#include "wayland-viewporter-client-protocol.h"
|
||||||
|
#include "wayland-relative-pointer-unstable-v1-client-protocol.h"
|
||||||
|
#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
|
||||||
|
#include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
|
||||||
|
|
||||||
|
#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_WINDOW ((EGLNativeWindowType) window->wl.native)
|
||||||
|
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.wl.display)
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWayland wl
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWayland wl
|
||||||
|
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWayland wl
|
||||||
|
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWayland wl
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_CONTEXT_STATE struct { int dummyContext; }
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE struct { int dummyLibraryContext; }
|
||||||
|
|
||||||
|
struct wl_cursor_image {
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
uint32_t hotspot_x;
|
||||||
|
uint32_t hotspot_y;
|
||||||
|
uint32_t delay;
|
||||||
|
};
|
||||||
|
struct wl_cursor {
|
||||||
|
unsigned int image_count;
|
||||||
|
struct wl_cursor_image** images;
|
||||||
|
char* name;
|
||||||
|
};
|
||||||
|
typedef struct wl_cursor_theme* (* PFN_wl_cursor_theme_load)(const char*, int, struct wl_shm*);
|
||||||
|
typedef void (* PFN_wl_cursor_theme_destroy)(struct wl_cursor_theme*);
|
||||||
|
typedef struct wl_cursor* (* PFN_wl_cursor_theme_get_cursor)(struct wl_cursor_theme*, const char*);
|
||||||
|
typedef struct wl_buffer* (* PFN_wl_cursor_image_get_buffer)(struct wl_cursor_image*);
|
||||||
|
#define wl_cursor_theme_load _glfw.wl.cursor.theme_load
|
||||||
|
#define wl_cursor_theme_destroy _glfw.wl.cursor.theme_destroy
|
||||||
|
#define wl_cursor_theme_get_cursor _glfw.wl.cursor.theme_get_cursor
|
||||||
|
#define wl_cursor_image_get_buffer _glfw.wl.cursor.image_get_buffer
|
||||||
|
|
||||||
|
typedef struct wl_egl_window* (* PFN_wl_egl_window_create)(struct wl_surface*, int, int);
|
||||||
|
typedef void (* PFN_wl_egl_window_destroy)(struct wl_egl_window*);
|
||||||
|
typedef void (* PFN_wl_egl_window_resize)(struct wl_egl_window*, int, int, int, int);
|
||||||
|
#define wl_egl_window_create _glfw.wl.egl.window_create
|
||||||
|
#define wl_egl_window_destroy _glfw.wl.egl.window_destroy
|
||||||
|
#define wl_egl_window_resize _glfw.wl.egl.window_resize
|
||||||
|
|
||||||
|
typedef struct xkb_context* (* PFN_xkb_context_new)(enum xkb_context_flags);
|
||||||
|
typedef void (* PFN_xkb_context_unref)(struct xkb_context*);
|
||||||
|
typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context*, const char*, enum xkb_keymap_format, enum xkb_keymap_compile_flags);
|
||||||
|
typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*);
|
||||||
|
typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*);
|
||||||
|
typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);
|
||||||
|
typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
|
||||||
|
typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
|
||||||
|
typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
|
||||||
|
typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
|
||||||
|
typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);
|
||||||
|
#define xkb_context_new _glfw.wl.xkb.context_new
|
||||||
|
#define xkb_context_unref _glfw.wl.xkb.context_unref
|
||||||
|
#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string
|
||||||
|
#define xkb_keymap_unref _glfw.wl.xkb.keymap_unref
|
||||||
|
#define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index
|
||||||
|
#define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats
|
||||||
|
#define xkb_state_new _glfw.wl.xkb.state_new
|
||||||
|
#define xkb_state_unref _glfw.wl.xkb.state_unref
|
||||||
|
#define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms
|
||||||
|
#define xkb_state_update_mask _glfw.wl.xkb.state_update_mask
|
||||||
|
#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods
|
||||||
|
|
||||||
|
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||||
|
typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
|
||||||
|
typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
|
||||||
|
typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags);
|
||||||
|
typedef void (* PFN_xkb_compose_state_unref)(struct xkb_compose_state*);
|
||||||
|
typedef enum xkb_compose_feed_result (* PFN_xkb_compose_state_feed)(struct xkb_compose_state*, xkb_keysym_t);
|
||||||
|
typedef enum xkb_compose_status (* PFN_xkb_compose_state_get_status)(struct xkb_compose_state*);
|
||||||
|
typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_state*);
|
||||||
|
#define xkb_compose_table_new_from_locale _glfw.wl.xkb.compose_table_new_from_locale
|
||||||
|
#define xkb_compose_table_unref _glfw.wl.xkb.compose_table_unref
|
||||||
|
#define xkb_compose_state_new _glfw.wl.xkb.compose_state_new
|
||||||
|
#define xkb_compose_state_unref _glfw.wl.xkb.compose_state_unref
|
||||||
|
#define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed
|
||||||
|
#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
|
||||||
|
#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _GLFW_DECORATION_WIDTH 4
|
||||||
|
#define _GLFW_DECORATION_TOP 24
|
||||||
|
#define _GLFW_DECORATION_VERTICAL (_GLFW_DECORATION_TOP + _GLFW_DECORATION_WIDTH)
|
||||||
|
#define _GLFW_DECORATION_HORIZONTAL (2 * _GLFW_DECORATION_WIDTH)
|
||||||
|
|
||||||
|
typedef enum _GLFWdecorationSideWayland
|
||||||
|
{
|
||||||
|
mainWindow,
|
||||||
|
topDecoration,
|
||||||
|
leftDecoration,
|
||||||
|
rightDecoration,
|
||||||
|
bottomDecoration,
|
||||||
|
|
||||||
|
} _GLFWdecorationSideWayland;
|
||||||
|
|
||||||
|
typedef struct _GLFWdecorationWayland
|
||||||
|
{
|
||||||
|
struct wl_surface* surface;
|
||||||
|
struct wl_subsurface* subsurface;
|
||||||
|
struct wp_viewport* viewport;
|
||||||
|
|
||||||
|
} _GLFWdecorationWayland;
|
||||||
|
|
||||||
|
// Wayland-specific per-window data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWwindowWayland
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
GLFWbool visible;
|
||||||
|
GLFWbool maximized;
|
||||||
|
GLFWbool hovered;
|
||||||
|
GLFWbool transparent;
|
||||||
|
struct wl_surface* surface;
|
||||||
|
struct wl_egl_window* native;
|
||||||
|
struct wl_shell_surface* shellSurface;
|
||||||
|
struct wl_callback* callback;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct xdg_surface* surface;
|
||||||
|
struct xdg_toplevel* toplevel;
|
||||||
|
struct zxdg_toplevel_decoration_v1* decoration;
|
||||||
|
} xdg;
|
||||||
|
|
||||||
|
_GLFWcursor* currentCursor;
|
||||||
|
double cursorPosX, cursorPosY;
|
||||||
|
|
||||||
|
char* title;
|
||||||
|
|
||||||
|
// We need to track the monitors the window spans on to calculate the
|
||||||
|
// optimal scaling factor.
|
||||||
|
int scale;
|
||||||
|
_GLFWmonitor** monitors;
|
||||||
|
int monitorsCount;
|
||||||
|
int monitorsSize;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct zwp_relative_pointer_v1* relativePointer;
|
||||||
|
struct zwp_locked_pointer_v1* lockedPointer;
|
||||||
|
} pointerLock;
|
||||||
|
|
||||||
|
struct zwp_idle_inhibitor_v1* idleInhibitor;
|
||||||
|
|
||||||
|
GLFWbool wasFullscreen;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
GLFWbool serverSide;
|
||||||
|
struct wl_buffer* buffer;
|
||||||
|
_GLFWdecorationWayland top, left, right, bottom;
|
||||||
|
int focus;
|
||||||
|
} decorations;
|
||||||
|
|
||||||
|
} _GLFWwindowWayland;
|
||||||
|
|
||||||
|
// Wayland-specific global data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWlibraryWayland
|
||||||
|
{
|
||||||
|
struct wl_display* display;
|
||||||
|
struct wl_registry* registry;
|
||||||
|
struct wl_compositor* compositor;
|
||||||
|
struct wl_subcompositor* subcompositor;
|
||||||
|
struct wl_shell* shell;
|
||||||
|
struct wl_shm* shm;
|
||||||
|
struct wl_seat* seat;
|
||||||
|
struct wl_pointer* pointer;
|
||||||
|
struct wl_keyboard* keyboard;
|
||||||
|
struct wl_data_device_manager* dataDeviceManager;
|
||||||
|
struct wl_data_device* dataDevice;
|
||||||
|
struct wl_data_offer* dataOffer;
|
||||||
|
struct wl_data_source* dataSource;
|
||||||
|
struct xdg_wm_base* wmBase;
|
||||||
|
struct zxdg_decoration_manager_v1* decorationManager;
|
||||||
|
struct wp_viewporter* viewporter;
|
||||||
|
struct zwp_relative_pointer_manager_v1* relativePointerManager;
|
||||||
|
struct zwp_pointer_constraints_v1* pointerConstraints;
|
||||||
|
struct zwp_idle_inhibit_manager_v1* idleInhibitManager;
|
||||||
|
|
||||||
|
int compositorVersion;
|
||||||
|
int seatVersion;
|
||||||
|
|
||||||
|
struct wl_cursor_theme* cursorTheme;
|
||||||
|
struct wl_cursor_theme* cursorThemeHiDPI;
|
||||||
|
struct wl_surface* cursorSurface;
|
||||||
|
const char* cursorPreviousName;
|
||||||
|
int cursorTimerfd;
|
||||||
|
uint32_t serial;
|
||||||
|
|
||||||
|
int32_t keyboardRepeatRate;
|
||||||
|
int32_t keyboardRepeatDelay;
|
||||||
|
int keyboardLastKey;
|
||||||
|
int keyboardLastScancode;
|
||||||
|
char* clipboardString;
|
||||||
|
size_t clipboardSize;
|
||||||
|
char* clipboardSendString;
|
||||||
|
size_t clipboardSendSize;
|
||||||
|
int timerfd;
|
||||||
|
short int keycodes[256];
|
||||||
|
short int scancodes[GLFW_KEY_LAST + 1];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
void* handle;
|
||||||
|
struct xkb_context* context;
|
||||||
|
struct xkb_keymap* keymap;
|
||||||
|
struct xkb_state* state;
|
||||||
|
|
||||||
|
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||||
|
struct xkb_compose_state* composeState;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
xkb_mod_mask_t controlMask;
|
||||||
|
xkb_mod_mask_t altMask;
|
||||||
|
xkb_mod_mask_t shiftMask;
|
||||||
|
xkb_mod_mask_t superMask;
|
||||||
|
xkb_mod_mask_t capsLockMask;
|
||||||
|
xkb_mod_mask_t numLockMask;
|
||||||
|
unsigned int modifiers;
|
||||||
|
|
||||||
|
PFN_xkb_context_new context_new;
|
||||||
|
PFN_xkb_context_unref context_unref;
|
||||||
|
PFN_xkb_keymap_new_from_string keymap_new_from_string;
|
||||||
|
PFN_xkb_keymap_unref keymap_unref;
|
||||||
|
PFN_xkb_keymap_mod_get_index keymap_mod_get_index;
|
||||||
|
PFN_xkb_keymap_key_repeats keymap_key_repeats;
|
||||||
|
PFN_xkb_state_new state_new;
|
||||||
|
PFN_xkb_state_unref state_unref;
|
||||||
|
PFN_xkb_state_key_get_syms state_key_get_syms;
|
||||||
|
PFN_xkb_state_update_mask state_update_mask;
|
||||||
|
PFN_xkb_state_serialize_mods state_serialize_mods;
|
||||||
|
|
||||||
|
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
||||||
|
PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
|
||||||
|
PFN_xkb_compose_table_unref compose_table_unref;
|
||||||
|
PFN_xkb_compose_state_new compose_state_new;
|
||||||
|
PFN_xkb_compose_state_unref compose_state_unref;
|
||||||
|
PFN_xkb_compose_state_feed compose_state_feed;
|
||||||
|
PFN_xkb_compose_state_get_status compose_state_get_status;
|
||||||
|
PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
|
||||||
|
#endif
|
||||||
|
} xkb;
|
||||||
|
|
||||||
|
_GLFWwindow* pointerFocus;
|
||||||
|
_GLFWwindow* keyboardFocus;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
void* handle;
|
||||||
|
|
||||||
|
PFN_wl_cursor_theme_load theme_load;
|
||||||
|
PFN_wl_cursor_theme_destroy theme_destroy;
|
||||||
|
PFN_wl_cursor_theme_get_cursor theme_get_cursor;
|
||||||
|
PFN_wl_cursor_image_get_buffer image_get_buffer;
|
||||||
|
} cursor;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
void* handle;
|
||||||
|
|
||||||
|
PFN_wl_egl_window_create window_create;
|
||||||
|
PFN_wl_egl_window_destroy window_destroy;
|
||||||
|
PFN_wl_egl_window_resize window_resize;
|
||||||
|
} egl;
|
||||||
|
|
||||||
|
} _GLFWlibraryWayland;
|
||||||
|
|
||||||
|
// Wayland-specific per-monitor data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWmonitorWayland
|
||||||
|
{
|
||||||
|
struct wl_output* output;
|
||||||
|
uint32_t name;
|
||||||
|
int currentMode;
|
||||||
|
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int scale;
|
||||||
|
|
||||||
|
} _GLFWmonitorWayland;
|
||||||
|
|
||||||
|
// Wayland-specific per-cursor data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWcursorWayland
|
||||||
|
{
|
||||||
|
struct wl_cursor* cursor;
|
||||||
|
struct wl_cursor* cursorHiDPI;
|
||||||
|
struct wl_buffer* buffer;
|
||||||
|
int width, height;
|
||||||
|
int xhot, yhot;
|
||||||
|
int currentImage;
|
||||||
|
} _GLFWcursorWayland;
|
||||||
|
|
||||||
|
|
||||||
|
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,614 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 X11 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Check whether the display mode should be included in enumeration
|
||||||
|
//
|
||||||
|
static GLFWbool modeIsGood(const XRRModeInfo* mi)
|
||||||
|
{
|
||||||
|
return (mi->modeFlags & RR_Interlace) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates the refresh rate, in Hz, from the specified RandR mode info
|
||||||
|
//
|
||||||
|
static int calculateRefreshRate(const XRRModeInfo* mi)
|
||||||
|
{
|
||||||
|
if (mi->hTotal && mi->vTotal)
|
||||||
|
return (int) round((double) mi->dotClock / ((double) mi->hTotal * (double) mi->vTotal));
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the mode info for a RandR mode XID
|
||||||
|
//
|
||||||
|
static const XRRModeInfo* getModeInfo(const XRRScreenResources* sr, RRMode id)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < sr->nmode; i++)
|
||||||
|
{
|
||||||
|
if (sr->modes[i].id == id)
|
||||||
|
return sr->modes + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert RandR mode info to GLFW video mode
|
||||||
|
//
|
||||||
|
static GLFWvidmode vidmodeFromModeInfo(const XRRModeInfo* mi,
|
||||||
|
const XRRCrtcInfo* ci)
|
||||||
|
{
|
||||||
|
GLFWvidmode mode;
|
||||||
|
|
||||||
|
if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
|
||||||
|
{
|
||||||
|
mode.width = mi->height;
|
||||||
|
mode.height = mi->width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mode.width = mi->width;
|
||||||
|
mode.height = mi->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
mode.refreshRate = calculateRefreshRate(mi);
|
||||||
|
|
||||||
|
_glfwSplitBPP(DefaultDepth(_glfw.x11.display, _glfw.x11.screen),
|
||||||
|
&mode.redBits, &mode.greenBits, &mode.blueBits);
|
||||||
|
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Poll for changes in the set of connected monitors
|
||||||
|
//
|
||||||
|
void _glfwPollMonitorsX11(void)
|
||||||
|
{
|
||||||
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
|
{
|
||||||
|
int disconnectedCount, screenCount = 0;
|
||||||
|
_GLFWmonitor** disconnected = NULL;
|
||||||
|
XineramaScreenInfo* screens = NULL;
|
||||||
|
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display,
|
||||||
|
_glfw.x11.root);
|
||||||
|
RROutput primary = XRRGetOutputPrimary(_glfw.x11.display,
|
||||||
|
_glfw.x11.root);
|
||||||
|
|
||||||
|
if (_glfw.x11.xinerama.available)
|
||||||
|
screens = XineramaQueryScreens(_glfw.x11.display, &screenCount);
|
||||||
|
|
||||||
|
disconnectedCount = _glfw.monitorCount;
|
||||||
|
if (disconnectedCount)
|
||||||
|
{
|
||||||
|
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
|
||||||
|
memcpy(disconnected,
|
||||||
|
_glfw.monitors,
|
||||||
|
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < sr->noutput; i++)
|
||||||
|
{
|
||||||
|
int j, type, widthMM, heightMM;
|
||||||
|
|
||||||
|
XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, sr->outputs[i]);
|
||||||
|
if (oi->connection != RR_Connected || oi->crtc == None)
|
||||||
|
{
|
||||||
|
XRRFreeOutputInfo(oi);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < disconnectedCount; j++)
|
||||||
|
{
|
||||||
|
if (disconnected[j] &&
|
||||||
|
disconnected[j]->x11.output == sr->outputs[i])
|
||||||
|
{
|
||||||
|
disconnected[j] = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j < disconnectedCount)
|
||||||
|
{
|
||||||
|
XRRFreeOutputInfo(oi);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc);
|
||||||
|
if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
|
||||||
|
{
|
||||||
|
widthMM = oi->mm_height;
|
||||||
|
heightMM = oi->mm_width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
widthMM = oi->mm_width;
|
||||||
|
heightMM = oi->mm_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (widthMM <= 0 || heightMM <= 0)
|
||||||
|
{
|
||||||
|
// HACK: If RandR does not provide a physical size, assume the
|
||||||
|
// X11 default 96 DPI and calculate from the CRTC viewport
|
||||||
|
// NOTE: These members are affected by rotation, unlike the mode
|
||||||
|
// info and output info members
|
||||||
|
widthMM = (int) (ci->width * 25.4f / 96.f);
|
||||||
|
heightMM = (int) (ci->height * 25.4f / 96.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
_GLFWmonitor* monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);
|
||||||
|
monitor->x11.output = sr->outputs[i];
|
||||||
|
monitor->x11.crtc = oi->crtc;
|
||||||
|
|
||||||
|
for (j = 0; j < screenCount; j++)
|
||||||
|
{
|
||||||
|
if (screens[j].x_org == ci->x &&
|
||||||
|
screens[j].y_org == ci->y &&
|
||||||
|
screens[j].width == ci->width &&
|
||||||
|
screens[j].height == ci->height)
|
||||||
|
{
|
||||||
|
monitor->x11.index = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (monitor->x11.output == primary)
|
||||||
|
type = _GLFW_INSERT_FIRST;
|
||||||
|
else
|
||||||
|
type = _GLFW_INSERT_LAST;
|
||||||
|
|
||||||
|
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
|
||||||
|
|
||||||
|
XRRFreeOutputInfo(oi);
|
||||||
|
XRRFreeCrtcInfo(ci);
|
||||||
|
}
|
||||||
|
|
||||||
|
XRRFreeScreenResources(sr);
|
||||||
|
|
||||||
|
if (screens)
|
||||||
|
XFree(screens);
|
||||||
|
|
||||||
|
for (int i = 0; i < disconnectedCount; i++)
|
||||||
|
{
|
||||||
|
if (disconnected[i])
|
||||||
|
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(disconnected);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const int widthMM = DisplayWidthMM(_glfw.x11.display, _glfw.x11.screen);
|
||||||
|
const int heightMM = DisplayHeightMM(_glfw.x11.display, _glfw.x11.screen);
|
||||||
|
|
||||||
|
_glfwInputMonitor(_glfwAllocMonitor("Display", widthMM, heightMM),
|
||||||
|
GLFW_CONNECTED,
|
||||||
|
_GLFW_INSERT_FIRST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the current video mode for the specified monitor
|
||||||
|
//
|
||||||
|
void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||||
|
{
|
||||||
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
|
{
|
||||||
|
GLFWvidmode current;
|
||||||
|
RRMode native = None;
|
||||||
|
|
||||||
|
const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired);
|
||||||
|
_glfwPlatformGetVideoMode(monitor, ¤t);
|
||||||
|
if (_glfwCompareVideoModes(¤t, best) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
XRRScreenResources* sr =
|
||||||
|
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
|
XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
|
||||||
|
|
||||||
|
for (int i = 0; i < oi->nmode; i++)
|
||||||
|
{
|
||||||
|
const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
|
||||||
|
if (!modeIsGood(mi))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
|
||||||
|
if (_glfwCompareVideoModes(best, &mode) == 0)
|
||||||
|
{
|
||||||
|
native = mi->id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (native)
|
||||||
|
{
|
||||||
|
if (monitor->x11.oldMode == None)
|
||||||
|
monitor->x11.oldMode = ci->mode;
|
||||||
|
|
||||||
|
XRRSetCrtcConfig(_glfw.x11.display,
|
||||||
|
sr, monitor->x11.crtc,
|
||||||
|
CurrentTime,
|
||||||
|
ci->x, ci->y,
|
||||||
|
native,
|
||||||
|
ci->rotation,
|
||||||
|
ci->outputs,
|
||||||
|
ci->noutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
XRRFreeOutputInfo(oi);
|
||||||
|
XRRFreeCrtcInfo(ci);
|
||||||
|
XRRFreeScreenResources(sr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore the saved (original) video mode for the specified monitor
|
||||||
|
//
|
||||||
|
void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor)
|
||||||
|
{
|
||||||
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
|
{
|
||||||
|
if (monitor->x11.oldMode == None)
|
||||||
|
return;
|
||||||
|
|
||||||
|
XRRScreenResources* sr =
|
||||||
|
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
|
|
||||||
|
XRRSetCrtcConfig(_glfw.x11.display,
|
||||||
|
sr, monitor->x11.crtc,
|
||||||
|
CurrentTime,
|
||||||
|
ci->x, ci->y,
|
||||||
|
monitor->x11.oldMode,
|
||||||
|
ci->rotation,
|
||||||
|
ci->outputs,
|
||||||
|
ci->noutput);
|
||||||
|
|
||||||
|
XRRFreeCrtcInfo(ci);
|
||||||
|
XRRFreeScreenResources(sr);
|
||||||
|
|
||||||
|
monitor->x11.oldMode = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||||
|
{
|
||||||
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
|
{
|
||||||
|
XRRScreenResources* sr =
|
||||||
|
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
|
|
||||||
|
if (ci)
|
||||||
|
{
|
||||||
|
if (xpos)
|
||||||
|
*xpos = ci->x;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = ci->y;
|
||||||
|
|
||||||
|
XRRFreeCrtcInfo(ci);
|
||||||
|
}
|
||||||
|
|
||||||
|
XRRFreeScreenResources(sr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||||
|
float* xscale, float* yscale)
|
||||||
|
{
|
||||||
|
if (xscale)
|
||||||
|
*xscale = _glfw.x11.contentScaleX;
|
||||||
|
if (yscale)
|
||||||
|
*yscale = _glfw.x11.contentScaleY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height)
|
||||||
|
{
|
||||||
|
int areaX = 0, areaY = 0, areaWidth = 0, areaHeight = 0;
|
||||||
|
|
||||||
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
|
{
|
||||||
|
XRRScreenResources* sr =
|
||||||
|
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
|
|
||||||
|
areaX = ci->x;
|
||||||
|
areaY = ci->y;
|
||||||
|
|
||||||
|
const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
|
||||||
|
|
||||||
|
if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
|
||||||
|
{
|
||||||
|
areaWidth = mi->height;
|
||||||
|
areaHeight = mi->width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
areaWidth = mi->width;
|
||||||
|
areaHeight = mi->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
XRRFreeCrtcInfo(ci);
|
||||||
|
XRRFreeScreenResources(sr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
areaWidth = DisplayWidth(_glfw.x11.display, _glfw.x11.screen);
|
||||||
|
areaHeight = DisplayHeight(_glfw.x11.display, _glfw.x11.screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.x11.NET_WORKAREA && _glfw.x11.NET_CURRENT_DESKTOP)
|
||||||
|
{
|
||||||
|
Atom* extents = NULL;
|
||||||
|
Atom* desktop = NULL;
|
||||||
|
const unsigned long extentCount =
|
||||||
|
_glfwGetWindowPropertyX11(_glfw.x11.root,
|
||||||
|
_glfw.x11.NET_WORKAREA,
|
||||||
|
XA_CARDINAL,
|
||||||
|
(unsigned char**) &extents);
|
||||||
|
|
||||||
|
if (_glfwGetWindowPropertyX11(_glfw.x11.root,
|
||||||
|
_glfw.x11.NET_CURRENT_DESKTOP,
|
||||||
|
XA_CARDINAL,
|
||||||
|
(unsigned char**) &desktop) > 0)
|
||||||
|
{
|
||||||
|
if (extentCount >= 4 && *desktop < extentCount / 4)
|
||||||
|
{
|
||||||
|
const int globalX = extents[*desktop * 4 + 0];
|
||||||
|
const int globalY = extents[*desktop * 4 + 1];
|
||||||
|
const int globalWidth = extents[*desktop * 4 + 2];
|
||||||
|
const int globalHeight = extents[*desktop * 4 + 3];
|
||||||
|
|
||||||
|
if (areaX < globalX)
|
||||||
|
{
|
||||||
|
areaWidth -= globalX - areaX;
|
||||||
|
areaX = globalX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (areaY < globalY)
|
||||||
|
{
|
||||||
|
areaHeight -= globalY - areaY;
|
||||||
|
areaY = globalY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (areaX + areaWidth > globalX + globalWidth)
|
||||||
|
areaWidth = globalX - areaX + globalWidth;
|
||||||
|
if (areaY + areaHeight > globalY + globalHeight)
|
||||||
|
areaHeight = globalY - areaY + globalHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extents)
|
||||||
|
XFree(extents);
|
||||||
|
if (desktop)
|
||||||
|
XFree(desktop);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xpos)
|
||||||
|
*xpos = areaX;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = areaY;
|
||||||
|
if (width)
|
||||||
|
*width = areaWidth;
|
||||||
|
if (height)
|
||||||
|
*height = areaHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||||
|
{
|
||||||
|
GLFWvidmode* result;
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
|
{
|
||||||
|
XRRScreenResources* sr =
|
||||||
|
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
|
XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
|
||||||
|
|
||||||
|
result = calloc(oi->nmode, sizeof(GLFWvidmode));
|
||||||
|
|
||||||
|
for (int i = 0; i < oi->nmode; i++)
|
||||||
|
{
|
||||||
|
const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
|
||||||
|
if (!modeIsGood(mi))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for (j = 0; j < *count; j++)
|
||||||
|
{
|
||||||
|
if (_glfwCompareVideoModes(result + j, &mode) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip duplicate modes
|
||||||
|
if (j < *count)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
(*count)++;
|
||||||
|
result[*count - 1] = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
XRRFreeOutputInfo(oi);
|
||||||
|
XRRFreeCrtcInfo(ci);
|
||||||
|
XRRFreeScreenResources(sr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*count = 1;
|
||||||
|
result = calloc(1, sizeof(GLFWvidmode));
|
||||||
|
_glfwPlatformGetVideoMode(monitor, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||||
|
{
|
||||||
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
|
{
|
||||||
|
XRRScreenResources* sr =
|
||||||
|
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
|
|
||||||
|
if (ci)
|
||||||
|
{
|
||||||
|
const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
|
||||||
|
if (mi) // mi can be NULL if the monitor has been disconnected
|
||||||
|
*mode = vidmodeFromModeInfo(mi, ci);
|
||||||
|
|
||||||
|
XRRFreeCrtcInfo(ci);
|
||||||
|
}
|
||||||
|
|
||||||
|
XRRFreeScreenResources(sr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mode->width = DisplayWidth(_glfw.x11.display, _glfw.x11.screen);
|
||||||
|
mode->height = DisplayHeight(_glfw.x11.display, _glfw.x11.screen);
|
||||||
|
mode->refreshRate = 0;
|
||||||
|
|
||||||
|
_glfwSplitBPP(DefaultDepth(_glfw.x11.display, _glfw.x11.screen),
|
||||||
|
&mode->redBits, &mode->greenBits, &mode->blueBits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||||
|
{
|
||||||
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
|
||||||
|
{
|
||||||
|
const size_t size = XRRGetCrtcGammaSize(_glfw.x11.display,
|
||||||
|
monitor->x11.crtc);
|
||||||
|
XRRCrtcGamma* gamma = XRRGetCrtcGamma(_glfw.x11.display,
|
||||||
|
monitor->x11.crtc);
|
||||||
|
|
||||||
|
_glfwAllocGammaArrays(ramp, size);
|
||||||
|
|
||||||
|
memcpy(ramp->red, gamma->red, size * sizeof(unsigned short));
|
||||||
|
memcpy(ramp->green, gamma->green, size * sizeof(unsigned short));
|
||||||
|
memcpy(ramp->blue, gamma->blue, size * sizeof(unsigned short));
|
||||||
|
|
||||||
|
XRRFreeGamma(gamma);
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
else if (_glfw.x11.vidmode.available)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
XF86VidModeGetGammaRampSize(_glfw.x11.display, _glfw.x11.screen, &size);
|
||||||
|
|
||||||
|
_glfwAllocGammaArrays(ramp, size);
|
||||||
|
|
||||||
|
XF86VidModeGetGammaRamp(_glfw.x11.display,
|
||||||
|
_glfw.x11.screen,
|
||||||
|
ramp->size, ramp->red, ramp->green, ramp->blue);
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"X11: Gamma ramp access not supported by server");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||||
|
{
|
||||||
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
|
||||||
|
{
|
||||||
|
if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) != ramp->size)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"X11: Gamma ramp size must match current ramp size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
XRRCrtcGamma* gamma = XRRAllocGamma(ramp->size);
|
||||||
|
|
||||||
|
memcpy(gamma->red, ramp->red, ramp->size * sizeof(unsigned short));
|
||||||
|
memcpy(gamma->green, ramp->green, ramp->size * sizeof(unsigned short));
|
||||||
|
memcpy(gamma->blue, ramp->blue, ramp->size * sizeof(unsigned short));
|
||||||
|
|
||||||
|
XRRSetCrtcGamma(_glfw.x11.display, monitor->x11.crtc, gamma);
|
||||||
|
XRRFreeGamma(gamma);
|
||||||
|
}
|
||||||
|
else if (_glfw.x11.vidmode.available)
|
||||||
|
{
|
||||||
|
XF86VidModeSetGammaRamp(_glfw.x11.display,
|
||||||
|
_glfw.x11.screen,
|
||||||
|
ramp->size,
|
||||||
|
(unsigned short*) ramp->red,
|
||||||
|
(unsigned short*) ramp->green,
|
||||||
|
(unsigned short*) ramp->blue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"X11: Gamma ramp access not supported by server");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW native API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* handle)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(None);
|
||||||
|
return monitor->x11.crtc;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* handle)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(None);
|
||||||
|
return monitor->x11.output;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,451 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 X11 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/keysym.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
#include <X11/Xcursor/Xcursor.h>
|
||||||
|
|
||||||
|
// The XRandR extension provides mode setting and gamma control
|
||||||
|
#include <X11/extensions/Xrandr.h>
|
||||||
|
|
||||||
|
// The Xkb extension provides improved keyboard support
|
||||||
|
#include <X11/XKBlib.h>
|
||||||
|
|
||||||
|
// The Xinerama extension provides legacy monitor indices
|
||||||
|
#include <X11/extensions/Xinerama.h>
|
||||||
|
|
||||||
|
// The XInput extension provides raw mouse motion input
|
||||||
|
#include <X11/extensions/XInput2.h>
|
||||||
|
|
||||||
|
typedef XRRCrtcGamma* (* PFN_XRRAllocGamma)(int);
|
||||||
|
typedef void (* PFN_XRRFreeCrtcInfo)(XRRCrtcInfo*);
|
||||||
|
typedef void (* PFN_XRRFreeGamma)(XRRCrtcGamma*);
|
||||||
|
typedef void (* PFN_XRRFreeOutputInfo)(XRROutputInfo*);
|
||||||
|
typedef void (* PFN_XRRFreeScreenResources)(XRRScreenResources*);
|
||||||
|
typedef XRRCrtcGamma* (* PFN_XRRGetCrtcGamma)(Display*,RRCrtc);
|
||||||
|
typedef int (* PFN_XRRGetCrtcGammaSize)(Display*,RRCrtc);
|
||||||
|
typedef XRRCrtcInfo* (* PFN_XRRGetCrtcInfo) (Display*,XRRScreenResources*,RRCrtc);
|
||||||
|
typedef XRROutputInfo* (* PFN_XRRGetOutputInfo)(Display*,XRRScreenResources*,RROutput);
|
||||||
|
typedef RROutput (* PFN_XRRGetOutputPrimary)(Display*,Window);
|
||||||
|
typedef XRRScreenResources* (* PFN_XRRGetScreenResourcesCurrent)(Display*,Window);
|
||||||
|
typedef Bool (* PFN_XRRQueryExtension)(Display*,int*,int*);
|
||||||
|
typedef Status (* PFN_XRRQueryVersion)(Display*,int*,int*);
|
||||||
|
typedef void (* PFN_XRRSelectInput)(Display*,Window,int);
|
||||||
|
typedef Status (* PFN_XRRSetCrtcConfig)(Display*,XRRScreenResources*,RRCrtc,Time,int,int,RRMode,Rotation,RROutput*,int);
|
||||||
|
typedef void (* PFN_XRRSetCrtcGamma)(Display*,RRCrtc,XRRCrtcGamma*);
|
||||||
|
typedef int (* PFN_XRRUpdateConfiguration)(XEvent*);
|
||||||
|
#define XRRAllocGamma _glfw.x11.randr.AllocGamma
|
||||||
|
#define XRRFreeCrtcInfo _glfw.x11.randr.FreeCrtcInfo
|
||||||
|
#define XRRFreeGamma _glfw.x11.randr.FreeGamma
|
||||||
|
#define XRRFreeOutputInfo _glfw.x11.randr.FreeOutputInfo
|
||||||
|
#define XRRFreeScreenResources _glfw.x11.randr.FreeScreenResources
|
||||||
|
#define XRRGetCrtcGamma _glfw.x11.randr.GetCrtcGamma
|
||||||
|
#define XRRGetCrtcGammaSize _glfw.x11.randr.GetCrtcGammaSize
|
||||||
|
#define XRRGetCrtcInfo _glfw.x11.randr.GetCrtcInfo
|
||||||
|
#define XRRGetOutputInfo _glfw.x11.randr.GetOutputInfo
|
||||||
|
#define XRRGetOutputPrimary _glfw.x11.randr.GetOutputPrimary
|
||||||
|
#define XRRGetScreenResourcesCurrent _glfw.x11.randr.GetScreenResourcesCurrent
|
||||||
|
#define XRRQueryExtension _glfw.x11.randr.QueryExtension
|
||||||
|
#define XRRQueryVersion _glfw.x11.randr.QueryVersion
|
||||||
|
#define XRRSelectInput _glfw.x11.randr.SelectInput
|
||||||
|
#define XRRSetCrtcConfig _glfw.x11.randr.SetCrtcConfig
|
||||||
|
#define XRRSetCrtcGamma _glfw.x11.randr.SetCrtcGamma
|
||||||
|
#define XRRUpdateConfiguration _glfw.x11.randr.UpdateConfiguration
|
||||||
|
|
||||||
|
typedef XcursorImage* (* PFN_XcursorImageCreate)(int,int);
|
||||||
|
typedef void (* PFN_XcursorImageDestroy)(XcursorImage*);
|
||||||
|
typedef Cursor (* PFN_XcursorImageLoadCursor)(Display*,const XcursorImage*);
|
||||||
|
#define XcursorImageCreate _glfw.x11.xcursor.ImageCreate
|
||||||
|
#define XcursorImageDestroy _glfw.x11.xcursor.ImageDestroy
|
||||||
|
#define XcursorImageLoadCursor _glfw.x11.xcursor.ImageLoadCursor
|
||||||
|
|
||||||
|
typedef Bool (* PFN_XineramaIsActive)(Display*);
|
||||||
|
typedef Bool (* PFN_XineramaQueryExtension)(Display*,int*,int*);
|
||||||
|
typedef XineramaScreenInfo* (* PFN_XineramaQueryScreens)(Display*,int*);
|
||||||
|
#define XineramaIsActive _glfw.x11.xinerama.IsActive
|
||||||
|
#define XineramaQueryExtension _glfw.x11.xinerama.QueryExtension
|
||||||
|
#define XineramaQueryScreens _glfw.x11.xinerama.QueryScreens
|
||||||
|
|
||||||
|
typedef XID xcb_window_t;
|
||||||
|
typedef XID xcb_visualid_t;
|
||||||
|
typedef struct xcb_connection_t xcb_connection_t;
|
||||||
|
typedef xcb_connection_t* (* PFN_XGetXCBConnection)(Display*);
|
||||||
|
#define XGetXCBConnection _glfw.x11.x11xcb.GetXCBConnection
|
||||||
|
|
||||||
|
typedef Bool (* PFN_XF86VidModeQueryExtension)(Display*,int*,int*);
|
||||||
|
typedef Bool (* PFN_XF86VidModeGetGammaRamp)(Display*,int,int,unsigned short*,unsigned short*,unsigned short*);
|
||||||
|
typedef Bool (* PFN_XF86VidModeSetGammaRamp)(Display*,int,int,unsigned short*,unsigned short*,unsigned short*);
|
||||||
|
typedef Bool (* PFN_XF86VidModeGetGammaRampSize)(Display*,int,int*);
|
||||||
|
#define XF86VidModeQueryExtension _glfw.x11.vidmode.QueryExtension
|
||||||
|
#define XF86VidModeGetGammaRamp _glfw.x11.vidmode.GetGammaRamp
|
||||||
|
#define XF86VidModeSetGammaRamp _glfw.x11.vidmode.SetGammaRamp
|
||||||
|
#define XF86VidModeGetGammaRampSize _glfw.x11.vidmode.GetGammaRampSize
|
||||||
|
|
||||||
|
typedef Status (* PFN_XIQueryVersion)(Display*,int*,int*);
|
||||||
|
typedef int (* PFN_XISelectEvents)(Display*,Window,XIEventMask*,int);
|
||||||
|
#define XIQueryVersion _glfw.x11.xi.QueryVersion
|
||||||
|
#define XISelectEvents _glfw.x11.xi.SelectEvents
|
||||||
|
|
||||||
|
typedef Bool (* PFN_XRenderQueryExtension)(Display*,int*,int*);
|
||||||
|
typedef Status (* PFN_XRenderQueryVersion)(Display*dpy,int*,int*);
|
||||||
|
typedef XRenderPictFormat* (* PFN_XRenderFindVisualFormat)(Display*,Visual const*);
|
||||||
|
#define XRenderQueryExtension _glfw.x11.xrender.QueryExtension
|
||||||
|
#define XRenderQueryVersion _glfw.x11.xrender.QueryVersion
|
||||||
|
#define XRenderFindVisualFormat _glfw.x11.xrender.FindVisualFormat
|
||||||
|
|
||||||
|
typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
|
||||||
|
typedef VkFlags VkXcbSurfaceCreateFlagsKHR;
|
||||||
|
|
||||||
|
typedef struct VkXlibSurfaceCreateInfoKHR
|
||||||
|
{
|
||||||
|
VkStructureType sType;
|
||||||
|
const void* pNext;
|
||||||
|
VkXlibSurfaceCreateFlagsKHR flags;
|
||||||
|
Display* dpy;
|
||||||
|
Window window;
|
||||||
|
} VkXlibSurfaceCreateInfoKHR;
|
||||||
|
|
||||||
|
typedef struct VkXcbSurfaceCreateInfoKHR
|
||||||
|
{
|
||||||
|
VkStructureType sType;
|
||||||
|
const void* pNext;
|
||||||
|
VkXcbSurfaceCreateFlagsKHR flags;
|
||||||
|
xcb_connection_t* connection;
|
||||||
|
xcb_window_t window;
|
||||||
|
} VkXcbSurfaceCreateInfoKHR;
|
||||||
|
|
||||||
|
typedef VkResult (APIENTRY *PFN_vkCreateXlibSurfaceKHR)(VkInstance,const VkXlibSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||||
|
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice,uint32_t,Display*,VisualID);
|
||||||
|
typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||||
|
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t);
|
||||||
|
|
||||||
|
#include "posix_thread.h"
|
||||||
|
#include "posix_time.h"
|
||||||
|
#include "xkb_unicode.h"
|
||||||
|
#include "glx_context.h"
|
||||||
|
#include "egl_context.h"
|
||||||
|
#include "osmesa_context.h"
|
||||||
|
#if defined(__linux__)
|
||||||
|
#include "linux_joystick.h"
|
||||||
|
#else
|
||||||
|
#include "null_joystick.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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_WINDOW ((EGLNativeWindowType) window->x11.handle)
|
||||||
|
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.x11.display)
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11
|
||||||
|
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11
|
||||||
|
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorX11 x11
|
||||||
|
|
||||||
|
|
||||||
|
// X11-specific per-window data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWwindowX11
|
||||||
|
{
|
||||||
|
Colormap colormap;
|
||||||
|
Window handle;
|
||||||
|
Window parent;
|
||||||
|
XIC ic;
|
||||||
|
|
||||||
|
GLFWbool overrideRedirect;
|
||||||
|
GLFWbool iconified;
|
||||||
|
GLFWbool maximized;
|
||||||
|
|
||||||
|
// Whether the visual supports framebuffer transparency
|
||||||
|
GLFWbool transparent;
|
||||||
|
|
||||||
|
// Cached position and size used to filter out duplicate events
|
||||||
|
int width, height;
|
||||||
|
int xpos, ypos;
|
||||||
|
|
||||||
|
// The last received cursor position, regardless of source
|
||||||
|
int lastCursorPosX, lastCursorPosY;
|
||||||
|
// The last position the cursor was warped to by GLFW
|
||||||
|
int warpCursorPosX, warpCursorPosY;
|
||||||
|
|
||||||
|
// The time of the last KeyPress event per keycode, for discarding
|
||||||
|
// duplicate key events generated for some keys by ibus
|
||||||
|
Time keyPressTimes[256];
|
||||||
|
|
||||||
|
} _GLFWwindowX11;
|
||||||
|
|
||||||
|
// X11-specific global data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWlibraryX11
|
||||||
|
{
|
||||||
|
Display* display;
|
||||||
|
int screen;
|
||||||
|
Window root;
|
||||||
|
|
||||||
|
// System content scale
|
||||||
|
float contentScaleX, contentScaleY;
|
||||||
|
// Helper window for IPC
|
||||||
|
Window helperWindowHandle;
|
||||||
|
// Invisible cursor for hidden cursor mode
|
||||||
|
Cursor hiddenCursorHandle;
|
||||||
|
// Context for mapping window XIDs to _GLFWwindow pointers
|
||||||
|
XContext context;
|
||||||
|
// XIM input method
|
||||||
|
XIM im;
|
||||||
|
// Most recent error code received by X error handler
|
||||||
|
int errorCode;
|
||||||
|
// Primary selection string (while the primary selection is owned)
|
||||||
|
char* primarySelectionString;
|
||||||
|
// Clipboard string (while the selection is owned)
|
||||||
|
char* clipboardString;
|
||||||
|
// Key name string
|
||||||
|
char keynames[GLFW_KEY_LAST + 1][5];
|
||||||
|
// X11 keycode to GLFW key LUT
|
||||||
|
short int keycodes[256];
|
||||||
|
// GLFW key to X11 keycode LUT
|
||||||
|
short int scancodes[GLFW_KEY_LAST + 1];
|
||||||
|
// Where to place the cursor when re-enabled
|
||||||
|
double restoreCursorPosX, restoreCursorPosY;
|
||||||
|
// The window whose disabled cursor mode is active
|
||||||
|
_GLFWwindow* disabledCursorWindow;
|
||||||
|
|
||||||
|
// Window manager atoms
|
||||||
|
Atom NET_SUPPORTED;
|
||||||
|
Atom NET_SUPPORTING_WM_CHECK;
|
||||||
|
Atom WM_PROTOCOLS;
|
||||||
|
Atom WM_STATE;
|
||||||
|
Atom WM_DELETE_WINDOW;
|
||||||
|
Atom NET_WM_NAME;
|
||||||
|
Atom NET_WM_ICON_NAME;
|
||||||
|
Atom NET_WM_ICON;
|
||||||
|
Atom NET_WM_PID;
|
||||||
|
Atom NET_WM_PING;
|
||||||
|
Atom NET_WM_WINDOW_TYPE;
|
||||||
|
Atom NET_WM_WINDOW_TYPE_NORMAL;
|
||||||
|
Atom NET_WM_STATE;
|
||||||
|
Atom NET_WM_STATE_ABOVE;
|
||||||
|
Atom NET_WM_STATE_FULLSCREEN;
|
||||||
|
Atom NET_WM_STATE_MAXIMIZED_VERT;
|
||||||
|
Atom NET_WM_STATE_MAXIMIZED_HORZ;
|
||||||
|
Atom NET_WM_STATE_DEMANDS_ATTENTION;
|
||||||
|
Atom NET_WM_BYPASS_COMPOSITOR;
|
||||||
|
Atom NET_WM_FULLSCREEN_MONITORS;
|
||||||
|
Atom NET_WM_WINDOW_OPACITY;
|
||||||
|
Atom NET_WM_CM_Sx;
|
||||||
|
Atom NET_WORKAREA;
|
||||||
|
Atom NET_CURRENT_DESKTOP;
|
||||||
|
Atom NET_ACTIVE_WINDOW;
|
||||||
|
Atom NET_FRAME_EXTENTS;
|
||||||
|
Atom NET_REQUEST_FRAME_EXTENTS;
|
||||||
|
Atom MOTIF_WM_HINTS;
|
||||||
|
|
||||||
|
// Xdnd (drag and drop) atoms
|
||||||
|
Atom XdndAware;
|
||||||
|
Atom XdndEnter;
|
||||||
|
Atom XdndPosition;
|
||||||
|
Atom XdndStatus;
|
||||||
|
Atom XdndActionCopy;
|
||||||
|
Atom XdndDrop;
|
||||||
|
Atom XdndFinished;
|
||||||
|
Atom XdndSelection;
|
||||||
|
Atom XdndTypeList;
|
||||||
|
Atom text_uri_list;
|
||||||
|
|
||||||
|
// Selection (clipboard) atoms
|
||||||
|
Atom TARGETS;
|
||||||
|
Atom MULTIPLE;
|
||||||
|
Atom INCR;
|
||||||
|
Atom CLIPBOARD;
|
||||||
|
Atom PRIMARY;
|
||||||
|
Atom CLIPBOARD_MANAGER;
|
||||||
|
Atom SAVE_TARGETS;
|
||||||
|
Atom NULL_;
|
||||||
|
Atom UTF8_STRING;
|
||||||
|
Atom COMPOUND_STRING;
|
||||||
|
Atom ATOM_PAIR;
|
||||||
|
Atom GLFW_SELECTION;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
GLFWbool available;
|
||||||
|
void* handle;
|
||||||
|
int eventBase;
|
||||||
|
int errorBase;
|
||||||
|
int major;
|
||||||
|
int minor;
|
||||||
|
GLFWbool gammaBroken;
|
||||||
|
GLFWbool monitorBroken;
|
||||||
|
PFN_XRRAllocGamma AllocGamma;
|
||||||
|
PFN_XRRFreeCrtcInfo FreeCrtcInfo;
|
||||||
|
PFN_XRRFreeGamma FreeGamma;
|
||||||
|
PFN_XRRFreeOutputInfo FreeOutputInfo;
|
||||||
|
PFN_XRRFreeScreenResources FreeScreenResources;
|
||||||
|
PFN_XRRGetCrtcGamma GetCrtcGamma;
|
||||||
|
PFN_XRRGetCrtcGammaSize GetCrtcGammaSize;
|
||||||
|
PFN_XRRGetCrtcInfo GetCrtcInfo;
|
||||||
|
PFN_XRRGetOutputInfo GetOutputInfo;
|
||||||
|
PFN_XRRGetOutputPrimary GetOutputPrimary;
|
||||||
|
PFN_XRRGetScreenResourcesCurrent GetScreenResourcesCurrent;
|
||||||
|
PFN_XRRQueryExtension QueryExtension;
|
||||||
|
PFN_XRRQueryVersion QueryVersion;
|
||||||
|
PFN_XRRSelectInput SelectInput;
|
||||||
|
PFN_XRRSetCrtcConfig SetCrtcConfig;
|
||||||
|
PFN_XRRSetCrtcGamma SetCrtcGamma;
|
||||||
|
PFN_XRRUpdateConfiguration UpdateConfiguration;
|
||||||
|
} randr;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
GLFWbool available;
|
||||||
|
GLFWbool detectable;
|
||||||
|
int majorOpcode;
|
||||||
|
int eventBase;
|
||||||
|
int errorBase;
|
||||||
|
int major;
|
||||||
|
int minor;
|
||||||
|
unsigned int group;
|
||||||
|
} xkb;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int count;
|
||||||
|
int timeout;
|
||||||
|
int interval;
|
||||||
|
int blanking;
|
||||||
|
int exposure;
|
||||||
|
} saver;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int version;
|
||||||
|
Window source;
|
||||||
|
Atom format;
|
||||||
|
} xdnd;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
void* handle;
|
||||||
|
PFN_XcursorImageCreate ImageCreate;
|
||||||
|
PFN_XcursorImageDestroy ImageDestroy;
|
||||||
|
PFN_XcursorImageLoadCursor ImageLoadCursor;
|
||||||
|
} xcursor;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
GLFWbool available;
|
||||||
|
void* handle;
|
||||||
|
int major;
|
||||||
|
int minor;
|
||||||
|
PFN_XineramaIsActive IsActive;
|
||||||
|
PFN_XineramaQueryExtension QueryExtension;
|
||||||
|
PFN_XineramaQueryScreens QueryScreens;
|
||||||
|
} xinerama;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
void* handle;
|
||||||
|
PFN_XGetXCBConnection GetXCBConnection;
|
||||||
|
} x11xcb;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
GLFWbool available;
|
||||||
|
void* handle;
|
||||||
|
int eventBase;
|
||||||
|
int errorBase;
|
||||||
|
PFN_XF86VidModeQueryExtension QueryExtension;
|
||||||
|
PFN_XF86VidModeGetGammaRamp GetGammaRamp;
|
||||||
|
PFN_XF86VidModeSetGammaRamp SetGammaRamp;
|
||||||
|
PFN_XF86VidModeGetGammaRampSize GetGammaRampSize;
|
||||||
|
} vidmode;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
GLFWbool available;
|
||||||
|
void* handle;
|
||||||
|
int majorOpcode;
|
||||||
|
int eventBase;
|
||||||
|
int errorBase;
|
||||||
|
int major;
|
||||||
|
int minor;
|
||||||
|
PFN_XIQueryVersion QueryVersion;
|
||||||
|
PFN_XISelectEvents SelectEvents;
|
||||||
|
} xi;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
GLFWbool available;
|
||||||
|
void* handle;
|
||||||
|
int major;
|
||||||
|
int minor;
|
||||||
|
int eventBase;
|
||||||
|
int errorBase;
|
||||||
|
PFN_XRenderQueryExtension QueryExtension;
|
||||||
|
PFN_XRenderQueryVersion QueryVersion;
|
||||||
|
PFN_XRenderFindVisualFormat FindVisualFormat;
|
||||||
|
} xrender;
|
||||||
|
|
||||||
|
} _GLFWlibraryX11;
|
||||||
|
|
||||||
|
// X11-specific per-monitor data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWmonitorX11
|
||||||
|
{
|
||||||
|
RROutput output;
|
||||||
|
RRCrtc crtc;
|
||||||
|
RRMode oldMode;
|
||||||
|
|
||||||
|
// Index of corresponding Xinerama screen,
|
||||||
|
// for EWMH full screen window placement
|
||||||
|
int index;
|
||||||
|
|
||||||
|
} _GLFWmonitorX11;
|
||||||
|
|
||||||
|
// X11-specific per-cursor data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWcursorX11
|
||||||
|
{
|
||||||
|
Cursor handle;
|
||||||
|
|
||||||
|
} _GLFWcursorX11;
|
||||||
|
|
||||||
|
|
||||||
|
void _glfwPollMonitorsX11(void);
|
||||||
|
void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||||
|
void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor);
|
||||||
|
|
||||||
|
Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot);
|
||||||
|
|
||||||
|
unsigned long _glfwGetWindowPropertyX11(Window window,
|
||||||
|
Atom property,
|
||||||
|
Atom type,
|
||||||
|
unsigned char** value);
|
||||||
|
GLFWbool _glfwIsVisualTransparentX11(Visual* visual);
|
||||||
|
|
||||||
|
void _glfwGrabErrorHandlerX11(void);
|
||||||
|
void _glfwReleaseErrorHandlerX11(void);
|
||||||
|
void _glfwInputErrorX11(int error, const char* message);
|
||||||
|
|
||||||
|
void _glfwPushSelectionToManagerX11(void);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,942 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 X11 - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Marcus: This code was originally written by Markus G. Kuhn.
|
||||||
|
* I have made some slight changes (trimmed it down a bit from >60 KB to
|
||||||
|
* 20 KB), but the functionality is the same.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This module converts keysym values into the corresponding ISO 10646
|
||||||
|
* (UCS, Unicode) values.
|
||||||
|
*
|
||||||
|
* The array keysymtab[] contains pairs of X11 keysym values for graphical
|
||||||
|
* characters and the corresponding Unicode value. The function
|
||||||
|
* _glfwKeySym2Unicode() maps a keysym onto a Unicode value using a binary
|
||||||
|
* search, therefore keysymtab[] must remain SORTED by keysym value.
|
||||||
|
*
|
||||||
|
* We allow to represent any UCS character in the range U-00000000 to
|
||||||
|
* U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
|
||||||
|
* This admittedly does not cover the entire 31-bit space of UCS, but
|
||||||
|
* it does cover all of the characters up to U-10FFFF, which can be
|
||||||
|
* represented by UTF-16, and more, and it is very unlikely that higher
|
||||||
|
* UCS codes will ever be assigned by ISO. So to get Unicode character
|
||||||
|
* U+ABCD you can directly use keysym 0x0100abcd.
|
||||||
|
*
|
||||||
|
* Original author: Markus G. Kuhn <mkuhn@acm.org>, University of
|
||||||
|
* Cambridge, April 2001
|
||||||
|
*
|
||||||
|
* Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing
|
||||||
|
* an initial draft of the mapping table.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//************************************************************************
|
||||||
|
//**** KeySym to Unicode mapping table ****
|
||||||
|
//************************************************************************
|
||||||
|
|
||||||
|
static const struct codepair {
|
||||||
|
unsigned short keysym;
|
||||||
|
unsigned short ucs;
|
||||||
|
} keysymtab[] = {
|
||||||
|
{ 0x01a1, 0x0104 },
|
||||||
|
{ 0x01a2, 0x02d8 },
|
||||||
|
{ 0x01a3, 0x0141 },
|
||||||
|
{ 0x01a5, 0x013d },
|
||||||
|
{ 0x01a6, 0x015a },
|
||||||
|
{ 0x01a9, 0x0160 },
|
||||||
|
{ 0x01aa, 0x015e },
|
||||||
|
{ 0x01ab, 0x0164 },
|
||||||
|
{ 0x01ac, 0x0179 },
|
||||||
|
{ 0x01ae, 0x017d },
|
||||||
|
{ 0x01af, 0x017b },
|
||||||
|
{ 0x01b1, 0x0105 },
|
||||||
|
{ 0x01b2, 0x02db },
|
||||||
|
{ 0x01b3, 0x0142 },
|
||||||
|
{ 0x01b5, 0x013e },
|
||||||
|
{ 0x01b6, 0x015b },
|
||||||
|
{ 0x01b7, 0x02c7 },
|
||||||
|
{ 0x01b9, 0x0161 },
|
||||||
|
{ 0x01ba, 0x015f },
|
||||||
|
{ 0x01bb, 0x0165 },
|
||||||
|
{ 0x01bc, 0x017a },
|
||||||
|
{ 0x01bd, 0x02dd },
|
||||||
|
{ 0x01be, 0x017e },
|
||||||
|
{ 0x01bf, 0x017c },
|
||||||
|
{ 0x01c0, 0x0154 },
|
||||||
|
{ 0x01c3, 0x0102 },
|
||||||
|
{ 0x01c5, 0x0139 },
|
||||||
|
{ 0x01c6, 0x0106 },
|
||||||
|
{ 0x01c8, 0x010c },
|
||||||
|
{ 0x01ca, 0x0118 },
|
||||||
|
{ 0x01cc, 0x011a },
|
||||||
|
{ 0x01cf, 0x010e },
|
||||||
|
{ 0x01d0, 0x0110 },
|
||||||
|
{ 0x01d1, 0x0143 },
|
||||||
|
{ 0x01d2, 0x0147 },
|
||||||
|
{ 0x01d5, 0x0150 },
|
||||||
|
{ 0x01d8, 0x0158 },
|
||||||
|
{ 0x01d9, 0x016e },
|
||||||
|
{ 0x01db, 0x0170 },
|
||||||
|
{ 0x01de, 0x0162 },
|
||||||
|
{ 0x01e0, 0x0155 },
|
||||||
|
{ 0x01e3, 0x0103 },
|
||||||
|
{ 0x01e5, 0x013a },
|
||||||
|
{ 0x01e6, 0x0107 },
|
||||||
|
{ 0x01e8, 0x010d },
|
||||||
|
{ 0x01ea, 0x0119 },
|
||||||
|
{ 0x01ec, 0x011b },
|
||||||
|
{ 0x01ef, 0x010f },
|
||||||
|
{ 0x01f0, 0x0111 },
|
||||||
|
{ 0x01f1, 0x0144 },
|
||||||
|
{ 0x01f2, 0x0148 },
|
||||||
|
{ 0x01f5, 0x0151 },
|
||||||
|
{ 0x01f8, 0x0159 },
|
||||||
|
{ 0x01f9, 0x016f },
|
||||||
|
{ 0x01fb, 0x0171 },
|
||||||
|
{ 0x01fe, 0x0163 },
|
||||||
|
{ 0x01ff, 0x02d9 },
|
||||||
|
{ 0x02a1, 0x0126 },
|
||||||
|
{ 0x02a6, 0x0124 },
|
||||||
|
{ 0x02a9, 0x0130 },
|
||||||
|
{ 0x02ab, 0x011e },
|
||||||
|
{ 0x02ac, 0x0134 },
|
||||||
|
{ 0x02b1, 0x0127 },
|
||||||
|
{ 0x02b6, 0x0125 },
|
||||||
|
{ 0x02b9, 0x0131 },
|
||||||
|
{ 0x02bb, 0x011f },
|
||||||
|
{ 0x02bc, 0x0135 },
|
||||||
|
{ 0x02c5, 0x010a },
|
||||||
|
{ 0x02c6, 0x0108 },
|
||||||
|
{ 0x02d5, 0x0120 },
|
||||||
|
{ 0x02d8, 0x011c },
|
||||||
|
{ 0x02dd, 0x016c },
|
||||||
|
{ 0x02de, 0x015c },
|
||||||
|
{ 0x02e5, 0x010b },
|
||||||
|
{ 0x02e6, 0x0109 },
|
||||||
|
{ 0x02f5, 0x0121 },
|
||||||
|
{ 0x02f8, 0x011d },
|
||||||
|
{ 0x02fd, 0x016d },
|
||||||
|
{ 0x02fe, 0x015d },
|
||||||
|
{ 0x03a2, 0x0138 },
|
||||||
|
{ 0x03a3, 0x0156 },
|
||||||
|
{ 0x03a5, 0x0128 },
|
||||||
|
{ 0x03a6, 0x013b },
|
||||||
|
{ 0x03aa, 0x0112 },
|
||||||
|
{ 0x03ab, 0x0122 },
|
||||||
|
{ 0x03ac, 0x0166 },
|
||||||
|
{ 0x03b3, 0x0157 },
|
||||||
|
{ 0x03b5, 0x0129 },
|
||||||
|
{ 0x03b6, 0x013c },
|
||||||
|
{ 0x03ba, 0x0113 },
|
||||||
|
{ 0x03bb, 0x0123 },
|
||||||
|
{ 0x03bc, 0x0167 },
|
||||||
|
{ 0x03bd, 0x014a },
|
||||||
|
{ 0x03bf, 0x014b },
|
||||||
|
{ 0x03c0, 0x0100 },
|
||||||
|
{ 0x03c7, 0x012e },
|
||||||
|
{ 0x03cc, 0x0116 },
|
||||||
|
{ 0x03cf, 0x012a },
|
||||||
|
{ 0x03d1, 0x0145 },
|
||||||
|
{ 0x03d2, 0x014c },
|
||||||
|
{ 0x03d3, 0x0136 },
|
||||||
|
{ 0x03d9, 0x0172 },
|
||||||
|
{ 0x03dd, 0x0168 },
|
||||||
|
{ 0x03de, 0x016a },
|
||||||
|
{ 0x03e0, 0x0101 },
|
||||||
|
{ 0x03e7, 0x012f },
|
||||||
|
{ 0x03ec, 0x0117 },
|
||||||
|
{ 0x03ef, 0x012b },
|
||||||
|
{ 0x03f1, 0x0146 },
|
||||||
|
{ 0x03f2, 0x014d },
|
||||||
|
{ 0x03f3, 0x0137 },
|
||||||
|
{ 0x03f9, 0x0173 },
|
||||||
|
{ 0x03fd, 0x0169 },
|
||||||
|
{ 0x03fe, 0x016b },
|
||||||
|
{ 0x047e, 0x203e },
|
||||||
|
{ 0x04a1, 0x3002 },
|
||||||
|
{ 0x04a2, 0x300c },
|
||||||
|
{ 0x04a3, 0x300d },
|
||||||
|
{ 0x04a4, 0x3001 },
|
||||||
|
{ 0x04a5, 0x30fb },
|
||||||
|
{ 0x04a6, 0x30f2 },
|
||||||
|
{ 0x04a7, 0x30a1 },
|
||||||
|
{ 0x04a8, 0x30a3 },
|
||||||
|
{ 0x04a9, 0x30a5 },
|
||||||
|
{ 0x04aa, 0x30a7 },
|
||||||
|
{ 0x04ab, 0x30a9 },
|
||||||
|
{ 0x04ac, 0x30e3 },
|
||||||
|
{ 0x04ad, 0x30e5 },
|
||||||
|
{ 0x04ae, 0x30e7 },
|
||||||
|
{ 0x04af, 0x30c3 },
|
||||||
|
{ 0x04b0, 0x30fc },
|
||||||
|
{ 0x04b1, 0x30a2 },
|
||||||
|
{ 0x04b2, 0x30a4 },
|
||||||
|
{ 0x04b3, 0x30a6 },
|
||||||
|
{ 0x04b4, 0x30a8 },
|
||||||
|
{ 0x04b5, 0x30aa },
|
||||||
|
{ 0x04b6, 0x30ab },
|
||||||
|
{ 0x04b7, 0x30ad },
|
||||||
|
{ 0x04b8, 0x30af },
|
||||||
|
{ 0x04b9, 0x30b1 },
|
||||||
|
{ 0x04ba, 0x30b3 },
|
||||||
|
{ 0x04bb, 0x30b5 },
|
||||||
|
{ 0x04bc, 0x30b7 },
|
||||||
|
{ 0x04bd, 0x30b9 },
|
||||||
|
{ 0x04be, 0x30bb },
|
||||||
|
{ 0x04bf, 0x30bd },
|
||||||
|
{ 0x04c0, 0x30bf },
|
||||||
|
{ 0x04c1, 0x30c1 },
|
||||||
|
{ 0x04c2, 0x30c4 },
|
||||||
|
{ 0x04c3, 0x30c6 },
|
||||||
|
{ 0x04c4, 0x30c8 },
|
||||||
|
{ 0x04c5, 0x30ca },
|
||||||
|
{ 0x04c6, 0x30cb },
|
||||||
|
{ 0x04c7, 0x30cc },
|
||||||
|
{ 0x04c8, 0x30cd },
|
||||||
|
{ 0x04c9, 0x30ce },
|
||||||
|
{ 0x04ca, 0x30cf },
|
||||||
|
{ 0x04cb, 0x30d2 },
|
||||||
|
{ 0x04cc, 0x30d5 },
|
||||||
|
{ 0x04cd, 0x30d8 },
|
||||||
|
{ 0x04ce, 0x30db },
|
||||||
|
{ 0x04cf, 0x30de },
|
||||||
|
{ 0x04d0, 0x30df },
|
||||||
|
{ 0x04d1, 0x30e0 },
|
||||||
|
{ 0x04d2, 0x30e1 },
|
||||||
|
{ 0x04d3, 0x30e2 },
|
||||||
|
{ 0x04d4, 0x30e4 },
|
||||||
|
{ 0x04d5, 0x30e6 },
|
||||||
|
{ 0x04d6, 0x30e8 },
|
||||||
|
{ 0x04d7, 0x30e9 },
|
||||||
|
{ 0x04d8, 0x30ea },
|
||||||
|
{ 0x04d9, 0x30eb },
|
||||||
|
{ 0x04da, 0x30ec },
|
||||||
|
{ 0x04db, 0x30ed },
|
||||||
|
{ 0x04dc, 0x30ef },
|
||||||
|
{ 0x04dd, 0x30f3 },
|
||||||
|
{ 0x04de, 0x309b },
|
||||||
|
{ 0x04df, 0x309c },
|
||||||
|
{ 0x05ac, 0x060c },
|
||||||
|
{ 0x05bb, 0x061b },
|
||||||
|
{ 0x05bf, 0x061f },
|
||||||
|
{ 0x05c1, 0x0621 },
|
||||||
|
{ 0x05c2, 0x0622 },
|
||||||
|
{ 0x05c3, 0x0623 },
|
||||||
|
{ 0x05c4, 0x0624 },
|
||||||
|
{ 0x05c5, 0x0625 },
|
||||||
|
{ 0x05c6, 0x0626 },
|
||||||
|
{ 0x05c7, 0x0627 },
|
||||||
|
{ 0x05c8, 0x0628 },
|
||||||
|
{ 0x05c9, 0x0629 },
|
||||||
|
{ 0x05ca, 0x062a },
|
||||||
|
{ 0x05cb, 0x062b },
|
||||||
|
{ 0x05cc, 0x062c },
|
||||||
|
{ 0x05cd, 0x062d },
|
||||||
|
{ 0x05ce, 0x062e },
|
||||||
|
{ 0x05cf, 0x062f },
|
||||||
|
{ 0x05d0, 0x0630 },
|
||||||
|
{ 0x05d1, 0x0631 },
|
||||||
|
{ 0x05d2, 0x0632 },
|
||||||
|
{ 0x05d3, 0x0633 },
|
||||||
|
{ 0x05d4, 0x0634 },
|
||||||
|
{ 0x05d5, 0x0635 },
|
||||||
|
{ 0x05d6, 0x0636 },
|
||||||
|
{ 0x05d7, 0x0637 },
|
||||||
|
{ 0x05d8, 0x0638 },
|
||||||
|
{ 0x05d9, 0x0639 },
|
||||||
|
{ 0x05da, 0x063a },
|
||||||
|
{ 0x05e0, 0x0640 },
|
||||||
|
{ 0x05e1, 0x0641 },
|
||||||
|
{ 0x05e2, 0x0642 },
|
||||||
|
{ 0x05e3, 0x0643 },
|
||||||
|
{ 0x05e4, 0x0644 },
|
||||||
|
{ 0x05e5, 0x0645 },
|
||||||
|
{ 0x05e6, 0x0646 },
|
||||||
|
{ 0x05e7, 0x0647 },
|
||||||
|
{ 0x05e8, 0x0648 },
|
||||||
|
{ 0x05e9, 0x0649 },
|
||||||
|
{ 0x05ea, 0x064a },
|
||||||
|
{ 0x05eb, 0x064b },
|
||||||
|
{ 0x05ec, 0x064c },
|
||||||
|
{ 0x05ed, 0x064d },
|
||||||
|
{ 0x05ee, 0x064e },
|
||||||
|
{ 0x05ef, 0x064f },
|
||||||
|
{ 0x05f0, 0x0650 },
|
||||||
|
{ 0x05f1, 0x0651 },
|
||||||
|
{ 0x05f2, 0x0652 },
|
||||||
|
{ 0x06a1, 0x0452 },
|
||||||
|
{ 0x06a2, 0x0453 },
|
||||||
|
{ 0x06a3, 0x0451 },
|
||||||
|
{ 0x06a4, 0x0454 },
|
||||||
|
{ 0x06a5, 0x0455 },
|
||||||
|
{ 0x06a6, 0x0456 },
|
||||||
|
{ 0x06a7, 0x0457 },
|
||||||
|
{ 0x06a8, 0x0458 },
|
||||||
|
{ 0x06a9, 0x0459 },
|
||||||
|
{ 0x06aa, 0x045a },
|
||||||
|
{ 0x06ab, 0x045b },
|
||||||
|
{ 0x06ac, 0x045c },
|
||||||
|
{ 0x06ae, 0x045e },
|
||||||
|
{ 0x06af, 0x045f },
|
||||||
|
{ 0x06b0, 0x2116 },
|
||||||
|
{ 0x06b1, 0x0402 },
|
||||||
|
{ 0x06b2, 0x0403 },
|
||||||
|
{ 0x06b3, 0x0401 },
|
||||||
|
{ 0x06b4, 0x0404 },
|
||||||
|
{ 0x06b5, 0x0405 },
|
||||||
|
{ 0x06b6, 0x0406 },
|
||||||
|
{ 0x06b7, 0x0407 },
|
||||||
|
{ 0x06b8, 0x0408 },
|
||||||
|
{ 0x06b9, 0x0409 },
|
||||||
|
{ 0x06ba, 0x040a },
|
||||||
|
{ 0x06bb, 0x040b },
|
||||||
|
{ 0x06bc, 0x040c },
|
||||||
|
{ 0x06be, 0x040e },
|
||||||
|
{ 0x06bf, 0x040f },
|
||||||
|
{ 0x06c0, 0x044e },
|
||||||
|
{ 0x06c1, 0x0430 },
|
||||||
|
{ 0x06c2, 0x0431 },
|
||||||
|
{ 0x06c3, 0x0446 },
|
||||||
|
{ 0x06c4, 0x0434 },
|
||||||
|
{ 0x06c5, 0x0435 },
|
||||||
|
{ 0x06c6, 0x0444 },
|
||||||
|
{ 0x06c7, 0x0433 },
|
||||||
|
{ 0x06c8, 0x0445 },
|
||||||
|
{ 0x06c9, 0x0438 },
|
||||||
|
{ 0x06ca, 0x0439 },
|
||||||
|
{ 0x06cb, 0x043a },
|
||||||
|
{ 0x06cc, 0x043b },
|
||||||
|
{ 0x06cd, 0x043c },
|
||||||
|
{ 0x06ce, 0x043d },
|
||||||
|
{ 0x06cf, 0x043e },
|
||||||
|
{ 0x06d0, 0x043f },
|
||||||
|
{ 0x06d1, 0x044f },
|
||||||
|
{ 0x06d2, 0x0440 },
|
||||||
|
{ 0x06d3, 0x0441 },
|
||||||
|
{ 0x06d4, 0x0442 },
|
||||||
|
{ 0x06d5, 0x0443 },
|
||||||
|
{ 0x06d6, 0x0436 },
|
||||||
|
{ 0x06d7, 0x0432 },
|
||||||
|
{ 0x06d8, 0x044c },
|
||||||
|
{ 0x06d9, 0x044b },
|
||||||
|
{ 0x06da, 0x0437 },
|
||||||
|
{ 0x06db, 0x0448 },
|
||||||
|
{ 0x06dc, 0x044d },
|
||||||
|
{ 0x06dd, 0x0449 },
|
||||||
|
{ 0x06de, 0x0447 },
|
||||||
|
{ 0x06df, 0x044a },
|
||||||
|
{ 0x06e0, 0x042e },
|
||||||
|
{ 0x06e1, 0x0410 },
|
||||||
|
{ 0x06e2, 0x0411 },
|
||||||
|
{ 0x06e3, 0x0426 },
|
||||||
|
{ 0x06e4, 0x0414 },
|
||||||
|
{ 0x06e5, 0x0415 },
|
||||||
|
{ 0x06e6, 0x0424 },
|
||||||
|
{ 0x06e7, 0x0413 },
|
||||||
|
{ 0x06e8, 0x0425 },
|
||||||
|
{ 0x06e9, 0x0418 },
|
||||||
|
{ 0x06ea, 0x0419 },
|
||||||
|
{ 0x06eb, 0x041a },
|
||||||
|
{ 0x06ec, 0x041b },
|
||||||
|
{ 0x06ed, 0x041c },
|
||||||
|
{ 0x06ee, 0x041d },
|
||||||
|
{ 0x06ef, 0x041e },
|
||||||
|
{ 0x06f0, 0x041f },
|
||||||
|
{ 0x06f1, 0x042f },
|
||||||
|
{ 0x06f2, 0x0420 },
|
||||||
|
{ 0x06f3, 0x0421 },
|
||||||
|
{ 0x06f4, 0x0422 },
|
||||||
|
{ 0x06f5, 0x0423 },
|
||||||
|
{ 0x06f6, 0x0416 },
|
||||||
|
{ 0x06f7, 0x0412 },
|
||||||
|
{ 0x06f8, 0x042c },
|
||||||
|
{ 0x06f9, 0x042b },
|
||||||
|
{ 0x06fa, 0x0417 },
|
||||||
|
{ 0x06fb, 0x0428 },
|
||||||
|
{ 0x06fc, 0x042d },
|
||||||
|
{ 0x06fd, 0x0429 },
|
||||||
|
{ 0x06fe, 0x0427 },
|
||||||
|
{ 0x06ff, 0x042a },
|
||||||
|
{ 0x07a1, 0x0386 },
|
||||||
|
{ 0x07a2, 0x0388 },
|
||||||
|
{ 0x07a3, 0x0389 },
|
||||||
|
{ 0x07a4, 0x038a },
|
||||||
|
{ 0x07a5, 0x03aa },
|
||||||
|
{ 0x07a7, 0x038c },
|
||||||
|
{ 0x07a8, 0x038e },
|
||||||
|
{ 0x07a9, 0x03ab },
|
||||||
|
{ 0x07ab, 0x038f },
|
||||||
|
{ 0x07ae, 0x0385 },
|
||||||
|
{ 0x07af, 0x2015 },
|
||||||
|
{ 0x07b1, 0x03ac },
|
||||||
|
{ 0x07b2, 0x03ad },
|
||||||
|
{ 0x07b3, 0x03ae },
|
||||||
|
{ 0x07b4, 0x03af },
|
||||||
|
{ 0x07b5, 0x03ca },
|
||||||
|
{ 0x07b6, 0x0390 },
|
||||||
|
{ 0x07b7, 0x03cc },
|
||||||
|
{ 0x07b8, 0x03cd },
|
||||||
|
{ 0x07b9, 0x03cb },
|
||||||
|
{ 0x07ba, 0x03b0 },
|
||||||
|
{ 0x07bb, 0x03ce },
|
||||||
|
{ 0x07c1, 0x0391 },
|
||||||
|
{ 0x07c2, 0x0392 },
|
||||||
|
{ 0x07c3, 0x0393 },
|
||||||
|
{ 0x07c4, 0x0394 },
|
||||||
|
{ 0x07c5, 0x0395 },
|
||||||
|
{ 0x07c6, 0x0396 },
|
||||||
|
{ 0x07c7, 0x0397 },
|
||||||
|
{ 0x07c8, 0x0398 },
|
||||||
|
{ 0x07c9, 0x0399 },
|
||||||
|
{ 0x07ca, 0x039a },
|
||||||
|
{ 0x07cb, 0x039b },
|
||||||
|
{ 0x07cc, 0x039c },
|
||||||
|
{ 0x07cd, 0x039d },
|
||||||
|
{ 0x07ce, 0x039e },
|
||||||
|
{ 0x07cf, 0x039f },
|
||||||
|
{ 0x07d0, 0x03a0 },
|
||||||
|
{ 0x07d1, 0x03a1 },
|
||||||
|
{ 0x07d2, 0x03a3 },
|
||||||
|
{ 0x07d4, 0x03a4 },
|
||||||
|
{ 0x07d5, 0x03a5 },
|
||||||
|
{ 0x07d6, 0x03a6 },
|
||||||
|
{ 0x07d7, 0x03a7 },
|
||||||
|
{ 0x07d8, 0x03a8 },
|
||||||
|
{ 0x07d9, 0x03a9 },
|
||||||
|
{ 0x07e1, 0x03b1 },
|
||||||
|
{ 0x07e2, 0x03b2 },
|
||||||
|
{ 0x07e3, 0x03b3 },
|
||||||
|
{ 0x07e4, 0x03b4 },
|
||||||
|
{ 0x07e5, 0x03b5 },
|
||||||
|
{ 0x07e6, 0x03b6 },
|
||||||
|
{ 0x07e7, 0x03b7 },
|
||||||
|
{ 0x07e8, 0x03b8 },
|
||||||
|
{ 0x07e9, 0x03b9 },
|
||||||
|
{ 0x07ea, 0x03ba },
|
||||||
|
{ 0x07eb, 0x03bb },
|
||||||
|
{ 0x07ec, 0x03bc },
|
||||||
|
{ 0x07ed, 0x03bd },
|
||||||
|
{ 0x07ee, 0x03be },
|
||||||
|
{ 0x07ef, 0x03bf },
|
||||||
|
{ 0x07f0, 0x03c0 },
|
||||||
|
{ 0x07f1, 0x03c1 },
|
||||||
|
{ 0x07f2, 0x03c3 },
|
||||||
|
{ 0x07f3, 0x03c2 },
|
||||||
|
{ 0x07f4, 0x03c4 },
|
||||||
|
{ 0x07f5, 0x03c5 },
|
||||||
|
{ 0x07f6, 0x03c6 },
|
||||||
|
{ 0x07f7, 0x03c7 },
|
||||||
|
{ 0x07f8, 0x03c8 },
|
||||||
|
{ 0x07f9, 0x03c9 },
|
||||||
|
{ 0x08a1, 0x23b7 },
|
||||||
|
{ 0x08a2, 0x250c },
|
||||||
|
{ 0x08a3, 0x2500 },
|
||||||
|
{ 0x08a4, 0x2320 },
|
||||||
|
{ 0x08a5, 0x2321 },
|
||||||
|
{ 0x08a6, 0x2502 },
|
||||||
|
{ 0x08a7, 0x23a1 },
|
||||||
|
{ 0x08a8, 0x23a3 },
|
||||||
|
{ 0x08a9, 0x23a4 },
|
||||||
|
{ 0x08aa, 0x23a6 },
|
||||||
|
{ 0x08ab, 0x239b },
|
||||||
|
{ 0x08ac, 0x239d },
|
||||||
|
{ 0x08ad, 0x239e },
|
||||||
|
{ 0x08ae, 0x23a0 },
|
||||||
|
{ 0x08af, 0x23a8 },
|
||||||
|
{ 0x08b0, 0x23ac },
|
||||||
|
{ 0x08bc, 0x2264 },
|
||||||
|
{ 0x08bd, 0x2260 },
|
||||||
|
{ 0x08be, 0x2265 },
|
||||||
|
{ 0x08bf, 0x222b },
|
||||||
|
{ 0x08c0, 0x2234 },
|
||||||
|
{ 0x08c1, 0x221d },
|
||||||
|
{ 0x08c2, 0x221e },
|
||||||
|
{ 0x08c5, 0x2207 },
|
||||||
|
{ 0x08c8, 0x223c },
|
||||||
|
{ 0x08c9, 0x2243 },
|
||||||
|
{ 0x08cd, 0x21d4 },
|
||||||
|
{ 0x08ce, 0x21d2 },
|
||||||
|
{ 0x08cf, 0x2261 },
|
||||||
|
{ 0x08d6, 0x221a },
|
||||||
|
{ 0x08da, 0x2282 },
|
||||||
|
{ 0x08db, 0x2283 },
|
||||||
|
{ 0x08dc, 0x2229 },
|
||||||
|
{ 0x08dd, 0x222a },
|
||||||
|
{ 0x08de, 0x2227 },
|
||||||
|
{ 0x08df, 0x2228 },
|
||||||
|
{ 0x08ef, 0x2202 },
|
||||||
|
{ 0x08f6, 0x0192 },
|
||||||
|
{ 0x08fb, 0x2190 },
|
||||||
|
{ 0x08fc, 0x2191 },
|
||||||
|
{ 0x08fd, 0x2192 },
|
||||||
|
{ 0x08fe, 0x2193 },
|
||||||
|
{ 0x09e0, 0x25c6 },
|
||||||
|
{ 0x09e1, 0x2592 },
|
||||||
|
{ 0x09e2, 0x2409 },
|
||||||
|
{ 0x09e3, 0x240c },
|
||||||
|
{ 0x09e4, 0x240d },
|
||||||
|
{ 0x09e5, 0x240a },
|
||||||
|
{ 0x09e8, 0x2424 },
|
||||||
|
{ 0x09e9, 0x240b },
|
||||||
|
{ 0x09ea, 0x2518 },
|
||||||
|
{ 0x09eb, 0x2510 },
|
||||||
|
{ 0x09ec, 0x250c },
|
||||||
|
{ 0x09ed, 0x2514 },
|
||||||
|
{ 0x09ee, 0x253c },
|
||||||
|
{ 0x09ef, 0x23ba },
|
||||||
|
{ 0x09f0, 0x23bb },
|
||||||
|
{ 0x09f1, 0x2500 },
|
||||||
|
{ 0x09f2, 0x23bc },
|
||||||
|
{ 0x09f3, 0x23bd },
|
||||||
|
{ 0x09f4, 0x251c },
|
||||||
|
{ 0x09f5, 0x2524 },
|
||||||
|
{ 0x09f6, 0x2534 },
|
||||||
|
{ 0x09f7, 0x252c },
|
||||||
|
{ 0x09f8, 0x2502 },
|
||||||
|
{ 0x0aa1, 0x2003 },
|
||||||
|
{ 0x0aa2, 0x2002 },
|
||||||
|
{ 0x0aa3, 0x2004 },
|
||||||
|
{ 0x0aa4, 0x2005 },
|
||||||
|
{ 0x0aa5, 0x2007 },
|
||||||
|
{ 0x0aa6, 0x2008 },
|
||||||
|
{ 0x0aa7, 0x2009 },
|
||||||
|
{ 0x0aa8, 0x200a },
|
||||||
|
{ 0x0aa9, 0x2014 },
|
||||||
|
{ 0x0aaa, 0x2013 },
|
||||||
|
{ 0x0aae, 0x2026 },
|
||||||
|
{ 0x0aaf, 0x2025 },
|
||||||
|
{ 0x0ab0, 0x2153 },
|
||||||
|
{ 0x0ab1, 0x2154 },
|
||||||
|
{ 0x0ab2, 0x2155 },
|
||||||
|
{ 0x0ab3, 0x2156 },
|
||||||
|
{ 0x0ab4, 0x2157 },
|
||||||
|
{ 0x0ab5, 0x2158 },
|
||||||
|
{ 0x0ab6, 0x2159 },
|
||||||
|
{ 0x0ab7, 0x215a },
|
||||||
|
{ 0x0ab8, 0x2105 },
|
||||||
|
{ 0x0abb, 0x2012 },
|
||||||
|
{ 0x0abc, 0x2329 },
|
||||||
|
{ 0x0abe, 0x232a },
|
||||||
|
{ 0x0ac3, 0x215b },
|
||||||
|
{ 0x0ac4, 0x215c },
|
||||||
|
{ 0x0ac5, 0x215d },
|
||||||
|
{ 0x0ac6, 0x215e },
|
||||||
|
{ 0x0ac9, 0x2122 },
|
||||||
|
{ 0x0aca, 0x2613 },
|
||||||
|
{ 0x0acc, 0x25c1 },
|
||||||
|
{ 0x0acd, 0x25b7 },
|
||||||
|
{ 0x0ace, 0x25cb },
|
||||||
|
{ 0x0acf, 0x25af },
|
||||||
|
{ 0x0ad0, 0x2018 },
|
||||||
|
{ 0x0ad1, 0x2019 },
|
||||||
|
{ 0x0ad2, 0x201c },
|
||||||
|
{ 0x0ad3, 0x201d },
|
||||||
|
{ 0x0ad4, 0x211e },
|
||||||
|
{ 0x0ad6, 0x2032 },
|
||||||
|
{ 0x0ad7, 0x2033 },
|
||||||
|
{ 0x0ad9, 0x271d },
|
||||||
|
{ 0x0adb, 0x25ac },
|
||||||
|
{ 0x0adc, 0x25c0 },
|
||||||
|
{ 0x0add, 0x25b6 },
|
||||||
|
{ 0x0ade, 0x25cf },
|
||||||
|
{ 0x0adf, 0x25ae },
|
||||||
|
{ 0x0ae0, 0x25e6 },
|
||||||
|
{ 0x0ae1, 0x25ab },
|
||||||
|
{ 0x0ae2, 0x25ad },
|
||||||
|
{ 0x0ae3, 0x25b3 },
|
||||||
|
{ 0x0ae4, 0x25bd },
|
||||||
|
{ 0x0ae5, 0x2606 },
|
||||||
|
{ 0x0ae6, 0x2022 },
|
||||||
|
{ 0x0ae7, 0x25aa },
|
||||||
|
{ 0x0ae8, 0x25b2 },
|
||||||
|
{ 0x0ae9, 0x25bc },
|
||||||
|
{ 0x0aea, 0x261c },
|
||||||
|
{ 0x0aeb, 0x261e },
|
||||||
|
{ 0x0aec, 0x2663 },
|
||||||
|
{ 0x0aed, 0x2666 },
|
||||||
|
{ 0x0aee, 0x2665 },
|
||||||
|
{ 0x0af0, 0x2720 },
|
||||||
|
{ 0x0af1, 0x2020 },
|
||||||
|
{ 0x0af2, 0x2021 },
|
||||||
|
{ 0x0af3, 0x2713 },
|
||||||
|
{ 0x0af4, 0x2717 },
|
||||||
|
{ 0x0af5, 0x266f },
|
||||||
|
{ 0x0af6, 0x266d },
|
||||||
|
{ 0x0af7, 0x2642 },
|
||||||
|
{ 0x0af8, 0x2640 },
|
||||||
|
{ 0x0af9, 0x260e },
|
||||||
|
{ 0x0afa, 0x2315 },
|
||||||
|
{ 0x0afb, 0x2117 },
|
||||||
|
{ 0x0afc, 0x2038 },
|
||||||
|
{ 0x0afd, 0x201a },
|
||||||
|
{ 0x0afe, 0x201e },
|
||||||
|
{ 0x0ba3, 0x003c },
|
||||||
|
{ 0x0ba6, 0x003e },
|
||||||
|
{ 0x0ba8, 0x2228 },
|
||||||
|
{ 0x0ba9, 0x2227 },
|
||||||
|
{ 0x0bc0, 0x00af },
|
||||||
|
{ 0x0bc2, 0x22a5 },
|
||||||
|
{ 0x0bc3, 0x2229 },
|
||||||
|
{ 0x0bc4, 0x230a },
|
||||||
|
{ 0x0bc6, 0x005f },
|
||||||
|
{ 0x0bca, 0x2218 },
|
||||||
|
{ 0x0bcc, 0x2395 },
|
||||||
|
{ 0x0bce, 0x22a4 },
|
||||||
|
{ 0x0bcf, 0x25cb },
|
||||||
|
{ 0x0bd3, 0x2308 },
|
||||||
|
{ 0x0bd6, 0x222a },
|
||||||
|
{ 0x0bd8, 0x2283 },
|
||||||
|
{ 0x0bda, 0x2282 },
|
||||||
|
{ 0x0bdc, 0x22a2 },
|
||||||
|
{ 0x0bfc, 0x22a3 },
|
||||||
|
{ 0x0cdf, 0x2017 },
|
||||||
|
{ 0x0ce0, 0x05d0 },
|
||||||
|
{ 0x0ce1, 0x05d1 },
|
||||||
|
{ 0x0ce2, 0x05d2 },
|
||||||
|
{ 0x0ce3, 0x05d3 },
|
||||||
|
{ 0x0ce4, 0x05d4 },
|
||||||
|
{ 0x0ce5, 0x05d5 },
|
||||||
|
{ 0x0ce6, 0x05d6 },
|
||||||
|
{ 0x0ce7, 0x05d7 },
|
||||||
|
{ 0x0ce8, 0x05d8 },
|
||||||
|
{ 0x0ce9, 0x05d9 },
|
||||||
|
{ 0x0cea, 0x05da },
|
||||||
|
{ 0x0ceb, 0x05db },
|
||||||
|
{ 0x0cec, 0x05dc },
|
||||||
|
{ 0x0ced, 0x05dd },
|
||||||
|
{ 0x0cee, 0x05de },
|
||||||
|
{ 0x0cef, 0x05df },
|
||||||
|
{ 0x0cf0, 0x05e0 },
|
||||||
|
{ 0x0cf1, 0x05e1 },
|
||||||
|
{ 0x0cf2, 0x05e2 },
|
||||||
|
{ 0x0cf3, 0x05e3 },
|
||||||
|
{ 0x0cf4, 0x05e4 },
|
||||||
|
{ 0x0cf5, 0x05e5 },
|
||||||
|
{ 0x0cf6, 0x05e6 },
|
||||||
|
{ 0x0cf7, 0x05e7 },
|
||||||
|
{ 0x0cf8, 0x05e8 },
|
||||||
|
{ 0x0cf9, 0x05e9 },
|
||||||
|
{ 0x0cfa, 0x05ea },
|
||||||
|
{ 0x0da1, 0x0e01 },
|
||||||
|
{ 0x0da2, 0x0e02 },
|
||||||
|
{ 0x0da3, 0x0e03 },
|
||||||
|
{ 0x0da4, 0x0e04 },
|
||||||
|
{ 0x0da5, 0x0e05 },
|
||||||
|
{ 0x0da6, 0x0e06 },
|
||||||
|
{ 0x0da7, 0x0e07 },
|
||||||
|
{ 0x0da8, 0x0e08 },
|
||||||
|
{ 0x0da9, 0x0e09 },
|
||||||
|
{ 0x0daa, 0x0e0a },
|
||||||
|
{ 0x0dab, 0x0e0b },
|
||||||
|
{ 0x0dac, 0x0e0c },
|
||||||
|
{ 0x0dad, 0x0e0d },
|
||||||
|
{ 0x0dae, 0x0e0e },
|
||||||
|
{ 0x0daf, 0x0e0f },
|
||||||
|
{ 0x0db0, 0x0e10 },
|
||||||
|
{ 0x0db1, 0x0e11 },
|
||||||
|
{ 0x0db2, 0x0e12 },
|
||||||
|
{ 0x0db3, 0x0e13 },
|
||||||
|
{ 0x0db4, 0x0e14 },
|
||||||
|
{ 0x0db5, 0x0e15 },
|
||||||
|
{ 0x0db6, 0x0e16 },
|
||||||
|
{ 0x0db7, 0x0e17 },
|
||||||
|
{ 0x0db8, 0x0e18 },
|
||||||
|
{ 0x0db9, 0x0e19 },
|
||||||
|
{ 0x0dba, 0x0e1a },
|
||||||
|
{ 0x0dbb, 0x0e1b },
|
||||||
|
{ 0x0dbc, 0x0e1c },
|
||||||
|
{ 0x0dbd, 0x0e1d },
|
||||||
|
{ 0x0dbe, 0x0e1e },
|
||||||
|
{ 0x0dbf, 0x0e1f },
|
||||||
|
{ 0x0dc0, 0x0e20 },
|
||||||
|
{ 0x0dc1, 0x0e21 },
|
||||||
|
{ 0x0dc2, 0x0e22 },
|
||||||
|
{ 0x0dc3, 0x0e23 },
|
||||||
|
{ 0x0dc4, 0x0e24 },
|
||||||
|
{ 0x0dc5, 0x0e25 },
|
||||||
|
{ 0x0dc6, 0x0e26 },
|
||||||
|
{ 0x0dc7, 0x0e27 },
|
||||||
|
{ 0x0dc8, 0x0e28 },
|
||||||
|
{ 0x0dc9, 0x0e29 },
|
||||||
|
{ 0x0dca, 0x0e2a },
|
||||||
|
{ 0x0dcb, 0x0e2b },
|
||||||
|
{ 0x0dcc, 0x0e2c },
|
||||||
|
{ 0x0dcd, 0x0e2d },
|
||||||
|
{ 0x0dce, 0x0e2e },
|
||||||
|
{ 0x0dcf, 0x0e2f },
|
||||||
|
{ 0x0dd0, 0x0e30 },
|
||||||
|
{ 0x0dd1, 0x0e31 },
|
||||||
|
{ 0x0dd2, 0x0e32 },
|
||||||
|
{ 0x0dd3, 0x0e33 },
|
||||||
|
{ 0x0dd4, 0x0e34 },
|
||||||
|
{ 0x0dd5, 0x0e35 },
|
||||||
|
{ 0x0dd6, 0x0e36 },
|
||||||
|
{ 0x0dd7, 0x0e37 },
|
||||||
|
{ 0x0dd8, 0x0e38 },
|
||||||
|
{ 0x0dd9, 0x0e39 },
|
||||||
|
{ 0x0dda, 0x0e3a },
|
||||||
|
{ 0x0ddf, 0x0e3f },
|
||||||
|
{ 0x0de0, 0x0e40 },
|
||||||
|
{ 0x0de1, 0x0e41 },
|
||||||
|
{ 0x0de2, 0x0e42 },
|
||||||
|
{ 0x0de3, 0x0e43 },
|
||||||
|
{ 0x0de4, 0x0e44 },
|
||||||
|
{ 0x0de5, 0x0e45 },
|
||||||
|
{ 0x0de6, 0x0e46 },
|
||||||
|
{ 0x0de7, 0x0e47 },
|
||||||
|
{ 0x0de8, 0x0e48 },
|
||||||
|
{ 0x0de9, 0x0e49 },
|
||||||
|
{ 0x0dea, 0x0e4a },
|
||||||
|
{ 0x0deb, 0x0e4b },
|
||||||
|
{ 0x0dec, 0x0e4c },
|
||||||
|
{ 0x0ded, 0x0e4d },
|
||||||
|
{ 0x0df0, 0x0e50 },
|
||||||
|
{ 0x0df1, 0x0e51 },
|
||||||
|
{ 0x0df2, 0x0e52 },
|
||||||
|
{ 0x0df3, 0x0e53 },
|
||||||
|
{ 0x0df4, 0x0e54 },
|
||||||
|
{ 0x0df5, 0x0e55 },
|
||||||
|
{ 0x0df6, 0x0e56 },
|
||||||
|
{ 0x0df7, 0x0e57 },
|
||||||
|
{ 0x0df8, 0x0e58 },
|
||||||
|
{ 0x0df9, 0x0e59 },
|
||||||
|
{ 0x0ea1, 0x3131 },
|
||||||
|
{ 0x0ea2, 0x3132 },
|
||||||
|
{ 0x0ea3, 0x3133 },
|
||||||
|
{ 0x0ea4, 0x3134 },
|
||||||
|
{ 0x0ea5, 0x3135 },
|
||||||
|
{ 0x0ea6, 0x3136 },
|
||||||
|
{ 0x0ea7, 0x3137 },
|
||||||
|
{ 0x0ea8, 0x3138 },
|
||||||
|
{ 0x0ea9, 0x3139 },
|
||||||
|
{ 0x0eaa, 0x313a },
|
||||||
|
{ 0x0eab, 0x313b },
|
||||||
|
{ 0x0eac, 0x313c },
|
||||||
|
{ 0x0ead, 0x313d },
|
||||||
|
{ 0x0eae, 0x313e },
|
||||||
|
{ 0x0eaf, 0x313f },
|
||||||
|
{ 0x0eb0, 0x3140 },
|
||||||
|
{ 0x0eb1, 0x3141 },
|
||||||
|
{ 0x0eb2, 0x3142 },
|
||||||
|
{ 0x0eb3, 0x3143 },
|
||||||
|
{ 0x0eb4, 0x3144 },
|
||||||
|
{ 0x0eb5, 0x3145 },
|
||||||
|
{ 0x0eb6, 0x3146 },
|
||||||
|
{ 0x0eb7, 0x3147 },
|
||||||
|
{ 0x0eb8, 0x3148 },
|
||||||
|
{ 0x0eb9, 0x3149 },
|
||||||
|
{ 0x0eba, 0x314a },
|
||||||
|
{ 0x0ebb, 0x314b },
|
||||||
|
{ 0x0ebc, 0x314c },
|
||||||
|
{ 0x0ebd, 0x314d },
|
||||||
|
{ 0x0ebe, 0x314e },
|
||||||
|
{ 0x0ebf, 0x314f },
|
||||||
|
{ 0x0ec0, 0x3150 },
|
||||||
|
{ 0x0ec1, 0x3151 },
|
||||||
|
{ 0x0ec2, 0x3152 },
|
||||||
|
{ 0x0ec3, 0x3153 },
|
||||||
|
{ 0x0ec4, 0x3154 },
|
||||||
|
{ 0x0ec5, 0x3155 },
|
||||||
|
{ 0x0ec6, 0x3156 },
|
||||||
|
{ 0x0ec7, 0x3157 },
|
||||||
|
{ 0x0ec8, 0x3158 },
|
||||||
|
{ 0x0ec9, 0x3159 },
|
||||||
|
{ 0x0eca, 0x315a },
|
||||||
|
{ 0x0ecb, 0x315b },
|
||||||
|
{ 0x0ecc, 0x315c },
|
||||||
|
{ 0x0ecd, 0x315d },
|
||||||
|
{ 0x0ece, 0x315e },
|
||||||
|
{ 0x0ecf, 0x315f },
|
||||||
|
{ 0x0ed0, 0x3160 },
|
||||||
|
{ 0x0ed1, 0x3161 },
|
||||||
|
{ 0x0ed2, 0x3162 },
|
||||||
|
{ 0x0ed3, 0x3163 },
|
||||||
|
{ 0x0ed4, 0x11a8 },
|
||||||
|
{ 0x0ed5, 0x11a9 },
|
||||||
|
{ 0x0ed6, 0x11aa },
|
||||||
|
{ 0x0ed7, 0x11ab },
|
||||||
|
{ 0x0ed8, 0x11ac },
|
||||||
|
{ 0x0ed9, 0x11ad },
|
||||||
|
{ 0x0eda, 0x11ae },
|
||||||
|
{ 0x0edb, 0x11af },
|
||||||
|
{ 0x0edc, 0x11b0 },
|
||||||
|
{ 0x0edd, 0x11b1 },
|
||||||
|
{ 0x0ede, 0x11b2 },
|
||||||
|
{ 0x0edf, 0x11b3 },
|
||||||
|
{ 0x0ee0, 0x11b4 },
|
||||||
|
{ 0x0ee1, 0x11b5 },
|
||||||
|
{ 0x0ee2, 0x11b6 },
|
||||||
|
{ 0x0ee3, 0x11b7 },
|
||||||
|
{ 0x0ee4, 0x11b8 },
|
||||||
|
{ 0x0ee5, 0x11b9 },
|
||||||
|
{ 0x0ee6, 0x11ba },
|
||||||
|
{ 0x0ee7, 0x11bb },
|
||||||
|
{ 0x0ee8, 0x11bc },
|
||||||
|
{ 0x0ee9, 0x11bd },
|
||||||
|
{ 0x0eea, 0x11be },
|
||||||
|
{ 0x0eeb, 0x11bf },
|
||||||
|
{ 0x0eec, 0x11c0 },
|
||||||
|
{ 0x0eed, 0x11c1 },
|
||||||
|
{ 0x0eee, 0x11c2 },
|
||||||
|
{ 0x0eef, 0x316d },
|
||||||
|
{ 0x0ef0, 0x3171 },
|
||||||
|
{ 0x0ef1, 0x3178 },
|
||||||
|
{ 0x0ef2, 0x317f },
|
||||||
|
{ 0x0ef3, 0x3181 },
|
||||||
|
{ 0x0ef4, 0x3184 },
|
||||||
|
{ 0x0ef5, 0x3186 },
|
||||||
|
{ 0x0ef6, 0x318d },
|
||||||
|
{ 0x0ef7, 0x318e },
|
||||||
|
{ 0x0ef8, 0x11eb },
|
||||||
|
{ 0x0ef9, 0x11f0 },
|
||||||
|
{ 0x0efa, 0x11f9 },
|
||||||
|
{ 0x0eff, 0x20a9 },
|
||||||
|
{ 0x13a4, 0x20ac },
|
||||||
|
{ 0x13bc, 0x0152 },
|
||||||
|
{ 0x13bd, 0x0153 },
|
||||||
|
{ 0x13be, 0x0178 },
|
||||||
|
{ 0x20ac, 0x20ac },
|
||||||
|
{ 0xfe50, '`' },
|
||||||
|
{ 0xfe51, 0x00b4 },
|
||||||
|
{ 0xfe52, '^' },
|
||||||
|
{ 0xfe53, '~' },
|
||||||
|
{ 0xfe54, 0x00af },
|
||||||
|
{ 0xfe55, 0x02d8 },
|
||||||
|
{ 0xfe56, 0x02d9 },
|
||||||
|
{ 0xfe57, 0x00a8 },
|
||||||
|
{ 0xfe58, 0x02da },
|
||||||
|
{ 0xfe59, 0x02dd },
|
||||||
|
{ 0xfe5a, 0x02c7 },
|
||||||
|
{ 0xfe5b, 0x00b8 },
|
||||||
|
{ 0xfe5c, 0x02db },
|
||||||
|
{ 0xfe5d, 0x037a },
|
||||||
|
{ 0xfe5e, 0x309b },
|
||||||
|
{ 0xfe5f, 0x309c },
|
||||||
|
{ 0xfe63, '/' },
|
||||||
|
{ 0xfe64, 0x02bc },
|
||||||
|
{ 0xfe65, 0x02bd },
|
||||||
|
{ 0xfe66, 0x02f5 },
|
||||||
|
{ 0xfe67, 0x02f3 },
|
||||||
|
{ 0xfe68, 0x02cd },
|
||||||
|
{ 0xfe69, 0xa788 },
|
||||||
|
{ 0xfe6a, 0x02f7 },
|
||||||
|
{ 0xfe6e, ',' },
|
||||||
|
{ 0xfe6f, 0x00a4 },
|
||||||
|
{ 0xfe80, 'a' }, // XK_dead_a
|
||||||
|
{ 0xfe81, 'A' }, // XK_dead_A
|
||||||
|
{ 0xfe82, 'e' }, // XK_dead_e
|
||||||
|
{ 0xfe83, 'E' }, // XK_dead_E
|
||||||
|
{ 0xfe84, 'i' }, // XK_dead_i
|
||||||
|
{ 0xfe85, 'I' }, // XK_dead_I
|
||||||
|
{ 0xfe86, 'o' }, // XK_dead_o
|
||||||
|
{ 0xfe87, 'O' }, // XK_dead_O
|
||||||
|
{ 0xfe88, 'u' }, // XK_dead_u
|
||||||
|
{ 0xfe89, 'U' }, // XK_dead_U
|
||||||
|
{ 0xfe8a, 0x0259 },
|
||||||
|
{ 0xfe8b, 0x018f },
|
||||||
|
{ 0xfe8c, 0x00b5 },
|
||||||
|
{ 0xfe90, '_' },
|
||||||
|
{ 0xfe91, 0x02c8 },
|
||||||
|
{ 0xfe92, 0x02cc },
|
||||||
|
{ 0xff80 /*XKB_KEY_KP_Space*/, ' ' },
|
||||||
|
{ 0xff95 /*XKB_KEY_KP_7*/, 0x0037 },
|
||||||
|
{ 0xff96 /*XKB_KEY_KP_4*/, 0x0034 },
|
||||||
|
{ 0xff97 /*XKB_KEY_KP_8*/, 0x0038 },
|
||||||
|
{ 0xff98 /*XKB_KEY_KP_6*/, 0x0036 },
|
||||||
|
{ 0xff99 /*XKB_KEY_KP_2*/, 0x0032 },
|
||||||
|
{ 0xff9a /*XKB_KEY_KP_9*/, 0x0039 },
|
||||||
|
{ 0xff9b /*XKB_KEY_KP_3*/, 0x0033 },
|
||||||
|
{ 0xff9c /*XKB_KEY_KP_1*/, 0x0031 },
|
||||||
|
{ 0xff9d /*XKB_KEY_KP_5*/, 0x0035 },
|
||||||
|
{ 0xff9e /*XKB_KEY_KP_0*/, 0x0030 },
|
||||||
|
{ 0xffaa /*XKB_KEY_KP_Multiply*/, '*' },
|
||||||
|
{ 0xffab /*XKB_KEY_KP_Add*/, '+' },
|
||||||
|
{ 0xffac /*XKB_KEY_KP_Separator*/, ',' },
|
||||||
|
{ 0xffad /*XKB_KEY_KP_Subtract*/, '-' },
|
||||||
|
{ 0xffae /*XKB_KEY_KP_Decimal*/, '.' },
|
||||||
|
{ 0xffaf /*XKB_KEY_KP_Divide*/, '/' },
|
||||||
|
{ 0xffb0 /*XKB_KEY_KP_0*/, 0x0030 },
|
||||||
|
{ 0xffb1 /*XKB_KEY_KP_1*/, 0x0031 },
|
||||||
|
{ 0xffb2 /*XKB_KEY_KP_2*/, 0x0032 },
|
||||||
|
{ 0xffb3 /*XKB_KEY_KP_3*/, 0x0033 },
|
||||||
|
{ 0xffb4 /*XKB_KEY_KP_4*/, 0x0034 },
|
||||||
|
{ 0xffb5 /*XKB_KEY_KP_5*/, 0x0035 },
|
||||||
|
{ 0xffb6 /*XKB_KEY_KP_6*/, 0x0036 },
|
||||||
|
{ 0xffb7 /*XKB_KEY_KP_7*/, 0x0037 },
|
||||||
|
{ 0xffb8 /*XKB_KEY_KP_8*/, 0x0038 },
|
||||||
|
{ 0xffb9 /*XKB_KEY_KP_9*/, 0x0039 },
|
||||||
|
{ 0xffbd /*XKB_KEY_KP_Equal*/, '=' }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Convert XKB KeySym to Unicode
|
||||||
|
//
|
||||||
|
long _glfwKeySym2Unicode(unsigned int keysym)
|
||||||
|
{
|
||||||
|
int min = 0;
|
||||||
|
int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
|
||||||
|
int mid;
|
||||||
|
|
||||||
|
// First check for Latin-1 characters (1:1 mapping)
|
||||||
|
if ((keysym >= 0x0020 && keysym <= 0x007e) ||
|
||||||
|
(keysym >= 0x00a0 && keysym <= 0x00ff))
|
||||||
|
{
|
||||||
|
return keysym;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also check for directly encoded 24-bit UCS characters
|
||||||
|
if ((keysym & 0xff000000) == 0x01000000)
|
||||||
|
return keysym & 0x00ffffff;
|
||||||
|
|
||||||
|
// Binary search in table
|
||||||
|
while (max >= min)
|
||||||
|
{
|
||||||
|
mid = (min + max) / 2;
|
||||||
|
if (keysymtab[mid].keysym < keysym)
|
||||||
|
min = mid + 1;
|
||||||
|
else if (keysymtab[mid].keysym > keysym)
|
||||||
|
max = mid - 1;
|
||||||
|
else
|
||||||
|
return keysymtab[mid].ucs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No matching Unicode value found
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 Linux - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would
|
||||||
|
// be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not
|
||||||
|
// be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
long _glfwKeySym2Unicode(unsigned int keysym);
|
||||||
|
|
|
@ -2,8 +2,26 @@ cmake_minimum_required(VERSION 3.14)
|
||||||
project(nexus)
|
project(nexus)
|
||||||
|
|
||||||
|
|
||||||
find_package(X11 REQUIRED)
|
###########################################################
|
||||||
find_package(OpenGL REQUIRED)
|
# DIRECTORIES
|
||||||
|
###########################################################
|
||||||
|
|
||||||
|
set(3RD_PARTY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdParty)
|
||||||
|
|
||||||
|
|
||||||
|
###########################################################
|
||||||
|
# 3RD PARTY LIBRARIES
|
||||||
|
###########################################################
|
||||||
|
|
||||||
|
# GLFW (window creation and input)
|
||||||
|
set(GLFW_BUILD_EXAMPLES OFF)
|
||||||
|
set(GLFW_BUILD_TESTS OFF)
|
||||||
|
set(GLFW_BUILD_DOCS OFF)
|
||||||
|
set(GLFW_INSTALL OFF)
|
||||||
|
add_subdirectory(${3RD_PARTY_DIR}/glfw-3.3.3)
|
||||||
|
|
||||||
|
# glad (OpenGL function loading)
|
||||||
|
add_subdirectory(${3RD_PARTY_DIR}/glad)
|
||||||
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
@ -22,7 +40,6 @@ target_compile_options(
|
||||||
target_sources(
|
target_sources(
|
||||||
nexus
|
nexus
|
||||||
PRIVATE
|
PRIVATE
|
||||||
Source/Graphics/GlLoader.cpp
|
|
||||||
Source/Graphics/Shader.cpp
|
Source/Graphics/Shader.cpp
|
||||||
Source/Main.cpp
|
Source/Main.cpp
|
||||||
Source/Systems/CameraControlSystem.cpp
|
Source/Systems/CameraControlSystem.cpp
|
||||||
|
@ -61,5 +78,6 @@ target_include_directories(
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
nexus
|
nexus
|
||||||
PRIVATE
|
PRIVATE
|
||||||
OpenGL::GLX
|
glad
|
||||||
X11::X11)
|
glfw)
|
||||||
|
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
#include "GlLoader.hpp"
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
|
|
||||||
PFNGLCREATESHADERPROC glCreateShader = nullptr;
|
|
||||||
PFNGLSHADERSOURCEPROC glShaderSource = nullptr;
|
|
||||||
PFNGLCOMPILESHADERPROC glCompileShader = nullptr;
|
|
||||||
PFNGLGETSHADERIVPROC glGetShaderiv = nullptr;
|
|
||||||
PFNGLGETSHADERSOURCEPROC glGetShaderInfo = nullptr;
|
|
||||||
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = nullptr;
|
|
||||||
PFNGLCREATEPROGRAMPROC glCreateProgram = nullptr;
|
|
||||||
PFNGLATTACHSHADERPROC glAttachShader = nullptr;
|
|
||||||
PFNGLLINKPROGRAMPROC glLinkProgram = nullptr;
|
|
||||||
PFNGLGETPROGRAMIVPROC glGetProgramiv = nullptr;
|
|
||||||
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = nullptr;
|
|
||||||
PFNGLDELETESHADERPROC glDeleteShader = nullptr;
|
|
||||||
PFNGLGENBUFFERSPROC glGenBuffers = nullptr;
|
|
||||||
PFNGLBINDBUFFERPROC glBindBuffer = nullptr;
|
|
||||||
PFNGLBUFFERDATAPROC glBufferData = nullptr;
|
|
||||||
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = nullptr;
|
|
||||||
PFNGLBINDVERTEXARRAYPROC glBindVertexArray = nullptr;
|
|
||||||
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = nullptr;
|
|
||||||
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr;
|
|
||||||
PFNGLUSEPROGRAMPROC glUseProgram = nullptr;
|
|
||||||
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = nullptr;
|
|
||||||
PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv = nullptr;
|
|
||||||
PFNGLUNIFORM3FVPROC glUniform3fv = nullptr;
|
|
||||||
|
|
||||||
#define LOAD_GL_FUNCTION(type, name) \
|
|
||||||
(name) = (PFN##type##PROC) glXGetProcAddress((unsigned char *) #name); \
|
|
||||||
assert(name && "GL function not found");
|
|
||||||
|
|
||||||
void LoadGlFunctions()
|
|
||||||
{
|
|
||||||
LOAD_GL_FUNCTION(GLCREATESHADER, glCreateShader)
|
|
||||||
LOAD_GL_FUNCTION(GLSHADERSOURCE, glShaderSource)
|
|
||||||
LOAD_GL_FUNCTION(GLCOMPILESHADER, glCompileShader)
|
|
||||||
LOAD_GL_FUNCTION(GLGETSHADERIV, glGetShaderiv)
|
|
||||||
LOAD_GL_FUNCTION(GLGETSHADERSOURCE, glGetShaderInfo)
|
|
||||||
LOAD_GL_FUNCTION(GLGETSHADERINFOLOG, glGetShaderInfoLog)
|
|
||||||
LOAD_GL_FUNCTION(GLCREATEPROGRAM, glCreateProgram)
|
|
||||||
LOAD_GL_FUNCTION(GLATTACHSHADER, glAttachShader)
|
|
||||||
LOAD_GL_FUNCTION(GLLINKPROGRAM, glLinkProgram)
|
|
||||||
LOAD_GL_FUNCTION(GLGETPROGRAMIV, glGetProgramiv)
|
|
||||||
LOAD_GL_FUNCTION(GLGETPROGRAMINFOLOG, glGetProgramInfoLog)
|
|
||||||
LOAD_GL_FUNCTION(GLDELETESHADER, glDeleteShader)
|
|
||||||
LOAD_GL_FUNCTION(GLGENBUFFERS, glGenBuffers)
|
|
||||||
LOAD_GL_FUNCTION(GLBINDBUFFER, glBindBuffer)
|
|
||||||
LOAD_GL_FUNCTION(GLBUFFERDATA, glBufferData)
|
|
||||||
LOAD_GL_FUNCTION(GLGENVERTEXARRAYS, glGenVertexArrays)
|
|
||||||
LOAD_GL_FUNCTION(GLBINDVERTEXARRAY, glBindVertexArray)
|
|
||||||
LOAD_GL_FUNCTION(GLVERTEXATTRIBPOINTER, glVertexAttribPointer)
|
|
||||||
LOAD_GL_FUNCTION(GLENABLEVERTEXATTRIBARRAY, glEnableVertexAttribArray)
|
|
||||||
LOAD_GL_FUNCTION(GLUSEPROGRAM, glUseProgram)
|
|
||||||
LOAD_GL_FUNCTION(GLGETUNIFORMLOCATION, glGetUniformLocation)
|
|
||||||
LOAD_GL_FUNCTION(GLUNIFORMMATRIX4FV, glUniformMatrix4fv)
|
|
||||||
LOAD_GL_FUNCTION(GLUNIFORM3FV, glUniform3fv)
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <GL/glx.h>
|
|
||||||
|
|
||||||
|
|
||||||
extern PFNGLCREATESHADERPROC glCreateShader;
|
|
||||||
extern PFNGLSHADERSOURCEPROC glShaderSource;
|
|
||||||
extern PFNGLCOMPILESHADERPROC glCompileShader;
|
|
||||||
extern PFNGLGETSHADERIVPROC glGetShaderiv;
|
|
||||||
extern PFNGLGETSHADERSOURCEPROC glGetShaderInfo;
|
|
||||||
extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
|
|
||||||
extern PFNGLCREATEPROGRAMPROC glCreateProgram;
|
|
||||||
extern PFNGLATTACHSHADERPROC glAttachShader;
|
|
||||||
extern PFNGLLINKPROGRAMPROC glLinkProgram;
|
|
||||||
extern PFNGLGETPROGRAMIVPROC glGetProgramiv;
|
|
||||||
extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
|
|
||||||
extern PFNGLDELETESHADERPROC glDeleteShader;
|
|
||||||
extern PFNGLGENBUFFERSPROC glGenBuffers;
|
|
||||||
extern PFNGLBINDBUFFERPROC glBindBuffer;
|
|
||||||
extern PFNGLBUFFERDATAPROC glBufferData;
|
|
||||||
extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
|
|
||||||
extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
|
|
||||||
extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
|
|
||||||
extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
|
|
||||||
extern PFNGLUSEPROGRAMPROC glUseProgram;
|
|
||||||
extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
|
|
||||||
extern PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
|
|
||||||
extern PFNGLUNIFORM3FVPROC glUniform3fv;
|
|
||||||
|
|
||||||
void LoadGlFunctions();
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "GlLoader.hpp"
|
#include <glad/glad.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,6 @@ int main()
|
||||||
windowManager.Init("Nexus", 1920, 1080, 0, 0);
|
windowManager.Init("Nexus", 1920, 1080, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
LoadGlFunctions();
|
|
||||||
|
|
||||||
|
|
||||||
gCoordinator.AddEventListener(FUNCTION_LISTENER(Events::Window::QUIT, QuitHandler));
|
gCoordinator.AddEventListener(FUNCTION_LISTENER(Events::Window::QUIT, QuitHandler));
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Core/System.hpp"
|
#include "Core/System.hpp"
|
||||||
#include "Graphics/GlLoader.hpp"
|
|
||||||
#include "Graphics/Shader.hpp"
|
#include "Graphics/Shader.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include "Core/Coordinator.hpp"
|
#include "Core/Coordinator.hpp"
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <X11/XKBlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
extern Coordinator gCoordinator;
|
extern Coordinator gCoordinator;
|
||||||
|
@ -14,221 +13,76 @@ void WindowManager::Init(
|
||||||
std::string const& windowTitle, unsigned int windowWidth, unsigned int windowHeight, unsigned int windowPositionX,
|
std::string const& windowTitle, unsigned int windowWidth, unsigned int windowHeight, unsigned int windowPositionX,
|
||||||
unsigned int windowPositionY)
|
unsigned int windowPositionY)
|
||||||
{
|
{
|
||||||
// Open the mDisplay
|
glfwInit();
|
||||||
{
|
|
||||||
mDisplay = XOpenDisplay(nullptr);
|
|
||||||
|
|
||||||
if (!mDisplay)
|
mWindow = glfwCreateWindow(windowWidth, windowHeight, windowTitle.c_str(), NULL, NULL);
|
||||||
{
|
|
||||||
std::cerr << "Error: XOpenDisplay()\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the proper frame buffer config
|
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
|
||||||
GLXFBConfig frameBufferConfig{};
|
glfwWindowHint(GLFW_FOCUSED, GLFW_TRUE);
|
||||||
{
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
// Frame buffer configs were added in GLX version 1.3.
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
if (int glxMajor, glxMinor;
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
!glXQueryVersion(mDisplay, &glxMajor, &glxMinor)
|
|
||||||
|| ((glxMajor == 1) && (glxMinor < 3)) || (glxMajor < 1))
|
|
||||||
{
|
|
||||||
std::cerr << "Invalid GLX version.\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int visualAttributes[] =
|
// Create OpenGL Context
|
||||||
{
|
glfwMakeContextCurrent(mWindow);
|
||||||
GLX_X_RENDERABLE, True,
|
gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
|
||||||
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
glfwSwapInterval(2);
|
||||||
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
|
||||||
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
|
|
||||||
GLX_RED_SIZE, 8,
|
|
||||||
GLX_GREEN_SIZE, 8,
|
|
||||||
GLX_BLUE_SIZE, 8,
|
|
||||||
GLX_ALPHA_SIZE, 8,
|
|
||||||
GLX_DEPTH_SIZE, 24,
|
|
||||||
GLX_STENCIL_SIZE, 8,
|
|
||||||
GLX_DOUBLEBUFFER, True,
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// Configure OpenGL
|
||||||
int frameBufferCount;
|
|
||||||
GLXFBConfig* frameBufferConfigList = glXChooseFBConfig(
|
|
||||||
mDisplay, DefaultScreen(mDisplay), visualAttributes, &frameBufferCount);
|
|
||||||
|
|
||||||
if (!frameBufferConfigList)
|
|
||||||
{
|
|
||||||
std::cerr << "Error: glXChooseFBConfig()\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
frameBufferConfig = frameBufferConfigList[0];
|
|
||||||
|
|
||||||
XFree(frameBufferConfigList);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Create the window
|
|
||||||
{
|
|
||||||
XVisualInfo* visualInfo = glXGetVisualFromFBConfig(mDisplay, frameBufferConfig);
|
|
||||||
|
|
||||||
XSetWindowAttributes swa;
|
|
||||||
swa.colormap = XCreateColormap(
|
|
||||||
mDisplay,
|
|
||||||
RootWindow(mDisplay, visualInfo->screen),
|
|
||||||
visualInfo->visual, AllocNone);
|
|
||||||
|
|
||||||
swa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask; // NOLINT(hicpp-signed-bitwise)
|
|
||||||
|
|
||||||
mWindow = XCreateWindow(
|
|
||||||
mDisplay, RootWindow(mDisplay, visualInfo->screen),
|
|
||||||
windowPositionX, windowPositionY,
|
|
||||||
windowWidth, windowHeight,
|
|
||||||
0, visualInfo->depth, InputOutput,
|
|
||||||
visualInfo->visual,
|
|
||||||
CWColormap | CWEventMask, &swa); // NOLINT (hicpp-signed-bitwise)
|
|
||||||
|
|
||||||
if (!mWindow)
|
|
||||||
{
|
|
||||||
std::cerr << "Error: XCreateWindow()\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
XFree(visualInfo);
|
|
||||||
XStoreName(mDisplay, mWindow, windowTitle.c_str());
|
|
||||||
XMapWindow(mDisplay, mWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Create the context
|
|
||||||
{
|
|
||||||
typedef GLXContext (* glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
|
|
||||||
|
|
||||||
auto glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddress(
|
|
||||||
(const GLubyte*)"glXCreateContextAttribsARB");
|
|
||||||
|
|
||||||
if (!glXCreateContextAttribsARB)
|
|
||||||
{
|
|
||||||
std::cerr << "glXCreateContextAttribsARB() not found\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int contextAttributes[] =
|
|
||||||
{
|
|
||||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
|
||||||
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
mGlxContext = glXCreateContextAttribsARB(
|
|
||||||
mDisplay, frameBufferConfig, nullptr,
|
|
||||||
True, contextAttributes);
|
|
||||||
|
|
||||||
if (!mGlxContext)
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to create an OpenGL context\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate KeyRelease event only when physical key is actually released
|
|
||||||
{
|
|
||||||
bool detectableSet = XkbSetDetectableAutoRepeat(mDisplay, true, nullptr);
|
|
||||||
|
|
||||||
if (!detectableSet)
|
|
||||||
{
|
|
||||||
std::cerr << "Detectable auto repeat not set - holding a key down will cause event spamming and delays.\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glXMakeCurrent(mDisplay, mWindow, mGlxContext);
|
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
glXSwapBuffers(mDisplay, mWindow);
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WindowManager::Update()
|
void WindowManager::Update()
|
||||||
{
|
{
|
||||||
glXSwapBuffers(mDisplay, mWindow);
|
glfwSwapBuffers(mWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WindowManager::Shutdown()
|
void WindowManager::Shutdown()
|
||||||
{
|
{
|
||||||
glXMakeCurrent(mDisplay, 0, nullptr);
|
glfwDestroyWindow(mWindow);
|
||||||
glXDestroyContext(mDisplay, mGlxContext);
|
glfwTerminate();
|
||||||
XDestroyWindow(mDisplay, mWindow);
|
|
||||||
XCloseDisplay(mDisplay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::ProcessEvents()
|
void WindowManager::ProcessEvents()
|
||||||
{
|
{
|
||||||
XEvent xEvent;
|
glfwPollEvents();
|
||||||
|
|
||||||
if (XCheckWindowEvent(mDisplay, mWindow, ExposureMask | KeyPressMask | KeyReleaseMask, &xEvent)) // NOLINT (hicpp-signed-bitwise)
|
|
||||||
{
|
|
||||||
if (xEvent.type == Expose)
|
|
||||||
{
|
|
||||||
XWindowAttributes gwa;
|
|
||||||
XGetWindowAttributes(mDisplay, mWindow, &gwa);
|
|
||||||
glViewport(0, 0, gwa.width, gwa.height);
|
|
||||||
|
|
||||||
Event event(Events::Window::RESIZED);
|
|
||||||
event.SetParam<unsigned int>(Events::Window::Resized::WIDTH, gwa.width);
|
|
||||||
event.SetParam<unsigned int>(Events::Window::Resized::HEIGHT, gwa.height);
|
|
||||||
|
|
||||||
gCoordinator.SendEvent(event);
|
|
||||||
}
|
|
||||||
else if (xEvent.type == KeyPress)
|
|
||||||
{
|
|
||||||
KeySym key = XkbKeycodeToKeysym(
|
|
||||||
mDisplay,
|
|
||||||
static_cast<KeyCode>(xEvent.xkey.keycode),
|
|
||||||
0, 0);
|
|
||||||
|
|
||||||
bool buttonStateChanged = true;
|
bool buttonStateChanged = true;
|
||||||
|
|
||||||
if (key == XK_Escape)
|
if (glfwGetKey(mWindow, GLFW_KEY_ESCAPE))
|
||||||
{
|
{
|
||||||
gCoordinator.SendEvent(Events::Window::QUIT);
|
gCoordinator.SendEvent(Events::Window::QUIT);
|
||||||
}
|
}
|
||||||
|
else if (glfwGetKey(mWindow, GLFW_KEY_W))
|
||||||
else if (key == XK_w)
|
|
||||||
{
|
{
|
||||||
mButtons.set(static_cast<std::size_t>(InputButtons::W));
|
mButtons.set(static_cast<std::size_t>(InputButtons::W));
|
||||||
}
|
}
|
||||||
|
else if (glfwGetKey(mWindow, GLFW_KEY_A))
|
||||||
else if (key == XK_a)
|
|
||||||
{
|
{
|
||||||
mButtons.set(static_cast<std::size_t>(InputButtons::A));
|
mButtons.set(static_cast<std::size_t>(InputButtons::A));
|
||||||
}
|
}
|
||||||
|
else if (glfwGetKey(mWindow, GLFW_KEY_S))
|
||||||
else if (key == XK_s)
|
|
||||||
{
|
{
|
||||||
mButtons.set(static_cast<std::size_t>(InputButtons::S));
|
mButtons.set(static_cast<std::size_t>(InputButtons::S));
|
||||||
}
|
}
|
||||||
|
else if (glfwGetKey(mWindow, GLFW_KEY_D))
|
||||||
else if (key == XK_d)
|
|
||||||
{
|
{
|
||||||
mButtons.set(static_cast<std::size_t>(InputButtons::D));
|
mButtons.set(static_cast<std::size_t>(InputButtons::D));
|
||||||
}
|
}
|
||||||
|
else if (glfwGetKey(mWindow, GLFW_KEY_Q))
|
||||||
else if (key == XK_q)
|
|
||||||
{
|
{
|
||||||
mButtons.set(static_cast<std::size_t>(InputButtons::Q));
|
mButtons.set(static_cast<std::size_t>(InputButtons::Q));
|
||||||
}
|
}
|
||||||
|
else if (glfwGetKey(mWindow, GLFW_KEY_E))
|
||||||
else if (key == XK_e)
|
|
||||||
{
|
{
|
||||||
mButtons.set(static_cast<std::size_t>(InputButtons::E));
|
mButtons.set(static_cast<std::size_t>(InputButtons::E));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buttonStateChanged = false;
|
buttonStateChanged = false;
|
||||||
XFlush(mDisplay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buttonStateChanged)
|
if (buttonStateChanged)
|
||||||
|
@ -237,65 +91,4 @@ void WindowManager::ProcessEvents()
|
||||||
event.SetParam(Events::Window::Input::INPUT, mButtons);
|
event.SetParam(Events::Window::Input::INPUT, mButtons);
|
||||||
gCoordinator.SendEvent(event);
|
gCoordinator.SendEvent(event);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (xEvent.type == KeyRelease)
|
|
||||||
{
|
|
||||||
KeySym key = XkbKeycodeToKeysym(
|
|
||||||
mDisplay,
|
|
||||||
static_cast<KeyCode>(xEvent.xkey.keycode),
|
|
||||||
0, 0);
|
|
||||||
|
|
||||||
bool buttonStateChanged = true;
|
|
||||||
|
|
||||||
if (key == XK_Escape)
|
|
||||||
{
|
|
||||||
gCoordinator.SendEvent(Events::Window::QUIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (key == XK_w)
|
|
||||||
{
|
|
||||||
mButtons.reset(static_cast<std::size_t>(InputButtons::W));
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (key == XK_a)
|
|
||||||
{
|
|
||||||
mButtons.reset(static_cast<std::size_t>(InputButtons::A));
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (key == XK_s)
|
|
||||||
{
|
|
||||||
mButtons.reset(static_cast<std::size_t>(InputButtons::S));
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (key == XK_d)
|
|
||||||
{
|
|
||||||
mButtons.reset(static_cast<std::size_t>(InputButtons::D));
|
|
||||||
}
|
|
||||||
else if (key == XK_q)
|
|
||||||
{
|
|
||||||
mButtons.reset(static_cast<std::size_t>(InputButtons::Q));
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (key == XK_e)
|
|
||||||
{
|
|
||||||
mButtons.reset(static_cast<std::size_t>(InputButtons::E));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buttonStateChanged = false;
|
|
||||||
XFlush(mDisplay);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buttonStateChanged)
|
|
||||||
{
|
|
||||||
Event event(Events::Window::INPUT);
|
|
||||||
event.SetParam(Events::Window::Input::INPUT, mButtons);
|
|
||||||
gCoordinator.SendEvent(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
XFlush(mDisplay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <glad/glad.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <GL/glx.h>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <X11/Xlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
class WindowManager
|
class WindowManager
|
||||||
|
@ -20,9 +20,7 @@ public:
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Display* mDisplay;
|
GLFWwindow* mWindow;
|
||||||
Window mWindow;
|
|
||||||
GLXContext mGlxContext;
|
|
||||||
|
|
||||||
std::bitset<8> mButtons;
|
std::bitset<8> mButtons;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue