mirror of https://github.com/inolen/redream.git
added glfw source
This commit is contained in:
parent
c0a713613c
commit
cd5447f038
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleLongVersionString</key>
|
||||
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
<key>LSRequiresCarbon</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,13 @@
|
|||
# Define the environment for cross compiling from Linux to Win64
|
||||
SET(CMAKE_SYSTEM_NAME Windows)
|
||||
SET(CMAKE_SYSTEM_VERSION 1)
|
||||
SET(CMAKE_C_COMPILER "amd64-mingw32msvc-gcc")
|
||||
SET(CMAKE_CXX_COMPILER "amd64-mingw32msvc-g++")
|
||||
SET(CMAKE_RC_COMPILER "amd64-mingw32msvc-windres")
|
||||
SET(CMAKE_RANLIB "amd64-mingw32msvc-ranlib")
|
||||
|
||||
# Configure the behaviour of the find commands
|
||||
SET(CMAKE_FIND_ROOT_PATH "/usr/amd64-mingw32msvc")
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
|
@ -0,0 +1,13 @@
|
|||
# Define the environment for cross compiling from Linux to Win32
|
||||
SET(CMAKE_SYSTEM_NAME Windows)
|
||||
SET(CMAKE_SYSTEM_VERSION 1)
|
||||
SET(CMAKE_C_COMPILER "i586-mingw32msvc-gcc")
|
||||
SET(CMAKE_CXX_COMPILER "i586-mingw32msvc-g++")
|
||||
SET(CMAKE_RC_COMPILER "i586-mingw32msvc-windres")
|
||||
SET(CMAKE_RANLIB "i586-mingw32msvc-ranlib")
|
||||
|
||||
# Configure the behaviour of the find commands
|
||||
SET(CMAKE_FIND_ROOT_PATH "/usr/i586-mingw32msvc")
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
|
@ -0,0 +1,13 @@
|
|||
# Define the environment for cross compiling from Linux to Win32
|
||||
SET(CMAKE_SYSTEM_NAME Windows) # Target system name
|
||||
SET(CMAKE_SYSTEM_VERSION 1)
|
||||
SET(CMAKE_C_COMPILER "i686-pc-mingw32-gcc")
|
||||
SET(CMAKE_CXX_COMPILER "i686-pc-mingw32-g++")
|
||||
SET(CMAKE_RC_COMPILER "i686-pc-mingw32-windres")
|
||||
SET(CMAKE_RANLIB "i686-pc-mingw32-ranlib")
|
||||
|
||||
#Configure the behaviour of the find commands
|
||||
SET(CMAKE_FIND_ROOT_PATH "/opt/mingw/usr/i686-pc-mingw32")
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
|
@ -0,0 +1,13 @@
|
|||
# Define the environment for cross compiling from Linux to Win32
|
||||
SET(CMAKE_SYSTEM_NAME Windows) # Target system name
|
||||
SET(CMAKE_SYSTEM_VERSION 1)
|
||||
SET(CMAKE_C_COMPILER "i686-w64-mingw32-gcc")
|
||||
SET(CMAKE_CXX_COMPILER "i686-w64-mingw32-g++")
|
||||
SET(CMAKE_RC_COMPILER "i686-w64-mingw32-windres")
|
||||
SET(CMAKE_RANLIB "i686-w64-mingw32-ranlib")
|
||||
|
||||
# Configure the behaviour of the find commands
|
||||
SET(CMAKE_FIND_ROOT_PATH "/usr/i686-w64-mingw32")
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
|
@ -0,0 +1,34 @@
|
|||
# FindMir
|
||||
# -------
|
||||
# Finds the Mir library
|
||||
#
|
||||
# This will will define the following variables::
|
||||
#
|
||||
# MIR_FOUND - the system has Mir
|
||||
# MIR_INCLUDE_DIRS - the Mir include directory
|
||||
# MIR_LIBRARIES - the Mir libraries
|
||||
# MIR_DEFINITIONS - the Mir definitions
|
||||
|
||||
|
||||
find_package (PkgConfig)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_check_modules (PC_MIR mirclient>=0.26.2 QUIET)
|
||||
|
||||
find_path(MIR_INCLUDE_DIR NAMES mir_toolkit/mir_client_library.h
|
||||
PATHS ${PC_MIR_INCLUDE_DIRS})
|
||||
|
||||
find_library(MIR_LIBRARY NAMES mirclient
|
||||
PATHS ${PC_MIR_LIBRARIES} ${PC_MIR_LIBRARY_DIRS})
|
||||
|
||||
include (FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args (MIR
|
||||
REQUIRED_VARS MIR_LIBRARY MIR_INCLUDE_DIR)
|
||||
|
||||
if (MIR_FOUND)
|
||||
set(MIR_LIBRARIES ${MIR_LIBRARY})
|
||||
set(MIR_INCLUDE_DIRS ${PC_MIR_INCLUDE_DIRS})
|
||||
set(MIR_DEFINITIONS -DHAVE_MIR=1)
|
||||
endif()
|
||||
|
||||
mark_as_advanced (MIR_LIBRARY MIR_INCLUDE_DIR)
|
||||
endif()
|
|
@ -0,0 +1,18 @@
|
|||
# Try to find OSMesa on a Unix system
|
||||
#
|
||||
# This will define:
|
||||
#
|
||||
# OSMESA_LIBRARIES - Link these to use OSMesa
|
||||
# OSMESA_INCLUDE_DIR - Include directory for OSMesa
|
||||
#
|
||||
# Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||
|
||||
if (NOT WIN32)
|
||||
|
||||
find_package (PkgConfig)
|
||||
pkg_check_modules (PKG_OSMESA QUIET osmesa)
|
||||
|
||||
set (OSMESA_INCLUDE_DIR ${PKG_OSMESA_INCLUDE_DIRS})
|
||||
set (OSMESA_LIBRARIES ${PKG_OSMESA_LIBRARIES})
|
||||
|
||||
endif ()
|
|
@ -0,0 +1,48 @@
|
|||
# Find Vulkan
|
||||
#
|
||||
# VULKAN_INCLUDE_DIR
|
||||
# VULKAN_LIBRARY
|
||||
# VULKAN_FOUND
|
||||
|
||||
if (WIN32)
|
||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||
"$ENV{VULKAN_SDK}/Include"
|
||||
"$ENV{VK_SDK_PATH}/Include")
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
find_library(VULKAN_LIBRARY NAMES vulkan-1 HINTS
|
||||
"$ENV{VULKAN_SDK}/Lib"
|
||||
"$ENV{VULKAN_SDK}/Bin"
|
||||
"$ENV{VK_SDK_PATH}/Bin")
|
||||
find_library(VULKAN_STATIC_LIBRARY NAMES vkstatic.1 HINTS
|
||||
"$ENV{VULKAN_SDK}/Lib"
|
||||
"$ENV{VULKAN_SDK}/Bin"
|
||||
"$ENV{VK_SDK_PATH}/Bin")
|
||||
else()
|
||||
find_library(VULKAN_LIBRARY NAMES vulkan-1 HINTS
|
||||
"$ENV{VULKAN_SDK}/Lib32"
|
||||
"$ENV{VULKAN_SDK}/Bin32"
|
||||
"$ENV{VK_SDK_PATH}/Bin32")
|
||||
find_library(VULKAN_STATIC_LIBRARY NAMES vkstatic.1 HINTS
|
||||
"$ENV{VULKAN_SDK}/Lib32"
|
||||
"$ENV{VULKAN_SDK}/Bin32"
|
||||
"$ENV{VK_SDK_PATH}/Bin32")
|
||||
endif()
|
||||
elseif (APPLE)
|
||||
find_library(VULKAN_LIBRARY MoltenVK)
|
||||
if (VULKAN_LIBRARY)
|
||||
set(VULKAN_STATIC_LIBRARY ${VULKAN_LIBRARY})
|
||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||
"${VULKAN_LIBRARY}/Headers")
|
||||
endif()
|
||||
else()
|
||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||
"$ENV{VULKAN_SDK}/include")
|
||||
find_library(VULKAN_LIBRARY NAMES vulkan HINTS
|
||||
"$ENV{VULKAN_SDK}/lib")
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Vulkan DEFAULT_MSG VULKAN_LIBRARY VULKAN_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced(VULKAN_INCLUDE_DIR VULKAN_LIBRARY VULKAN_STATIC_LIBRARY)
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
find_package(PkgConfig)
|
||||
|
||||
pkg_check_modules(WaylandProtocols QUIET wayland-protocols>=${WaylandProtocols_FIND_VERSION})
|
||||
|
||||
execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-protocols
|
||||
OUTPUT_VARIABLE WaylandProtocols_PKGDATADIR
|
||||
RESULT_VARIABLE _pkgconfig_failed)
|
||||
if (_pkgconfig_failed)
|
||||
message(FATAL_ERROR "Missing wayland-protocols pkgdatadir")
|
||||
endif()
|
||||
|
||||
string(REGEX REPLACE "[\r\n]" "" WaylandProtocols_PKGDATADIR "${WaylandProtocols_PKGDATADIR}")
|
||||
|
||||
find_package_handle_standard_args(WaylandProtocols
|
||||
FOUND_VAR
|
||||
WaylandProtocols_FOUND
|
||||
REQUIRED_VARS
|
||||
WaylandProtocols_PKGDATADIR
|
||||
VERSION_VAR
|
||||
WaylandProtocols_VERSION
|
||||
HANDLE_COMPONENTS
|
||||
)
|
||||
|
||||
set(WAYLAND_PROTOCOLS_FOUND ${WaylandProtocols_FOUND})
|
||||
set(WAYLAND_PROTOCOLS_PKGDATADIR ${WaylandProtocols_PKGDATADIR})
|
||||
set(WAYLAND_PROTOCOLS_VERSION ${WaylandProtocols_VERSION})
|
|
@ -0,0 +1,34 @@
|
|||
# - Try to find XKBCommon
|
||||
# Once done, this will define
|
||||
#
|
||||
# XKBCOMMON_FOUND - System has XKBCommon
|
||||
# XKBCOMMON_INCLUDE_DIRS - The XKBCommon include directories
|
||||
# XKBCOMMON_LIBRARIES - The libraries needed to use XKBCommon
|
||||
# XKBCOMMON_DEFINITIONS - Compiler switches required for using XKBCommon
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_XKBCOMMON QUIET xkbcommon)
|
||||
set(XKBCOMMON_DEFINITIONS ${PC_XKBCOMMON_CFLAGS_OTHER})
|
||||
|
||||
find_path(XKBCOMMON_INCLUDE_DIR
|
||||
NAMES xkbcommon/xkbcommon.h
|
||||
HINTS ${PC_XKBCOMMON_INCLUDE_DIR} ${PC_XKBCOMMON_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(XKBCOMMON_LIBRARY
|
||||
NAMES xkbcommon
|
||||
HINTS ${PC_XKBCOMMON_LIBRARY} ${PC_XKBCOMMON_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
set(XKBCOMMON_LIBRARIES ${XKBCOMMON_LIBRARY})
|
||||
set(XKBCOMMON_LIBRARY_DIRS ${XKBCOMMON_LIBRARY_DIRS})
|
||||
set(XKBCOMMON_INCLUDE_DIRS ${XKBCOMMON_INCLUDE_DIR})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(XKBCommon DEFAULT_MSG
|
||||
XKBCOMMON_LIBRARY
|
||||
XKBCOMMON_INCLUDE_DIR
|
||||
)
|
||||
|
||||
mark_as_advanced(XKBCOMMON_LIBRARY XKBCOMMON_INCLUDE_DIR)
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# Define the environment for cross compiling from Linux to Win32
|
||||
SET(CMAKE_SYSTEM_NAME Windows) # Target system name
|
||||
SET(CMAKE_SYSTEM_VERSION 1)
|
||||
SET(CMAKE_C_COMPILER "x86_64-w64-mingw32-gcc")
|
||||
SET(CMAKE_CXX_COMPILER "x86_64-w64-mingw32-g++")
|
||||
SET(CMAKE_RC_COMPILER "x86_64-w64-mingw32-windres")
|
||||
SET(CMAKE_RANLIB "x86_64-w64-mingw32-ranlib")
|
||||
|
||||
# Configure the behaviour of the find commands
|
||||
SET(CMAKE_FIND_ROOT_PATH "/usr/x86_64-w64-mingw32")
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
|
@ -0,0 +1,418 @@
|
|||
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
|
||||
|
||||
project(GLFW C)
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
if (NOT CMAKE_VERSION VERSION_LESS "3.0")
|
||||
# Until all major package systems have moved to CMake 3,
|
||||
# we stick with the older INSTALL_NAME_DIR mechanism
|
||||
cmake_policy(SET CMP0042 OLD)
|
||||
endif()
|
||||
|
||||
if (NOT CMAKE_VERSION VERSION_LESS "3.1")
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
endif()
|
||||
|
||||
set(GLFW_VERSION_MAJOR "3")
|
||||
set(GLFW_VERSION_MINOR "3")
|
||||
set(GLFW_VERSION_PATCH "0")
|
||||
set(GLFW_VERSION_EXTRA "")
|
||||
set(GLFW_VERSION "${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}")
|
||||
set(GLFW_VERSION_FULL "${GLFW_VERSION}.${GLFW_VERSION_PATCH}${GLFW_VERSION_EXTRA}")
|
||||
set(LIB_SUFFIX "" CACHE STRING "Takes an empty string or 64. Directory where lib will be installed: lib or lib64")
|
||||
|
||||
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 "Use the Vulkan loader statically linked into application" OFF)
|
||||
option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF)
|
||||
|
||||
if (UNIX)
|
||||
option(GLFW_USE_OSMESA "Use OSMesa for offscreen context creation" OFF)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF)
|
||||
endif()
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
|
||||
option(GLFW_USE_MIR "Use Mir for window creation" OFF)
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
option(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC runtime library DLL" ON)
|
||||
endif()
|
||||
|
||||
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)
|
||||
set(_GLFW_VULKAN_STATIC 1)
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules")
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(Vulkan)
|
||||
|
||||
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 SDK not found")
|
||||
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()
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
# Dependencies required by the MoltenVK static library
|
||||
set(GLFW_VULKAN_DEPS
|
||||
"-lc++"
|
||||
"-framework Cocoa"
|
||||
"-framework Metal"
|
||||
"-framework QuartzCore")
|
||||
endif()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Detect and select backend APIs
|
||||
#--------------------------------------------------------------------
|
||||
if (GLFW_USE_WAYLAND)
|
||||
set(_GLFW_WAYLAND 1)
|
||||
message(STATUS "Using Wayland for window creation")
|
||||
elseif (GLFW_USE_MIR)
|
||||
set(_GLFW_MIR 1)
|
||||
message(STATUS "Using Mir 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()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Add Vulkan static library if requested
|
||||
#--------------------------------------------------------------------
|
||||
if (GLFW_VULKAN_STATIC)
|
||||
if (VULKAN_FOUND AND VULKAN_STATIC_LIBRARY)
|
||||
list(APPEND glfw_LIBRARIES ${VULKAN_STATIC_LIBRARY} ${GLFW_VULKAN_DEPS})
|
||||
if (BUILD_SHARED_LIBS)
|
||||
message(WARNING "Linking Vulkan loader static library into GLFW")
|
||||
endif()
|
||||
else()
|
||||
if (BUILD_SHARED_LIBS OR GLFW_BUILD_EXAMPLES OR GLFW_BUILD_TESTS)
|
||||
message(FATAL_ERROR "Vulkan loader static library not found")
|
||||
else()
|
||||
message(WARNING "Vulkan loader static library not found")
|
||||
endif()
|
||||
endif()
|
||||
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_FOUND)
|
||||
message(FATAL_ERROR "The RandR library and headers were not found")
|
||||
endif()
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIRS "${X11_Xrandr_INCLUDE_PATH}")
|
||||
list(APPEND glfw_LIBRARIES "${X11_Xrandr_LIB}")
|
||||
list(APPEND glfw_PKG_DEPS "xrandr")
|
||||
|
||||
# Check for Xinerama (legacy multi-monitor support)
|
||||
if (NOT X11_Xinerama_FOUND)
|
||||
message(FATAL_ERROR "The Xinerama library and headers were not found")
|
||||
endif()
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIRS "${X11_Xinerama_INCLUDE_PATH}")
|
||||
list(APPEND glfw_LIBRARIES "${X11_Xinerama_LIB}")
|
||||
list(APPEND glfw_PKG_DEPS "xinerama")
|
||||
|
||||
# Check for Xkb (X keyboard extension)
|
||||
if (NOT X11_Xkb_FOUND)
|
||||
message(FATAL_ERROR "The X keyboard extension headers were not found")
|
||||
endif()
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIR "${X11_Xkb_INCLUDE_PATH}")
|
||||
|
||||
# Check for Xcursor
|
||||
if (NOT X11_Xcursor_FOUND)
|
||||
message(FATAL_ERROR "The Xcursor libraries and headers were not found")
|
||||
endif()
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIR "${X11_Xcursor_INCLUDE_PATH}")
|
||||
list(APPEND glfw_LIBRARIES "${X11_Xcursor_LIB}")
|
||||
list(APPEND glfw_PKG_DEPS "xcursor")
|
||||
|
||||
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)
|
||||
find_package(WaylandScanner REQUIRED)
|
||||
find_package(WaylandProtocols 1.1 REQUIRED)
|
||||
|
||||
list(APPEND glfw_PKG_DEPS "wayland-egl")
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIRS "${Wayland_INCLUDE_DIR}")
|
||||
list(APPEND glfw_LIBRARIES "${Wayland_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}")
|
||||
|
||||
find_package(XKBCommon REQUIRED)
|
||||
list(APPEND glfw_PKG_DEPS "xkbcommon")
|
||||
list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
|
||||
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
|
||||
endif()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Use Mir for window creation
|
||||
#--------------------------------------------------------------------
|
||||
if (_GLFW_MIR)
|
||||
find_package(Mir REQUIRED)
|
||||
list(APPEND glfw_PKG_DEPS "mirclient")
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIRS "${MIR_INCLUDE_DIRS}")
|
||||
list(APPEND glfw_LIBRARIES "${MIR_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}")
|
||||
|
||||
find_package(XKBCommon REQUIRED)
|
||||
list(APPEND glfw_PKG_DEPS "xkbcommon")
|
||||
list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
|
||||
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
|
||||
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"
|
||||
"-framework CoreVideo")
|
||||
|
||||
set(glfw_PKG_DEPS "")
|
||||
set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation -framework CoreVideo")
|
||||
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 "lib${LIB_SUFFIX}/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_FULL}
|
||||
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 include
|
||||
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 "lib${LIB_SUFFIX}/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")
|
||||
endif()
|
||||
endif()
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
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.
|
||||
|
|
@ -0,0 +1,353 @@
|
|||
# GLFW
|
||||
|
||||
[](https://travis-ci.org/glfw/glfw)
|
||||
[](https://ci.appveyor.com/project/elmindreda/glfw)
|
||||
[](https://scan.coverity.com/projects/glfw-glfw)
|
||||
|
||||
## Introduction
|
||||
|
||||
GLFW is an Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan
|
||||
application development. It provides a simple, platform-independent API for
|
||||
creating windows, contexts and surfaces, reading input, handling events, etc.
|
||||
|
||||
GLFW natively supports Windows, macOS and Linux and other Unix-like systems.
|
||||
Experimental implementations for the Wayland protocol and the Mir display server
|
||||
are available but not yet officially supported.
|
||||
|
||||
GLFW is licensed under the [zlib/libpng
|
||||
license](http://www.glfw.org/license.html).
|
||||
|
||||
The latest stable release is version 3.2.1.
|
||||
|
||||
See the [downloads](http://www.glfw.org/download.html) page for details and
|
||||
files, or fetch the `latest` branch, which always points to the latest stable
|
||||
release. Each release starting with 3.0 also has a corresponding [annotated
|
||||
tag](https://github.com/glfw/glfw/releases) with source and binary archives.
|
||||
The [version history](http://www.glfw.org/changelog.html) lists all user-visible
|
||||
changes for every release.
|
||||
|
||||
This is a development branch for version 3.3, which is _not yet described_.
|
||||
Pre-release documentation is available [here](http://www.glfw.org/docs/3.3/).
|
||||
|
||||
The `master` branch is the stable integration branch and _should_ always compile
|
||||
and run on all supported platforms, although details of newly added features may
|
||||
change until they have been included in a release. New features and many bug
|
||||
fixes live in [other branches](https://github.com/glfw/glfw/branches/all) until
|
||||
they are stable enough to merge.
|
||||
|
||||
If you are new to GLFW, you may find the
|
||||
[tutorial](http://www.glfw.org/docs/latest/quick.html) for GLFW
|
||||
3 useful. If you have used GLFW 2 in the past, there is a
|
||||
[transition guide](http://www.glfw.org/docs/latest/moving.html) for moving to
|
||||
the GLFW 3 API.
|
||||
|
||||
|
||||
## Compiling GLFW
|
||||
|
||||
GLFW itself requires only the headers and libraries for your window system. It
|
||||
does not need the headers for any context creation API (WGL, GLX, EGL, NSGL) or
|
||||
rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them.
|
||||
|
||||
GLFW supports compilation on Windows with Visual C++ 2010 and later, MinGW and
|
||||
MinGW-w64, on macOS with Clang and on Linux and other Unix-like systems with GCC
|
||||
and Clang. It will likely compile in other environments as well, but this is
|
||||
not regularly tested.
|
||||
|
||||
There are also [pre-compiled Windows
|
||||
binaries](http://www.glfw.org/download.html) available for all compilers
|
||||
supported on that platform.
|
||||
|
||||
See the [compilation guide](http://www.glfw.org/docs/latest/compile.html) for
|
||||
more information about how to compile GLFW.
|
||||
|
||||
|
||||
## Using GLFW
|
||||
|
||||
See the [documentation](http://www.glfw.org/docs/latest/) for tutorials, guides
|
||||
and the API reference.
|
||||
|
||||
|
||||
## Contributing to GLFW
|
||||
|
||||
See the [contribution
|
||||
guide](https://github.com/glfw/glfw/blob/master/.github/CONTRIBUTING.md) for
|
||||
more information.
|
||||
|
||||
|
||||
## System requirements
|
||||
|
||||
GLFW supports Windows XP and later and macOS 10.7 and later. Linux and other
|
||||
Unix-like systems running the X Window System are supported even without
|
||||
a desktop environment or modern extensions, although some features require
|
||||
a running window or clipboard manager. The OSMesa backend requires Mesa 6.3.
|
||||
|
||||
See the [compatibility guide](http://www.glfw.org/docs/latest/compat.html)
|
||||
in the documentation for more information.
|
||||
|
||||
|
||||
## Dependencies
|
||||
|
||||
GLFW itself depends only on the headers and libraries for your window system.
|
||||
|
||||
The examples and test programs depend on a number of tiny libraries. These are
|
||||
located in the `deps/` directory.
|
||||
|
||||
- [getopt\_port](https://github.com/kimgr/getopt_port/) for examples
|
||||
with command-line options
|
||||
- [TinyCThread](https://github.com/tinycthread/tinycthread) for threaded
|
||||
examples
|
||||
- An OpenGL 3.2 core loader generated by
|
||||
[glad](https://github.com/Dav1dde/glad) for examples using modern OpenGL
|
||||
- [linmath.h](https://github.com/datenwolf/linmath.h) for linear algebra in
|
||||
examples
|
||||
- [Nuklear](https://github.com/vurtun/nuklear) for test and example UI
|
||||
- [stb\_image\_write](https://github.com/nothings/stb) for writing images to disk
|
||||
- [Vulkan headers](https://www.khronos.org/registry/vulkan/) for Vulkan tests
|
||||
|
||||
The Vulkan example additionally requires the Vulkan SDK to be installed, or it
|
||||
will not be included in the build. On macOS you need to set the path to the
|
||||
MoltenVK SDK manually as it has no standard location.
|
||||
|
||||
The documentation is generated with [Doxygen](http://doxygen.org/). If CMake
|
||||
does not find Doxygen, the documentation will not be generated when you build.
|
||||
|
||||
|
||||
## Reporting bugs
|
||||
|
||||
Bugs are reported to our [issue tracker](https://github.com/glfw/glfw/issues).
|
||||
Please check the [contribution
|
||||
guide](https://github.com/glfw/glfw/blob/master/.github/CONTRIBUTING.md) for
|
||||
information on what to include when reporting a bug.
|
||||
|
||||
|
||||
## Changelog
|
||||
|
||||
- Added `glfwGetError` function for querying the last error code (#970)
|
||||
- Added `glfwGetKeyScancode` function that allows retrieving platform dependent
|
||||
scancodes for keys (#830)
|
||||
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
|
||||
receiving window maximization events (#778)
|
||||
- Added `glfwSetWindowAttrib` function for changing window attributes (#537)
|
||||
- Added `glfwGetJoystickHats` function for querying joystick hats
|
||||
(#889,#906,#934)
|
||||
- Added `glfwInitHint` function for setting library initialization hints
|
||||
- Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#850)
|
||||
- Added definition of `GLAPIENTRY` to public header
|
||||
- Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering
|
||||
(#749,#842)
|
||||
- Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889)
|
||||
- Added macOS specific `GLFW_COCOA_RETINA_FRAMEBUFFER` window hint
|
||||
- Added macOS specific `GLFW_COCOA_FRAME_AUTOSAVE` window hint (#195)
|
||||
- Added macOS specific `GLFW_COCOA_GRAPHICS_SWITCHING` window hint (#377,#935)
|
||||
- Added macOS specific `GLFW_COCOA_CHDIR_RESOURCES` init hint
|
||||
- Added macOS specific `GLFW_COCOA_MENUBAR` init hint
|
||||
- Added `GLFW_INCLUDE_ES32` for including the OpenGL ES 3.2 header
|
||||
- Added `GLFW_OSMESA_CONTEXT_API` for creating OpenGL contexts with
|
||||
[OSMesa](https://www.mesa3d.org/osmesa.html) (#281)
|
||||
- Removed `GLFW_USE_RETINA` compile-time option
|
||||
- Removed `GLFW_USE_CHDIR` compile-time option
|
||||
- Removed `GLFW_USE_MENUBAR` compile-time option
|
||||
- Bugfix: Calling `glfwMaximizeWindow` on a full screen window was not ignored
|
||||
- Bugfix: `GLFW_INCLUDE_VULKAN` could not be combined with the corresponding
|
||||
OpenGL and OpenGL ES header macros
|
||||
- Bugfix: `glfwGetInstanceProcAddress` returned `NULL` for
|
||||
`vkGetInstanceProcAddr` when `_GLFW_VULKAN_STATIC` was enabled
|
||||
- Bugfix: Invalid library paths were used in test and example CMake files (#930)
|
||||
- Bugfix: The scancode for synthetic key release events was always zero
|
||||
- [Win32] Added system error strings to relevant GLFW error descriptions (#733)
|
||||
- [Win32] Moved to `WM_INPUT` for disabled cursor mode motion input (#125)
|
||||
- [Win32] Bugfix: Undecorated windows could not be iconified by the user (#861)
|
||||
- [Win32] Bugfix: Deadzone logic could underflow with some controllers (#910)
|
||||
- [Win32] Bugfix: Bitness test in `FindVulkan.cmake` was VS specific (#928)
|
||||
- [Win32] Bugfix: `glfwVulkanSupported` emitted an error on systems with
|
||||
a loader but no ICD (#916)
|
||||
- [Win32] Bugfix: Non-iconified full sreeen windows did not prevent screen
|
||||
blanking or password enabled screensavers (#851)
|
||||
- [Win32] Bugfix: Mouse capture logic lost secondary release messages (#954)
|
||||
- [Win32] Bugfix: The 32-bit Vulkan loader library static was not searched for
|
||||
- [Win32] Bugfix: Vulkan libraries have a new path as of SDK 1.0.42.0 (#956)
|
||||
- [Win32] Bugfix: Monitors with no display devices were not enumerated (#960)
|
||||
- [Win32] Bugfix: Monitor events were not emitted (#784)
|
||||
- [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125)
|
||||
- [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading
|
||||
- [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X
|
||||
- [X11] Bugfix: Dynamic X11 library loading did not use full sonames (#941)
|
||||
- [X11] Bugfix: Window creation on 64-bit would read past top of stack (#951)
|
||||
- [X11] Bugfix: XDND support had multiple non-conformance issues (#968)
|
||||
- [X11] Bugfix: The RandR monitor path was disabled despite working RandR (#972)
|
||||
- [X11] Bugfix: IM-duplicated key events would leak at low polling rates (#747)
|
||||
- [X11] Bugfix: Gamma ramp setting via RandR did not validate ramp size
|
||||
- [Linux] Bugfix: Event processing did not detect joystick disconnection (#932)
|
||||
- [Cocoa] Added support for Vulkan window surface creation via
|
||||
[MoltenVK](https://moltengl.com/moltenvk/) (#870)
|
||||
- [Cocoa] Added support for loading a `MainMenu.nib` when available
|
||||
- [Cocoa] Bugfix: Disabling window aspect ratio would assert (#852)
|
||||
- [Cocoa] Bugfix: Window creation failed to set first responder (#876,#883)
|
||||
- [Cocoa] Bugfix: Removed use of deprecated `CGDisplayIOServicePort` function
|
||||
(#165,#192,#508,#511)
|
||||
- [Cocoa] Bugfix: Disabled use of deprecated `CGDisplayModeCopyPixelEncoding`
|
||||
function on macOS 10.12+
|
||||
- [Cocoa] Bugfix: Running in AppSandbox would emit warnings (#816,#882)
|
||||
- [Cocoa] Bugfix: Windows created after the first were not cascaded (#195)
|
||||
- [Cocoa] Bugfix: Leaving video mode with `glfwSetWindowMonitor` would set
|
||||
incorrect position and size (#748)
|
||||
- [Cocoa] Bugfix: Iconified full screen windows could not be restored (#848)
|
||||
- [Cocoa] Bugfix: Value range was ignored for joystick hats and buttons (#888)
|
||||
- [Cocoa] Bugfix: Full screen framebuffer was incorrectly sized for some video
|
||||
modes (#682)
|
||||
- [EGL] Added support for `EGL_KHR_get_all_proc_addresses` (#871)
|
||||
- [EGL] Added support for `EGL_KHR_context_flush_control`
|
||||
- [EGL] Bugfix: The test for `EGL_RGB_BUFFER` was invalid
|
||||
|
||||
|
||||
## Contact
|
||||
|
||||
On [glfw.org](http://www.glfw.org/) you can find the latest version of GLFW, as
|
||||
well as news, documentation and other information about the project.
|
||||
|
||||
If you have questions related to the use of GLFW, we have a
|
||||
[forum](http://discourse.glfw.org/), and the `#glfw` IRC channel on
|
||||
[Freenode](http://freenode.net/).
|
||||
|
||||
If you have a bug to report, a patch to submit or a feature you'd like to
|
||||
request, please file it in the
|
||||
[issue tracker](https://github.com/glfw/glfw/issues) on GitHub.
|
||||
|
||||
Finally, if you're interested in helping out with the development of GLFW or
|
||||
porting it to your favorite platform, join us on the forum, GitHub or IRC.
|
||||
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
GLFW exists because people around the world donated their time and lent their
|
||||
skills.
|
||||
|
||||
- Bobyshev Alexander
|
||||
- artblanc
|
||||
- arturo
|
||||
- Matt Arsenault
|
||||
- Keith Bauer
|
||||
- John Bartholomew
|
||||
- Niklas Behrens
|
||||
- Niklas Bergström
|
||||
- Doug Binks
|
||||
- blanco
|
||||
- Kyle Brenneman
|
||||
- Martin Capitanio
|
||||
- Chi-kwan Chan
|
||||
- Lambert Clara
|
||||
- Andrew Corrigan
|
||||
- Noel Cower
|
||||
- Jason Daly
|
||||
- Jarrod Davis
|
||||
- Olivier Delannoy
|
||||
- Paul R. Deppe
|
||||
- Michael Dickens
|
||||
- Роман Донченко
|
||||
- Mario Dorn
|
||||
- Jonathan Dummer
|
||||
- Ralph Eastwood
|
||||
- Siavash Eliasi
|
||||
- Michael Fogleman
|
||||
- Gerald Franz
|
||||
- Mário Freitas
|
||||
- GeO4d
|
||||
- Marcus Geelnard
|
||||
- Eloi Marín Gratacós
|
||||
- Stefan Gustavson
|
||||
- Sylvain Hellegouarch
|
||||
- Matthew Henry
|
||||
- heromyth
|
||||
- Lucas Hinderberger
|
||||
- Paul Holden
|
||||
- Warren Hu
|
||||
- IntellectualKitty
|
||||
- Aaron Jacobs
|
||||
- Erik S. V. Jansson
|
||||
- Toni Jovanoski
|
||||
- Arseny Kapoulkine
|
||||
- Osman Keskin
|
||||
- Cameron King
|
||||
- Peter Knut
|
||||
- Christoph Kubisch
|
||||
- Konstantin Käfer
|
||||
- Eric Larson
|
||||
- Robin Leffmann
|
||||
- Glenn Lewis
|
||||
- Shane Liesegang
|
||||
- Eyal Lotem
|
||||
- Дмитри Малышев
|
||||
- Martins Mozeiko
|
||||
- Tristam MacDonald
|
||||
- Hans Mackowiak
|
||||
- Zbigniew Mandziejewicz
|
||||
- Kyle McDonald
|
||||
- David Medlock
|
||||
- Bryce Mehring
|
||||
- Jonathan Mercier
|
||||
- Marcel Metz
|
||||
- Liam Middlebrook
|
||||
- Jonathan Miller
|
||||
- Kenneth Miller
|
||||
- Bruce Mitchener
|
||||
- Jack Moffitt
|
||||
- Jeff Molofee
|
||||
- Jon Morton
|
||||
- Pierre Moulon
|
||||
- Julian Møller
|
||||
- Kamil Nowakowski
|
||||
- Ozzy
|
||||
- Andri Pálsson
|
||||
- Peoro
|
||||
- Braden Pellett
|
||||
- Arturo J. Pérez
|
||||
- Orson Peters
|
||||
- Emmanuel Gil Peyrot
|
||||
- Cyril Pichard
|
||||
- Pieroman
|
||||
- Philip Rideout
|
||||
- Jorge Rodriguez
|
||||
- Ed Ropple
|
||||
- Aleksey Rybalkin
|
||||
- Riku Salminen
|
||||
- Brandon Schaefer
|
||||
- Sebastian Schuberth
|
||||
- Matt Sealey
|
||||
- SephiRok
|
||||
- Steve Sexton
|
||||
- Systemcluster
|
||||
- Yoshiki Shibukawa
|
||||
- Dmitri Shuralyov
|
||||
- Daniel Skorupski
|
||||
- Bradley Smith
|
||||
- Patrick Snape
|
||||
- Julian Squires
|
||||
- Johannes Stein
|
||||
- Michael Stocker
|
||||
- Justin Stoecker
|
||||
- Elviss Strazdins
|
||||
- Nathan Sweet
|
||||
- TTK-Bandit
|
||||
- Sergey Tikhomirov
|
||||
- Arthur Tombs
|
||||
- Ioannis Tsakpinis
|
||||
- Samuli Tuomola
|
||||
- Matthew Turner
|
||||
- urraka
|
||||
- Elias Vanderstuyft
|
||||
- Jari Vetoniemi
|
||||
- Ricardo Vieira
|
||||
- Nicholas Vitovitch
|
||||
- Simon Voordouw
|
||||
- Torsten Walluhn
|
||||
- Patrick Walton
|
||||
- Xo Wang
|
||||
- Jay Weisskopf
|
||||
- Frank Wille
|
||||
- yuriks
|
||||
- Santi Zupancic
|
||||
- Jonas Ådahl
|
||||
- Lasse Öörni
|
||||
- All the unmentioned and anonymous contributors in the GLFW community, for bug
|
||||
reports, patches, feedback, testing and encouragement
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
|
||||
endif()
|
||||
|
||||
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
|
||||
string(REGEX REPLACE "\n" ";" files "${files}")
|
||||
|
||||
foreach (file ${files})
|
||||
message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
|
||||
if (EXISTS "$ENV{DESTDIR}${file}")
|
||||
exec_program("@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||
OUTPUT_VARIABLE rm_out
|
||||
RETURN_VALUE rm_retval)
|
||||
if (NOT "${rm_retval}" STREQUAL 0)
|
||||
MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
|
||||
endif()
|
||||
elseif (IS_SYMLINK "$ENV{DESTDIR}${file}")
|
||||
EXEC_PROGRAM("@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||
OUTPUT_VARIABLE rm_out
|
||||
RETURN_VALUE rm_retval)
|
||||
if (NOT "${rm_retval}" STREQUAL 0)
|
||||
message(FATAL_ERROR "Problem when removing symlink \"$ENV{DESTDIR}${file}\"")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
|
||||
endif()
|
||||
endforeach()
|
||||
|
|
@ -0,0 +1,282 @@
|
|||
#ifndef __khrplatform_h_
|
||||
#define __khrplatform_h_
|
||||
|
||||
/*
|
||||
** Copyright (c) 2008-2009 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.
|
||||
*
|
||||
* $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $
|
||||
*
|
||||
* 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 sending them to the public Khronos Bugzilla
|
||||
* (http://khronos.org/bugzilla) by filing a bug against product
|
||||
* "Khronos (general)" component "Registry".
|
||||
*
|
||||
* A predefined template which fills in some of the bug fields can be
|
||||
* reached using http://tinyurl.com/khrplatform-h-bugreport, but you
|
||||
* must create a Bugzilla login first.
|
||||
*
|
||||
*
|
||||
* 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;
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Definition of KHRONOS_APICALL
|
||||
*-------------------------------------------------------------------------
|
||||
* This precedes the return type of the function in the function prototype.
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
|
||||
# define KHRONOS_APICALL __declspec(dllimport)
|
||||
#elif defined (__SYMBIAN32__)
|
||||
# define KHRONOS_APICALL IMPORT_C
|
||||
#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_ */
|
|
@ -0,0 +1,230 @@
|
|||
/* Copyright (c) 2012, Kim Gräsman
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* * Neither the name of Kim Gräsman nor the names of contributors may be used
|
||||
* to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL KIM GRÄSMAN BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
const int no_argument = 0;
|
||||
const int required_argument = 1;
|
||||
const int optional_argument = 2;
|
||||
|
||||
char* optarg;
|
||||
int optopt;
|
||||
/* The variable optind [...] shall be initialized to 1 by the system. */
|
||||
int optind = 1;
|
||||
int opterr;
|
||||
|
||||
static char* optcursor = NULL;
|
||||
|
||||
/* Implemented based on [1] and [2] for optional arguments.
|
||||
optopt is handled FreeBSD-style, per [3].
|
||||
Other GNU and FreeBSD extensions are purely accidental.
|
||||
|
||||
[1] http://pubs.opengroup.org/onlinepubs/000095399/functions/getopt.html
|
||||
[2] http://www.kernel.org/doc/man-pages/online/pages/man3/getopt.3.html
|
||||
[3] http://www.freebsd.org/cgi/man.cgi?query=getopt&sektion=3&manpath=FreeBSD+9.0-RELEASE
|
||||
*/
|
||||
int getopt(int argc, char* const argv[], const char* optstring) {
|
||||
int optchar = -1;
|
||||
const char* optdecl = NULL;
|
||||
|
||||
optarg = NULL;
|
||||
opterr = 0;
|
||||
optopt = 0;
|
||||
|
||||
/* Unspecified, but we need it to avoid overrunning the argv bounds. */
|
||||
if (optind >= argc)
|
||||
goto no_more_optchars;
|
||||
|
||||
/* If, when getopt() is called argv[optind] is a null pointer, getopt()
|
||||
shall return -1 without changing optind. */
|
||||
if (argv[optind] == NULL)
|
||||
goto no_more_optchars;
|
||||
|
||||
/* If, when getopt() is called *argv[optind] is not the character '-',
|
||||
getopt() shall return -1 without changing optind. */
|
||||
if (*argv[optind] != '-')
|
||||
goto no_more_optchars;
|
||||
|
||||
/* If, when getopt() is called argv[optind] points to the string "-",
|
||||
getopt() shall return -1 without changing optind. */
|
||||
if (strcmp(argv[optind], "-") == 0)
|
||||
goto no_more_optchars;
|
||||
|
||||
/* If, when getopt() is called argv[optind] points to the string "--",
|
||||
getopt() shall return -1 after incrementing optind. */
|
||||
if (strcmp(argv[optind], "--") == 0) {
|
||||
++optind;
|
||||
goto no_more_optchars;
|
||||
}
|
||||
|
||||
if (optcursor == NULL || *optcursor == '\0')
|
||||
optcursor = argv[optind] + 1;
|
||||
|
||||
optchar = *optcursor;
|
||||
|
||||
/* FreeBSD: The variable optopt saves the last known option character
|
||||
returned by getopt(). */
|
||||
optopt = optchar;
|
||||
|
||||
/* The getopt() function shall return the next option character (if one is
|
||||
found) from argv that matches a character in optstring, if there is
|
||||
one that matches. */
|
||||
optdecl = strchr(optstring, optchar);
|
||||
if (optdecl) {
|
||||
/* [I]f a character is followed by a colon, the option takes an
|
||||
argument. */
|
||||
if (optdecl[1] == ':') {
|
||||
optarg = ++optcursor;
|
||||
if (*optarg == '\0') {
|
||||
/* GNU extension: Two colons mean an option takes an
|
||||
optional arg; if there is text in the current argv-element
|
||||
(i.e., in the same word as the option name itself, for example,
|
||||
"-oarg"), then it is returned in optarg, otherwise optarg is set
|
||||
to zero. */
|
||||
if (optdecl[2] != ':') {
|
||||
/* If the option was the last character in the string pointed to by
|
||||
an element of argv, then optarg shall contain the next element
|
||||
of argv, and optind shall be incremented by 2. If the resulting
|
||||
value of optind is greater than argc, this indicates a missing
|
||||
option-argument, and getopt() shall return an error indication.
|
||||
|
||||
Otherwise, optarg shall point to the string following the
|
||||
option character in that element of argv, and optind shall be
|
||||
incremented by 1.
|
||||
*/
|
||||
if (++optind < argc) {
|
||||
optarg = argv[optind];
|
||||
} else {
|
||||
/* If it detects a missing option-argument, it shall return the
|
||||
colon character ( ':' ) if the first character of optstring
|
||||
was a colon, or a question-mark character ( '?' ) otherwise.
|
||||
*/
|
||||
optarg = NULL;
|
||||
optchar = (optstring[0] == ':') ? ':' : '?';
|
||||
}
|
||||
} else {
|
||||
optarg = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
optcursor = NULL;
|
||||
}
|
||||
} else {
|
||||
/* If getopt() encounters an option character that is not contained in
|
||||
optstring, it shall return the question-mark ( '?' ) character. */
|
||||
optchar = '?';
|
||||
}
|
||||
|
||||
if (optcursor == NULL || *++optcursor == '\0')
|
||||
++optind;
|
||||
|
||||
return optchar;
|
||||
|
||||
no_more_optchars:
|
||||
optcursor = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Implementation based on [1].
|
||||
|
||||
[1] http://www.kernel.org/doc/man-pages/online/pages/man3/getopt.3.html
|
||||
*/
|
||||
int getopt_long(int argc, char* const argv[], const char* optstring,
|
||||
const struct option* longopts, int* longindex) {
|
||||
const struct option* o = longopts;
|
||||
const struct option* match = NULL;
|
||||
int num_matches = 0;
|
||||
size_t argument_name_length = 0;
|
||||
const char* current_argument = NULL;
|
||||
int retval = -1;
|
||||
|
||||
optarg = NULL;
|
||||
optopt = 0;
|
||||
|
||||
if (optind >= argc)
|
||||
return -1;
|
||||
|
||||
if (strlen(argv[optind]) < 3 || strncmp(argv[optind], "--", 2) != 0)
|
||||
return getopt(argc, argv, optstring);
|
||||
|
||||
/* It's an option; starts with -- and is longer than two chars. */
|
||||
current_argument = argv[optind] + 2;
|
||||
argument_name_length = strcspn(current_argument, "=");
|
||||
for (; o->name; ++o) {
|
||||
if (strncmp(o->name, current_argument, argument_name_length) == 0) {
|
||||
match = o;
|
||||
++num_matches;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_matches == 1) {
|
||||
/* If longindex is not NULL, it points to a variable which is set to the
|
||||
index of the long option relative to longopts. */
|
||||
if (longindex)
|
||||
*longindex = (int) (match - longopts);
|
||||
|
||||
/* If flag is NULL, then getopt_long() shall return val.
|
||||
Otherwise, getopt_long() returns 0, and flag shall point to a variable
|
||||
which shall be set to val if the option is found, but left unchanged if
|
||||
the option is not found. */
|
||||
if (match->flag)
|
||||
*(match->flag) = match->val;
|
||||
|
||||
retval = match->flag ? 0 : match->val;
|
||||
|
||||
if (match->has_arg != no_argument) {
|
||||
optarg = strchr(argv[optind], '=');
|
||||
if (optarg != NULL)
|
||||
++optarg;
|
||||
|
||||
if (match->has_arg == required_argument) {
|
||||
/* Only scan the next argv for required arguments. Behavior is not
|
||||
specified, but has been observed with Ubuntu and Mac OSX. */
|
||||
if (optarg == NULL && ++optind < argc) {
|
||||
optarg = argv[optind];
|
||||
}
|
||||
|
||||
if (optarg == NULL)
|
||||
retval = ':';
|
||||
}
|
||||
} else if (strchr(argv[optind], '=')) {
|
||||
/* An argument was provided to a non-argument option.
|
||||
I haven't seen this specified explicitly, but both GNU and BSD-based
|
||||
implementations show this behavior.
|
||||
*/
|
||||
retval = '?';
|
||||
}
|
||||
} else {
|
||||
/* Unknown option or ambiguous match. */
|
||||
retval = '?';
|
||||
}
|
||||
|
||||
++optind;
|
||||
return retval;
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/* Copyright (c) 2012, Kim Gräsman
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* * Neither the name of Kim Gräsman nor the names of contributors may be used
|
||||
* to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL KIM GRÄSMAN BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_GETOPT_PORT_H
|
||||
#define INCLUDED_GETOPT_PORT_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const int no_argument;
|
||||
extern const int required_argument;
|
||||
extern const int optional_argument;
|
||||
|
||||
extern char* optarg;
|
||||
extern int optind, opterr, optopt;
|
||||
|
||||
struct option {
|
||||
const char* name;
|
||||
int has_arg;
|
||||
int* flag;
|
||||
int val;
|
||||
};
|
||||
|
||||
int getopt(int argc, char* const argv[], const char* optstring);
|
||||
|
||||
int getopt_long(int argc, char* const argv[],
|
||||
const char* optstring, const struct option* longopts, int* longindex);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // INCLUDED_GETOPT_PORT_H
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,574 @@
|
|||
#ifndef LINMATH_H
|
||||
#define LINMATH_H
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
#define LINMATH_H_DEFINE_VEC(n) \
|
||||
typedef float vec##n[n]; \
|
||||
static inline void vec##n##_add(vec##n r, vec##n const a, vec##n const b) \
|
||||
{ \
|
||||
int i; \
|
||||
for(i=0; i<n; ++i) \
|
||||
r[i] = a[i] + b[i]; \
|
||||
} \
|
||||
static inline void vec##n##_sub(vec##n r, vec##n const a, vec##n const b) \
|
||||
{ \
|
||||
int i; \
|
||||
for(i=0; i<n; ++i) \
|
||||
r[i] = a[i] - b[i]; \
|
||||
} \
|
||||
static inline void vec##n##_scale(vec##n r, vec##n const v, float const s) \
|
||||
{ \
|
||||
int i; \
|
||||
for(i=0; i<n; ++i) \
|
||||
r[i] = v[i] * s; \
|
||||
} \
|
||||
static inline float vec##n##_mul_inner(vec##n const a, vec##n const b) \
|
||||
{ \
|
||||
float p = 0.; \
|
||||
int i; \
|
||||
for(i=0; i<n; ++i) \
|
||||
p += b[i]*a[i]; \
|
||||
return p; \
|
||||
} \
|
||||
static inline float vec##n##_len(vec##n const v) \
|
||||
{ \
|
||||
return (float) sqrt(vec##n##_mul_inner(v,v)); \
|
||||
} \
|
||||
static inline void vec##n##_norm(vec##n r, vec##n const v) \
|
||||
{ \
|
||||
float k = 1.f / vec##n##_len(v); \
|
||||
vec##n##_scale(r, v, k); \
|
||||
}
|
||||
|
||||
LINMATH_H_DEFINE_VEC(2)
|
||||
LINMATH_H_DEFINE_VEC(3)
|
||||
LINMATH_H_DEFINE_VEC(4)
|
||||
|
||||
static inline void vec3_mul_cross(vec3 r, vec3 const a, vec3 const b)
|
||||
{
|
||||
r[0] = a[1]*b[2] - a[2]*b[1];
|
||||
r[1] = a[2]*b[0] - a[0]*b[2];
|
||||
r[2] = a[0]*b[1] - a[1]*b[0];
|
||||
}
|
||||
|
||||
static inline void vec3_reflect(vec3 r, vec3 const v, vec3 const n)
|
||||
{
|
||||
float p = 2.f*vec3_mul_inner(v, n);
|
||||
int i;
|
||||
for(i=0;i<3;++i)
|
||||
r[i] = v[i] - p*n[i];
|
||||
}
|
||||
|
||||
static inline void vec4_mul_cross(vec4 r, vec4 a, vec4 b)
|
||||
{
|
||||
r[0] = a[1]*b[2] - a[2]*b[1];
|
||||
r[1] = a[2]*b[0] - a[0]*b[2];
|
||||
r[2] = a[0]*b[1] - a[1]*b[0];
|
||||
r[3] = 1.f;
|
||||
}
|
||||
|
||||
static inline void vec4_reflect(vec4 r, vec4 v, vec4 n)
|
||||
{
|
||||
float p = 2.f*vec4_mul_inner(v, n);
|
||||
int i;
|
||||
for(i=0;i<4;++i)
|
||||
r[i] = v[i] - p*n[i];
|
||||
}
|
||||
|
||||
typedef vec4 mat4x4[4];
|
||||
static inline void mat4x4_identity(mat4x4 M)
|
||||
{
|
||||
int i, j;
|
||||
for(i=0; i<4; ++i)
|
||||
for(j=0; j<4; ++j)
|
||||
M[i][j] = i==j ? 1.f : 0.f;
|
||||
}
|
||||
static inline void mat4x4_dup(mat4x4 M, mat4x4 N)
|
||||
{
|
||||
int i, j;
|
||||
for(i=0; i<4; ++i)
|
||||
for(j=0; j<4; ++j)
|
||||
M[i][j] = N[i][j];
|
||||
}
|
||||
static inline void mat4x4_row(vec4 r, mat4x4 M, int i)
|
||||
{
|
||||
int k;
|
||||
for(k=0; k<4; ++k)
|
||||
r[k] = M[k][i];
|
||||
}
|
||||
static inline void mat4x4_col(vec4 r, mat4x4 M, int i)
|
||||
{
|
||||
int k;
|
||||
for(k=0; k<4; ++k)
|
||||
r[k] = M[i][k];
|
||||
}
|
||||
static inline void mat4x4_transpose(mat4x4 M, mat4x4 N)
|
||||
{
|
||||
int i, j;
|
||||
for(j=0; j<4; ++j)
|
||||
for(i=0; i<4; ++i)
|
||||
M[i][j] = N[j][i];
|
||||
}
|
||||
static inline void mat4x4_add(mat4x4 M, mat4x4 a, mat4x4 b)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<4; ++i)
|
||||
vec4_add(M[i], a[i], b[i]);
|
||||
}
|
||||
static inline void mat4x4_sub(mat4x4 M, mat4x4 a, mat4x4 b)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<4; ++i)
|
||||
vec4_sub(M[i], a[i], b[i]);
|
||||
}
|
||||
static inline void mat4x4_scale(mat4x4 M, mat4x4 a, float k)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<4; ++i)
|
||||
vec4_scale(M[i], a[i], k);
|
||||
}
|
||||
static inline void mat4x4_scale_aniso(mat4x4 M, mat4x4 a, float x, float y, float z)
|
||||
{
|
||||
int i;
|
||||
vec4_scale(M[0], a[0], x);
|
||||
vec4_scale(M[1], a[1], y);
|
||||
vec4_scale(M[2], a[2], z);
|
||||
for(i = 0; i < 4; ++i) {
|
||||
M[3][i] = a[3][i];
|
||||
}
|
||||
}
|
||||
static inline void mat4x4_mul(mat4x4 M, mat4x4 a, mat4x4 b)
|
||||
{
|
||||
mat4x4 temp;
|
||||
int k, r, c;
|
||||
for(c=0; c<4; ++c) for(r=0; r<4; ++r) {
|
||||
temp[c][r] = 0.f;
|
||||
for(k=0; k<4; ++k)
|
||||
temp[c][r] += a[k][r] * b[c][k];
|
||||
}
|
||||
mat4x4_dup(M, temp);
|
||||
}
|
||||
static inline void mat4x4_mul_vec4(vec4 r, mat4x4 M, vec4 v)
|
||||
{
|
||||
int i, j;
|
||||
for(j=0; j<4; ++j) {
|
||||
r[j] = 0.f;
|
||||
for(i=0; i<4; ++i)
|
||||
r[j] += M[i][j] * v[i];
|
||||
}
|
||||
}
|
||||
static inline void mat4x4_translate(mat4x4 T, float x, float y, float z)
|
||||
{
|
||||
mat4x4_identity(T);
|
||||
T[3][0] = x;
|
||||
T[3][1] = y;
|
||||
T[3][2] = z;
|
||||
}
|
||||
static inline void mat4x4_translate_in_place(mat4x4 M, float x, float y, float z)
|
||||
{
|
||||
vec4 t = {x, y, z, 0};
|
||||
vec4 r;
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
mat4x4_row(r, M, i);
|
||||
M[3][i] += vec4_mul_inner(r, t);
|
||||
}
|
||||
}
|
||||
static inline void mat4x4_from_vec3_mul_outer(mat4x4 M, vec3 a, vec3 b)
|
||||
{
|
||||
int i, j;
|
||||
for(i=0; i<4; ++i) for(j=0; j<4; ++j)
|
||||
M[i][j] = i<3 && j<3 ? a[i] * b[j] : 0.f;
|
||||
}
|
||||
static inline void mat4x4_rotate(mat4x4 R, mat4x4 M, float x, float y, float z, float angle)
|
||||
{
|
||||
float s = sinf(angle);
|
||||
float c = cosf(angle);
|
||||
vec3 u = {x, y, z};
|
||||
|
||||
if(vec3_len(u) > 1e-4) {
|
||||
mat4x4 T, C, S = {0};
|
||||
|
||||
vec3_norm(u, u);
|
||||
mat4x4_from_vec3_mul_outer(T, u, u);
|
||||
|
||||
S[1][2] = u[0];
|
||||
S[2][1] = -u[0];
|
||||
S[2][0] = u[1];
|
||||
S[0][2] = -u[1];
|
||||
S[0][1] = u[2];
|
||||
S[1][0] = -u[2];
|
||||
|
||||
mat4x4_scale(S, S, s);
|
||||
|
||||
mat4x4_identity(C);
|
||||
mat4x4_sub(C, C, T);
|
||||
|
||||
mat4x4_scale(C, C, c);
|
||||
|
||||
mat4x4_add(T, T, C);
|
||||
mat4x4_add(T, T, S);
|
||||
|
||||
T[3][3] = 1.;
|
||||
mat4x4_mul(R, M, T);
|
||||
} else {
|
||||
mat4x4_dup(R, M);
|
||||
}
|
||||
}
|
||||
static inline void mat4x4_rotate_X(mat4x4 Q, mat4x4 M, float angle)
|
||||
{
|
||||
float s = sinf(angle);
|
||||
float c = cosf(angle);
|
||||
mat4x4 R = {
|
||||
{1.f, 0.f, 0.f, 0.f},
|
||||
{0.f, c, s, 0.f},
|
||||
{0.f, -s, c, 0.f},
|
||||
{0.f, 0.f, 0.f, 1.f}
|
||||
};
|
||||
mat4x4_mul(Q, M, R);
|
||||
}
|
||||
static inline void mat4x4_rotate_Y(mat4x4 Q, mat4x4 M, float angle)
|
||||
{
|
||||
float s = sinf(angle);
|
||||
float c = cosf(angle);
|
||||
mat4x4 R = {
|
||||
{ c, 0.f, s, 0.f},
|
||||
{ 0.f, 1.f, 0.f, 0.f},
|
||||
{ -s, 0.f, c, 0.f},
|
||||
{ 0.f, 0.f, 0.f, 1.f}
|
||||
};
|
||||
mat4x4_mul(Q, M, R);
|
||||
}
|
||||
static inline void mat4x4_rotate_Z(mat4x4 Q, mat4x4 M, float angle)
|
||||
{
|
||||
float s = sinf(angle);
|
||||
float c = cosf(angle);
|
||||
mat4x4 R = {
|
||||
{ c, s, 0.f, 0.f},
|
||||
{ -s, c, 0.f, 0.f},
|
||||
{ 0.f, 0.f, 1.f, 0.f},
|
||||
{ 0.f, 0.f, 0.f, 1.f}
|
||||
};
|
||||
mat4x4_mul(Q, M, R);
|
||||
}
|
||||
static inline void mat4x4_invert(mat4x4 T, mat4x4 M)
|
||||
{
|
||||
float idet;
|
||||
float s[6];
|
||||
float c[6];
|
||||
s[0] = M[0][0]*M[1][1] - M[1][0]*M[0][1];
|
||||
s[1] = M[0][0]*M[1][2] - M[1][0]*M[0][2];
|
||||
s[2] = M[0][0]*M[1][3] - M[1][0]*M[0][3];
|
||||
s[3] = M[0][1]*M[1][2] - M[1][1]*M[0][2];
|
||||
s[4] = M[0][1]*M[1][3] - M[1][1]*M[0][3];
|
||||
s[5] = M[0][2]*M[1][3] - M[1][2]*M[0][3];
|
||||
|
||||
c[0] = M[2][0]*M[3][1] - M[3][0]*M[2][1];
|
||||
c[1] = M[2][0]*M[3][2] - M[3][0]*M[2][2];
|
||||
c[2] = M[2][0]*M[3][3] - M[3][0]*M[2][3];
|
||||
c[3] = M[2][1]*M[3][2] - M[3][1]*M[2][2];
|
||||
c[4] = M[2][1]*M[3][3] - M[3][1]*M[2][3];
|
||||
c[5] = M[2][2]*M[3][3] - M[3][2]*M[2][3];
|
||||
|
||||
/* Assumes it is invertible */
|
||||
idet = 1.0f/( s[0]*c[5]-s[1]*c[4]+s[2]*c[3]+s[3]*c[2]-s[4]*c[1]+s[5]*c[0] );
|
||||
|
||||
T[0][0] = ( M[1][1] * c[5] - M[1][2] * c[4] + M[1][3] * c[3]) * idet;
|
||||
T[0][1] = (-M[0][1] * c[5] + M[0][2] * c[4] - M[0][3] * c[3]) * idet;
|
||||
T[0][2] = ( M[3][1] * s[5] - M[3][2] * s[4] + M[3][3] * s[3]) * idet;
|
||||
T[0][3] = (-M[2][1] * s[5] + M[2][2] * s[4] - M[2][3] * s[3]) * idet;
|
||||
|
||||
T[1][0] = (-M[1][0] * c[5] + M[1][2] * c[2] - M[1][3] * c[1]) * idet;
|
||||
T[1][1] = ( M[0][0] * c[5] - M[0][2] * c[2] + M[0][3] * c[1]) * idet;
|
||||
T[1][2] = (-M[3][0] * s[5] + M[3][2] * s[2] - M[3][3] * s[1]) * idet;
|
||||
T[1][3] = ( M[2][0] * s[5] - M[2][2] * s[2] + M[2][3] * s[1]) * idet;
|
||||
|
||||
T[2][0] = ( M[1][0] * c[4] - M[1][1] * c[2] + M[1][3] * c[0]) * idet;
|
||||
T[2][1] = (-M[0][0] * c[4] + M[0][1] * c[2] - M[0][3] * c[0]) * idet;
|
||||
T[2][2] = ( M[3][0] * s[4] - M[3][1] * s[2] + M[3][3] * s[0]) * idet;
|
||||
T[2][3] = (-M[2][0] * s[4] + M[2][1] * s[2] - M[2][3] * s[0]) * idet;
|
||||
|
||||
T[3][0] = (-M[1][0] * c[3] + M[1][1] * c[1] - M[1][2] * c[0]) * idet;
|
||||
T[3][1] = ( M[0][0] * c[3] - M[0][1] * c[1] + M[0][2] * c[0]) * idet;
|
||||
T[3][2] = (-M[3][0] * s[3] + M[3][1] * s[1] - M[3][2] * s[0]) * idet;
|
||||
T[3][3] = ( M[2][0] * s[3] - M[2][1] * s[1] + M[2][2] * s[0]) * idet;
|
||||
}
|
||||
static inline void mat4x4_orthonormalize(mat4x4 R, mat4x4 M)
|
||||
{
|
||||
float s = 1.;
|
||||
vec3 h;
|
||||
|
||||
mat4x4_dup(R, M);
|
||||
vec3_norm(R[2], R[2]);
|
||||
|
||||
s = vec3_mul_inner(R[1], R[2]);
|
||||
vec3_scale(h, R[2], s);
|
||||
vec3_sub(R[1], R[1], h);
|
||||
vec3_norm(R[2], R[2]);
|
||||
|
||||
s = vec3_mul_inner(R[1], R[2]);
|
||||
vec3_scale(h, R[2], s);
|
||||
vec3_sub(R[1], R[1], h);
|
||||
vec3_norm(R[1], R[1]);
|
||||
|
||||
s = vec3_mul_inner(R[0], R[1]);
|
||||
vec3_scale(h, R[1], s);
|
||||
vec3_sub(R[0], R[0], h);
|
||||
vec3_norm(R[0], R[0]);
|
||||
}
|
||||
|
||||
static inline void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t, float n, float f)
|
||||
{
|
||||
M[0][0] = 2.f*n/(r-l);
|
||||
M[0][1] = M[0][2] = M[0][3] = 0.f;
|
||||
|
||||
M[1][1] = 2.f*n/(t-b);
|
||||
M[1][0] = M[1][2] = M[1][3] = 0.f;
|
||||
|
||||
M[2][0] = (r+l)/(r-l);
|
||||
M[2][1] = (t+b)/(t-b);
|
||||
M[2][2] = -(f+n)/(f-n);
|
||||
M[2][3] = -1.f;
|
||||
|
||||
M[3][2] = -2.f*(f*n)/(f-n);
|
||||
M[3][0] = M[3][1] = M[3][3] = 0.f;
|
||||
}
|
||||
static inline void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t, float n, float f)
|
||||
{
|
||||
M[0][0] = 2.f/(r-l);
|
||||
M[0][1] = M[0][2] = M[0][3] = 0.f;
|
||||
|
||||
M[1][1] = 2.f/(t-b);
|
||||
M[1][0] = M[1][2] = M[1][3] = 0.f;
|
||||
|
||||
M[2][2] = -2.f/(f-n);
|
||||
M[2][0] = M[2][1] = M[2][3] = 0.f;
|
||||
|
||||
M[3][0] = -(r+l)/(r-l);
|
||||
M[3][1] = -(t+b)/(t-b);
|
||||
M[3][2] = -(f+n)/(f-n);
|
||||
M[3][3] = 1.f;
|
||||
}
|
||||
static inline void mat4x4_perspective(mat4x4 m, float y_fov, float aspect, float n, float f)
|
||||
{
|
||||
/* NOTE: Degrees are an unhandy unit to work with.
|
||||
* linmath.h uses radians for everything! */
|
||||
float const a = 1.f / (float) tan(y_fov / 2.f);
|
||||
|
||||
m[0][0] = a / aspect;
|
||||
m[0][1] = 0.f;
|
||||
m[0][2] = 0.f;
|
||||
m[0][3] = 0.f;
|
||||
|
||||
m[1][0] = 0.f;
|
||||
m[1][1] = a;
|
||||
m[1][2] = 0.f;
|
||||
m[1][3] = 0.f;
|
||||
|
||||
m[2][0] = 0.f;
|
||||
m[2][1] = 0.f;
|
||||
m[2][2] = -((f + n) / (f - n));
|
||||
m[2][3] = -1.f;
|
||||
|
||||
m[3][0] = 0.f;
|
||||
m[3][1] = 0.f;
|
||||
m[3][2] = -((2.f * f * n) / (f - n));
|
||||
m[3][3] = 0.f;
|
||||
}
|
||||
static inline void mat4x4_look_at(mat4x4 m, vec3 eye, vec3 center, vec3 up)
|
||||
{
|
||||
/* Adapted from Android's OpenGL Matrix.java. */
|
||||
/* See the OpenGL GLUT documentation for gluLookAt for a description */
|
||||
/* of the algorithm. We implement it in a straightforward way: */
|
||||
|
||||
/* TODO: The negation of of can be spared by swapping the order of
|
||||
* operands in the following cross products in the right way. */
|
||||
vec3 f;
|
||||
vec3 s;
|
||||
vec3 t;
|
||||
|
||||
vec3_sub(f, center, eye);
|
||||
vec3_norm(f, f);
|
||||
|
||||
vec3_mul_cross(s, f, up);
|
||||
vec3_norm(s, s);
|
||||
|
||||
vec3_mul_cross(t, s, f);
|
||||
|
||||
m[0][0] = s[0];
|
||||
m[0][1] = t[0];
|
||||
m[0][2] = -f[0];
|
||||
m[0][3] = 0.f;
|
||||
|
||||
m[1][0] = s[1];
|
||||
m[1][1] = t[1];
|
||||
m[1][2] = -f[1];
|
||||
m[1][3] = 0.f;
|
||||
|
||||
m[2][0] = s[2];
|
||||
m[2][1] = t[2];
|
||||
m[2][2] = -f[2];
|
||||
m[2][3] = 0.f;
|
||||
|
||||
m[3][0] = 0.f;
|
||||
m[3][1] = 0.f;
|
||||
m[3][2] = 0.f;
|
||||
m[3][3] = 1.f;
|
||||
|
||||
mat4x4_translate_in_place(m, -eye[0], -eye[1], -eye[2]);
|
||||
}
|
||||
|
||||
typedef float quat[4];
|
||||
static inline void quat_identity(quat q)
|
||||
{
|
||||
q[0] = q[1] = q[2] = 0.f;
|
||||
q[3] = 1.f;
|
||||
}
|
||||
static inline void quat_add(quat r, quat a, quat b)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<4; ++i)
|
||||
r[i] = a[i] + b[i];
|
||||
}
|
||||
static inline void quat_sub(quat r, quat a, quat b)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<4; ++i)
|
||||
r[i] = a[i] - b[i];
|
||||
}
|
||||
static inline void quat_mul(quat r, quat p, quat q)
|
||||
{
|
||||
vec3 w;
|
||||
vec3_mul_cross(r, p, q);
|
||||
vec3_scale(w, p, q[3]);
|
||||
vec3_add(r, r, w);
|
||||
vec3_scale(w, q, p[3]);
|
||||
vec3_add(r, r, w);
|
||||
r[3] = p[3]*q[3] - vec3_mul_inner(p, q);
|
||||
}
|
||||
static inline void quat_scale(quat r, quat v, float s)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<4; ++i)
|
||||
r[i] = v[i] * s;
|
||||
}
|
||||
static inline float quat_inner_product(quat a, quat b)
|
||||
{
|
||||
float p = 0.f;
|
||||
int i;
|
||||
for(i=0; i<4; ++i)
|
||||
p += b[i]*a[i];
|
||||
return p;
|
||||
}
|
||||
static inline void quat_conj(quat r, quat q)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<3; ++i)
|
||||
r[i] = -q[i];
|
||||
r[3] = q[3];
|
||||
}
|
||||
static inline void quat_rotate(quat r, float angle, vec3 axis) {
|
||||
int i;
|
||||
vec3 v;
|
||||
vec3_scale(v, axis, sinf(angle / 2));
|
||||
for(i=0; i<3; ++i)
|
||||
r[i] = v[i];
|
||||
r[3] = cosf(angle / 2);
|
||||
}
|
||||
#define quat_norm vec4_norm
|
||||
static inline void quat_mul_vec3(vec3 r, quat q, vec3 v)
|
||||
{
|
||||
/*
|
||||
* Method by Fabian 'ryg' Giessen (of Farbrausch)
|
||||
t = 2 * cross(q.xyz, v)
|
||||
v' = v + q.w * t + cross(q.xyz, t)
|
||||
*/
|
||||
vec3 t = {q[0], q[1], q[2]};
|
||||
vec3 u = {q[0], q[1], q[2]};
|
||||
|
||||
vec3_mul_cross(t, t, v);
|
||||
vec3_scale(t, t, 2);
|
||||
|
||||
vec3_mul_cross(u, u, t);
|
||||
vec3_scale(t, t, q[3]);
|
||||
|
||||
vec3_add(r, v, t);
|
||||
vec3_add(r, r, u);
|
||||
}
|
||||
static inline void mat4x4_from_quat(mat4x4 M, quat q)
|
||||
{
|
||||
float a = q[3];
|
||||
float b = q[0];
|
||||
float c = q[1];
|
||||
float d = q[2];
|
||||
float a2 = a*a;
|
||||
float b2 = b*b;
|
||||
float c2 = c*c;
|
||||
float d2 = d*d;
|
||||
|
||||
M[0][0] = a2 + b2 - c2 - d2;
|
||||
M[0][1] = 2.f*(b*c + a*d);
|
||||
M[0][2] = 2.f*(b*d - a*c);
|
||||
M[0][3] = 0.f;
|
||||
|
||||
M[1][0] = 2*(b*c - a*d);
|
||||
M[1][1] = a2 - b2 + c2 - d2;
|
||||
M[1][2] = 2.f*(c*d + a*b);
|
||||
M[1][3] = 0.f;
|
||||
|
||||
M[2][0] = 2.f*(b*d + a*c);
|
||||
M[2][1] = 2.f*(c*d - a*b);
|
||||
M[2][2] = a2 - b2 - c2 + d2;
|
||||
M[2][3] = 0.f;
|
||||
|
||||
M[3][0] = M[3][1] = M[3][2] = 0.f;
|
||||
M[3][3] = 1.f;
|
||||
}
|
||||
|
||||
static inline void mat4x4o_mul_quat(mat4x4 R, mat4x4 M, quat q)
|
||||
{
|
||||
/* XXX: The way this is written only works for othogonal matrices. */
|
||||
/* TODO: Take care of non-orthogonal case. */
|
||||
quat_mul_vec3(R[0], q, M[0]);
|
||||
quat_mul_vec3(R[1], q, M[1]);
|
||||
quat_mul_vec3(R[2], q, M[2]);
|
||||
|
||||
R[3][0] = R[3][1] = R[3][2] = 0.f;
|
||||
R[3][3] = 1.f;
|
||||
}
|
||||
static inline void quat_from_mat4x4(quat q, mat4x4 M)
|
||||
{
|
||||
float r=0.f;
|
||||
int i;
|
||||
|
||||
int perm[] = { 0, 1, 2, 0, 1 };
|
||||
int *p = perm;
|
||||
|
||||
for(i = 0; i<3; i++) {
|
||||
float m = M[i][i];
|
||||
if( m < r )
|
||||
continue;
|
||||
m = r;
|
||||
p = &perm[i];
|
||||
}
|
||||
|
||||
r = (float) sqrt(1.f + M[p[0]][p[0]] - M[p[1]][p[1]] - M[p[2]][p[2]] );
|
||||
|
||||
if(r < 1e-6) {
|
||||
q[0] = 1.f;
|
||||
q[1] = q[2] = q[3] = 0.f;
|
||||
return;
|
||||
}
|
||||
|
||||
q[0] = r/2.f;
|
||||
q[1] = (M[p[0]][p[1]] - M[p[1]][p[0]])/(2.f*r);
|
||||
q[2] = (M[p[2]][p[0]] - M[p[0]][p[2]])/(2.f*r);
|
||||
q[3] = (M[p[2]][p[1]] - M[p[1]][p[2]])/(2.f*r);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,117 @@
|
|||
/**
|
||||
* This file has no copyright assigned and is placed in the Public Domain.
|
||||
* This file is part of the mingw-w64 runtime package.
|
||||
* No warranty is given; refer to the file DISCLAIMER within this package.
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER) && !defined(_MSC_EXTENSIONS)
|
||||
#define NONAMELESSUNION 1
|
||||
#endif
|
||||
#if defined(NONAMELESSSTRUCT) && \
|
||||
!defined(NONAMELESSUNION)
|
||||
#define NONAMELESSUNION 1
|
||||
#endif
|
||||
#if defined(NONAMELESSUNION) && \
|
||||
!defined(NONAMELESSSTRUCT)
|
||||
#define NONAMELESSSTRUCT 1
|
||||
#endif
|
||||
#if !defined(__GNU_EXTENSION)
|
||||
#if defined(__GNUC__) || defined(__GNUG__)
|
||||
#define __GNU_EXTENSION __extension__
|
||||
#else
|
||||
#define __GNU_EXTENSION
|
||||
#endif
|
||||
#endif /* __extension__ */
|
||||
|
||||
#ifndef __ANONYMOUS_DEFINED
|
||||
#define __ANONYMOUS_DEFINED
|
||||
#if defined(__GNUC__) || defined(__GNUG__)
|
||||
#define _ANONYMOUS_UNION __extension__
|
||||
#define _ANONYMOUS_STRUCT __extension__
|
||||
#else
|
||||
#define _ANONYMOUS_UNION
|
||||
#define _ANONYMOUS_STRUCT
|
||||
#endif
|
||||
#ifndef NONAMELESSUNION
|
||||
#define _UNION_NAME(x)
|
||||
#define _STRUCT_NAME(x)
|
||||
#else /* NONAMELESSUNION */
|
||||
#define _UNION_NAME(x) x
|
||||
#define _STRUCT_NAME(x) x
|
||||
#endif
|
||||
#endif /* __ANONYMOUS_DEFINED */
|
||||
|
||||
#ifndef DUMMYUNIONNAME
|
||||
# ifdef NONAMELESSUNION
|
||||
# define DUMMYUNIONNAME u
|
||||
# define DUMMYUNIONNAME1 u1 /* Wine uses this variant */
|
||||
# define DUMMYUNIONNAME2 u2
|
||||
# define DUMMYUNIONNAME3 u3
|
||||
# define DUMMYUNIONNAME4 u4
|
||||
# define DUMMYUNIONNAME5 u5
|
||||
# define DUMMYUNIONNAME6 u6
|
||||
# define DUMMYUNIONNAME7 u7
|
||||
# define DUMMYUNIONNAME8 u8
|
||||
# define DUMMYUNIONNAME9 u9
|
||||
# else /* NONAMELESSUNION */
|
||||
# define DUMMYUNIONNAME
|
||||
# define DUMMYUNIONNAME1 /* Wine uses this variant */
|
||||
# define DUMMYUNIONNAME2
|
||||
# define DUMMYUNIONNAME3
|
||||
# define DUMMYUNIONNAME4
|
||||
# define DUMMYUNIONNAME5
|
||||
# define DUMMYUNIONNAME6
|
||||
# define DUMMYUNIONNAME7
|
||||
# define DUMMYUNIONNAME8
|
||||
# define DUMMYUNIONNAME9
|
||||
# endif
|
||||
#endif /* DUMMYUNIONNAME */
|
||||
|
||||
#if !defined(DUMMYUNIONNAME1) /* MinGW does not define this one */
|
||||
# ifdef NONAMELESSUNION
|
||||
# define DUMMYUNIONNAME1 u1 /* Wine uses this variant */
|
||||
# else
|
||||
# define DUMMYUNIONNAME1 /* Wine uses this variant */
|
||||
# endif
|
||||
#endif /* DUMMYUNIONNAME1 */
|
||||
|
||||
#ifndef DUMMYSTRUCTNAME
|
||||
# ifdef NONAMELESSUNION
|
||||
# define DUMMYSTRUCTNAME s
|
||||
# define DUMMYSTRUCTNAME1 s1 /* Wine uses this variant */
|
||||
# define DUMMYSTRUCTNAME2 s2
|
||||
# define DUMMYSTRUCTNAME3 s3
|
||||
# define DUMMYSTRUCTNAME4 s4
|
||||
# define DUMMYSTRUCTNAME5 s5
|
||||
# else
|
||||
# define DUMMYSTRUCTNAME
|
||||
# define DUMMYSTRUCTNAME1 /* Wine uses this variant */
|
||||
# define DUMMYSTRUCTNAME2
|
||||
# define DUMMYSTRUCTNAME3
|
||||
# define DUMMYSTRUCTNAME4
|
||||
# define DUMMYSTRUCTNAME5
|
||||
# endif
|
||||
#endif /* DUMMYSTRUCTNAME */
|
||||
|
||||
/* These are for compatibility with the Wine source tree */
|
||||
|
||||
#ifndef WINELIB_NAME_AW
|
||||
# ifdef __MINGW_NAME_AW
|
||||
# define WINELIB_NAME_AW __MINGW_NAME_AW
|
||||
# else
|
||||
# ifdef UNICODE
|
||||
# define WINELIB_NAME_AW(func) func##W
|
||||
# else
|
||||
# define WINELIB_NAME_AW(func) func##A
|
||||
# endif
|
||||
# endif
|
||||
#endif /* WINELIB_NAME_AW */
|
||||
|
||||
#ifndef DECL_WINELIB_TYPE_AW
|
||||
# ifdef __MINGW_TYPEDEF_AW
|
||||
# define DECL_WINELIB_TYPE_AW __MINGW_TYPEDEF_AW
|
||||
# else
|
||||
# define DECL_WINELIB_TYPE_AW(type) typedef WINELIB_NAME_AW(type) type;
|
||||
# endif
|
||||
#endif /* DECL_WINELIB_TYPE_AW */
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* The Wine project - Xinput Joystick Library
|
||||
* Copyright 2008 Andrew Fenn
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef __WINE_XINPUT_H
|
||||
#define __WINE_XINPUT_H
|
||||
|
||||
#include <windef.h>
|
||||
|
||||
/*
|
||||
* Bitmasks for the joysticks buttons, determines what has
|
||||
* been pressed on the joystick, these need to be mapped
|
||||
* to whatever device you're using instead of an xbox 360
|
||||
* joystick
|
||||
*/
|
||||
|
||||
#define XINPUT_GAMEPAD_DPAD_UP 0x0001
|
||||
#define XINPUT_GAMEPAD_DPAD_DOWN 0x0002
|
||||
#define XINPUT_GAMEPAD_DPAD_LEFT 0x0004
|
||||
#define XINPUT_GAMEPAD_DPAD_RIGHT 0x0008
|
||||
#define XINPUT_GAMEPAD_START 0x0010
|
||||
#define XINPUT_GAMEPAD_BACK 0x0020
|
||||
#define XINPUT_GAMEPAD_LEFT_THUMB 0x0040
|
||||
#define XINPUT_GAMEPAD_RIGHT_THUMB 0x0080
|
||||
#define XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100
|
||||
#define XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200
|
||||
#define XINPUT_GAMEPAD_A 0x1000
|
||||
#define XINPUT_GAMEPAD_B 0x2000
|
||||
#define XINPUT_GAMEPAD_X 0x4000
|
||||
#define XINPUT_GAMEPAD_Y 0x8000
|
||||
|
||||
/*
|
||||
* Defines the flags used to determine if the user is pushing
|
||||
* down on a button, not holding a button, etc
|
||||
*/
|
||||
|
||||
#define XINPUT_KEYSTROKE_KEYDOWN 0x0001
|
||||
#define XINPUT_KEYSTROKE_KEYUP 0x0002
|
||||
#define XINPUT_KEYSTROKE_REPEAT 0x0004
|
||||
|
||||
/*
|
||||
* Defines the codes which are returned by XInputGetKeystroke
|
||||
*/
|
||||
|
||||
#define VK_PAD_A 0x5800
|
||||
#define VK_PAD_B 0x5801
|
||||
#define VK_PAD_X 0x5802
|
||||
#define VK_PAD_Y 0x5803
|
||||
#define VK_PAD_RSHOULDER 0x5804
|
||||
#define VK_PAD_LSHOULDER 0x5805
|
||||
#define VK_PAD_LTRIGGER 0x5806
|
||||
#define VK_PAD_RTRIGGER 0x5807
|
||||
#define VK_PAD_DPAD_UP 0x5810
|
||||
#define VK_PAD_DPAD_DOWN 0x5811
|
||||
#define VK_PAD_DPAD_LEFT 0x5812
|
||||
#define VK_PAD_DPAD_RIGHT 0x5813
|
||||
#define VK_PAD_START 0x5814
|
||||
#define VK_PAD_BACK 0x5815
|
||||
#define VK_PAD_LTHUMB_PRESS 0x5816
|
||||
#define VK_PAD_RTHUMB_PRESS 0x5817
|
||||
#define VK_PAD_LTHUMB_UP 0x5820
|
||||
#define VK_PAD_LTHUMB_DOWN 0x5821
|
||||
#define VK_PAD_LTHUMB_RIGHT 0x5822
|
||||
#define VK_PAD_LTHUMB_LEFT 0x5823
|
||||
#define VK_PAD_LTHUMB_UPLEFT 0x5824
|
||||
#define VK_PAD_LTHUMB_UPRIGHT 0x5825
|
||||
#define VK_PAD_LTHUMB_DOWNRIGHT 0x5826
|
||||
#define VK_PAD_LTHUMB_DOWNLEFT 0x5827
|
||||
#define VK_PAD_RTHUMB_UP 0x5830
|
||||
#define VK_PAD_RTHUMB_DOWN 0x5831
|
||||
#define VK_PAD_RTHUMB_RIGHT 0x5832
|
||||
#define VK_PAD_RTHUMB_LEFT 0x5833
|
||||
#define VK_PAD_RTHUMB_UPLEFT 0x5834
|
||||
#define VK_PAD_RTHUMB_UPRIGHT 0x5835
|
||||
#define VK_PAD_RTHUMB_DOWNRIGHT 0x5836
|
||||
#define VK_PAD_RTHUMB_DOWNLEFT 0x5837
|
||||
|
||||
/*
|
||||
* Deadzones are for analogue joystick controls on the joypad
|
||||
* which determine when input should be assumed to be in the
|
||||
* middle of the pad. This is a threshold to stop a joypad
|
||||
* controlling the game when the player isn't touching the
|
||||
* controls.
|
||||
*/
|
||||
|
||||
#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849
|
||||
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
|
||||
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
|
||||
|
||||
|
||||
/*
|
||||
* Defines what type of abilities the type of joystick has
|
||||
* DEVTYPE_GAMEPAD is available for all joysticks, however
|
||||
* there may be more specific identifiers for other joysticks
|
||||
* which are being used.
|
||||
*/
|
||||
|
||||
#define XINPUT_DEVTYPE_GAMEPAD 0x01
|
||||
#define XINPUT_DEVSUBTYPE_GAMEPAD 0x01
|
||||
#define XINPUT_DEVSUBTYPE_WHEEL 0x02
|
||||
#define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
|
||||
#define XINPUT_DEVSUBTYPE_FLIGHT_SICK 0x04
|
||||
#define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
|
||||
#define XINPUT_DEVSUBTYPE_GUITAR 0x06
|
||||
#define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
|
||||
|
||||
/*
|
||||
* These are used with the XInputGetCapabilities function to
|
||||
* determine the abilities to the joystick which has been
|
||||
* plugged in.
|
||||
*/
|
||||
|
||||
#define XINPUT_CAPS_VOICE_SUPPORTED 0x0004
|
||||
#define XINPUT_FLAG_GAMEPAD 0x00000001
|
||||
|
||||
/*
|
||||
* Defines the status of the battery if one is used in the
|
||||
* attached joystick. The first two define if the joystick
|
||||
* supports a battery. Disconnected means that the joystick
|
||||
* isn't connected. Wired shows that the joystick is a wired
|
||||
* joystick.
|
||||
*/
|
||||
|
||||
#define BATTERY_DEVTYPE_GAMEPAD 0x00
|
||||
#define BATTERY_DEVTYPE_HEADSET 0x01
|
||||
#define BATTERY_TYPE_DISCONNECTED 0x00
|
||||
#define BATTERY_TYPE_WIRED 0x01
|
||||
#define BATTERY_TYPE_ALKALINE 0x02
|
||||
#define BATTERY_TYPE_NIMH 0x03
|
||||
#define BATTERY_TYPE_UNKNOWN 0xFF
|
||||
#define BATTERY_LEVEL_EMPTY 0x00
|
||||
#define BATTERY_LEVEL_LOW 0x01
|
||||
#define BATTERY_LEVEL_MEDIUM 0x02
|
||||
#define BATTERY_LEVEL_FULL 0x03
|
||||
|
||||
/*
|
||||
* How many joysticks can be used with this library. Games that
|
||||
* use the xinput library will not go over this number.
|
||||
*/
|
||||
|
||||
#define XUSER_MAX_COUNT 4
|
||||
#define XUSER_INDEX_ANY 0x000000FF
|
||||
|
||||
/*
|
||||
* Defines the structure of an xbox 360 joystick.
|
||||
*/
|
||||
|
||||
typedef struct _XINPUT_GAMEPAD {
|
||||
WORD wButtons;
|
||||
BYTE bLeftTrigger;
|
||||
BYTE bRightTrigger;
|
||||
SHORT sThumbLX;
|
||||
SHORT sThumbLY;
|
||||
SHORT sThumbRX;
|
||||
SHORT sThumbRY;
|
||||
} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;
|
||||
|
||||
typedef struct _XINPUT_STATE {
|
||||
DWORD dwPacketNumber;
|
||||
XINPUT_GAMEPAD Gamepad;
|
||||
} XINPUT_STATE, *PXINPUT_STATE;
|
||||
|
||||
/*
|
||||
* Defines the structure of how much vibration is set on both the
|
||||
* right and left motors in a joystick. If you're not using a 360
|
||||
* joystick you will have to map these to your device.
|
||||
*/
|
||||
|
||||
typedef struct _XINPUT_VIBRATION {
|
||||
WORD wLeftMotorSpeed;
|
||||
WORD wRightMotorSpeed;
|
||||
} XINPUT_VIBRATION, *PXINPUT_VIBRATION;
|
||||
|
||||
/*
|
||||
* Defines the structure for what kind of abilities the joystick has
|
||||
* such abilities are things such as if the joystick has the ability
|
||||
* to send and receive audio, if the joystick is in fact a driving
|
||||
* wheel or perhaps if the joystick is some kind of dance pad or
|
||||
* guitar.
|
||||
*/
|
||||
|
||||
typedef struct _XINPUT_CAPABILITIES {
|
||||
BYTE Type;
|
||||
BYTE SubType;
|
||||
WORD Flags;
|
||||
XINPUT_GAMEPAD Gamepad;
|
||||
XINPUT_VIBRATION Vibration;
|
||||
} XINPUT_CAPABILITIES, *PXINPUT_CAPABILITIES;
|
||||
|
||||
/*
|
||||
* Defines the structure for a joystick input event which is
|
||||
* retrieved using the function XInputGetKeystroke
|
||||
*/
|
||||
typedef struct _XINPUT_KEYSTROKE {
|
||||
WORD VirtualKey;
|
||||
WCHAR Unicode;
|
||||
WORD Flags;
|
||||
BYTE UserIndex;
|
||||
BYTE HidCode;
|
||||
} XINPUT_KEYSTROKE, *PXINPUT_KEYSTROKE;
|
||||
|
||||
typedef struct _XINPUT_BATTERY_INFORMATION
|
||||
{
|
||||
BYTE BatteryType;
|
||||
BYTE BatteryLevel;
|
||||
} XINPUT_BATTERY_INFORMATION, *PXINPUT_BATTERY_INFORMATION;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void WINAPI XInputEnable(WINBOOL);
|
||||
DWORD WINAPI XInputSetState(DWORD, XINPUT_VIBRATION*);
|
||||
DWORD WINAPI XInputGetState(DWORD, XINPUT_STATE*);
|
||||
DWORD WINAPI XInputGetKeystroke(DWORD, DWORD, PXINPUT_KEYSTROKE);
|
||||
DWORD WINAPI XInputGetCapabilities(DWORD, DWORD, XINPUT_CAPABILITIES*);
|
||||
DWORD WINAPI XInputGetDSoundAudioDeviceGuids(DWORD, GUID*, GUID*);
|
||||
DWORD WINAPI XInputGetBatteryInformation(DWORD, BYTE, XINPUT_BATTERY_INFORMATION*);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __WINE_XINPUT_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
* Nuklear - v1.32.0 - public domain
|
||||
* no warrenty implied; use at your own risk.
|
||||
* authored from 2015-2016 by Micha Mettke
|
||||
*/
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
* API
|
||||
*
|
||||
* ===============================================================
|
||||
*/
|
||||
#ifndef NK_GLFW_GL2_H_
|
||||
#define NK_GLFW_GL2_H_
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
enum nk_glfw_init_state{
|
||||
NK_GLFW3_DEFAULT = 0,
|
||||
NK_GLFW3_INSTALL_CALLBACKS
|
||||
};
|
||||
NK_API struct nk_context* nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state);
|
||||
NK_API void nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas);
|
||||
NK_API void nk_glfw3_font_stash_end(void);
|
||||
|
||||
NK_API void nk_glfw3_new_frame(void);
|
||||
NK_API void nk_glfw3_render(enum nk_anti_aliasing , int max_vertex_buffer, int max_element_buffer);
|
||||
NK_API void nk_glfw3_shutdown(void);
|
||||
|
||||
NK_API void nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
|
||||
NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
* IMPLEMENTATION
|
||||
*
|
||||
* ===============================================================
|
||||
*/
|
||||
#ifdef NK_GLFW_GL2_IMPLEMENTATION
|
||||
|
||||
#ifndef NK_GLFW_TEXT_MAX
|
||||
#define NK_GLFW_TEXT_MAX 256
|
||||
#endif
|
||||
|
||||
struct nk_glfw_device {
|
||||
struct nk_buffer cmds;
|
||||
struct nk_draw_null_texture null;
|
||||
GLuint font_tex;
|
||||
};
|
||||
|
||||
struct nk_glfw_vertex {
|
||||
float position[2];
|
||||
float uv[2];
|
||||
nk_byte col[4];
|
||||
};
|
||||
|
||||
static struct nk_glfw {
|
||||
GLFWwindow *win;
|
||||
int width, height;
|
||||
int display_width, display_height;
|
||||
struct nk_glfw_device ogl;
|
||||
struct nk_context ctx;
|
||||
struct nk_font_atlas atlas;
|
||||
struct nk_vec2 fb_scale;
|
||||
unsigned int text[NK_GLFW_TEXT_MAX];
|
||||
int text_len;
|
||||
float scroll;
|
||||
} glfw;
|
||||
|
||||
NK_INTERN void
|
||||
nk_glfw3_device_upload_atlas(const void *image, int width, int height)
|
||||
{
|
||||
struct nk_glfw_device *dev = &glfw.ogl;
|
||||
glGenTextures(1, &dev->font_tex);
|
||||
glBindTexture(GL_TEXTURE_2D, dev->font_tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_glfw3_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer)
|
||||
{
|
||||
/* setup global state */
|
||||
struct nk_glfw_device *dev = &glfw.ogl;
|
||||
glPushAttrib(GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT|GL_TRANSFORM_BIT);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
/* setup viewport/project */
|
||||
glViewport(0,0,(GLsizei)glfw.display_width,(GLsizei)glfw.display_height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(0.0f, glfw.width, glfw.height, 0.0f, -1.0f, 1.0f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
{
|
||||
GLsizei vs = sizeof(struct nk_glfw_vertex);
|
||||
size_t vp = offsetof(struct nk_glfw_vertex, position);
|
||||
size_t vt = offsetof(struct nk_glfw_vertex, uv);
|
||||
size_t vc = offsetof(struct nk_glfw_vertex, col);
|
||||
|
||||
/* convert from command queue into draw list and draw to screen */
|
||||
const struct nk_draw_command *cmd;
|
||||
const nk_draw_index *offset = NULL;
|
||||
struct nk_buffer vbuf, ebuf;
|
||||
|
||||
/* fill convert configuration */
|
||||
struct nk_convert_config config;
|
||||
static const struct nk_draw_vertex_layout_element vertex_layout[] = {
|
||||
{NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)},
|
||||
{NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)},
|
||||
{NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)},
|
||||
{NK_VERTEX_LAYOUT_END}
|
||||
};
|
||||
NK_MEMSET(&config, 0, sizeof(config));
|
||||
config.vertex_layout = vertex_layout;
|
||||
config.vertex_size = sizeof(struct nk_glfw_vertex);
|
||||
config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex);
|
||||
config.null = dev->null;
|
||||
config.circle_segment_count = 22;
|
||||
config.curve_segment_count = 22;
|
||||
config.arc_segment_count = 22;
|
||||
config.global_alpha = 1.0f;
|
||||
config.shape_AA = AA;
|
||||
config.line_AA = AA;
|
||||
|
||||
/* convert shapes into vertexes */
|
||||
nk_buffer_init_default(&vbuf);
|
||||
nk_buffer_init_default(&ebuf);
|
||||
nk_convert(&glfw.ctx, &dev->cmds, &vbuf, &ebuf, &config);
|
||||
|
||||
/* setup vertex buffer pointer */
|
||||
{const void *vertices = nk_buffer_memory_const(&vbuf);
|
||||
glVertexPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vp));
|
||||
glTexCoordPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vt));
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, vs, (const void*)((const nk_byte*)vertices + vc));}
|
||||
|
||||
/* iterate over and execute each draw command */
|
||||
offset = (const nk_draw_index*)nk_buffer_memory_const(&ebuf);
|
||||
nk_draw_foreach(cmd, &glfw.ctx, &dev->cmds)
|
||||
{
|
||||
if (!cmd->elem_count) continue;
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
|
||||
glScissor(
|
||||
(GLint)(cmd->clip_rect.x * glfw.fb_scale.x),
|
||||
(GLint)((glfw.height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * glfw.fb_scale.y),
|
||||
(GLint)(cmd->clip_rect.w * glfw.fb_scale.x),
|
||||
(GLint)(cmd->clip_rect.h * glfw.fb_scale.y));
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
|
||||
offset += cmd->elem_count;
|
||||
}
|
||||
nk_clear(&glfw.ctx);
|
||||
nk_buffer_free(&vbuf);
|
||||
nk_buffer_free(&ebuf);
|
||||
}
|
||||
|
||||
/* default OpenGL state */
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint)
|
||||
{
|
||||
(void)win;
|
||||
if (glfw.text_len < NK_GLFW_TEXT_MAX)
|
||||
glfw.text[glfw.text_len++] = codepoint;
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff)
|
||||
{
|
||||
(void)win; (void)xoff;
|
||||
glfw.scroll += (float)yoff;
|
||||
}
|
||||
|
||||
NK_INTERN void
|
||||
nk_glfw3_clipbard_paste(nk_handle usr, struct nk_text_edit *edit)
|
||||
{
|
||||
const char *text = glfwGetClipboardString(glfw.win);
|
||||
if (text) nk_textedit_paste(edit, text, nk_strlen(text));
|
||||
(void)usr;
|
||||
}
|
||||
|
||||
NK_INTERN void
|
||||
nk_glfw3_clipbard_copy(nk_handle usr, const char *text, int len)
|
||||
{
|
||||
char *str = 0;
|
||||
(void)usr;
|
||||
if (!len) return;
|
||||
str = (char*)malloc((size_t)len+1);
|
||||
if (!str) return;
|
||||
NK_MEMCPY(str, text, (size_t)len);
|
||||
str[len] = '\0';
|
||||
glfwSetClipboardString(glfw.win, str);
|
||||
free(str);
|
||||
}
|
||||
|
||||
NK_API struct nk_context*
|
||||
nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state)
|
||||
{
|
||||
glfw.win = win;
|
||||
if (init_state == NK_GLFW3_INSTALL_CALLBACKS) {
|
||||
glfwSetScrollCallback(win, nk_gflw3_scroll_callback);
|
||||
glfwSetCharCallback(win, nk_glfw3_char_callback);
|
||||
}
|
||||
|
||||
nk_init_default(&glfw.ctx, 0);
|
||||
glfw.ctx.clip.copy = nk_glfw3_clipbard_copy;
|
||||
glfw.ctx.clip.paste = nk_glfw3_clipbard_paste;
|
||||
glfw.ctx.clip.userdata = nk_handle_ptr(0);
|
||||
nk_buffer_init_default(&glfw.ogl.cmds);
|
||||
return &glfw.ctx;
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas)
|
||||
{
|
||||
nk_font_atlas_init_default(&glfw.atlas);
|
||||
nk_font_atlas_begin(&glfw.atlas);
|
||||
*atlas = &glfw.atlas;
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_glfw3_font_stash_end(void)
|
||||
{
|
||||
const void *image; int w, h;
|
||||
image = nk_font_atlas_bake(&glfw.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
|
||||
nk_glfw3_device_upload_atlas(image, w, h);
|
||||
nk_font_atlas_end(&glfw.atlas, nk_handle_id((int)glfw.ogl.font_tex), &glfw.ogl.null);
|
||||
if (glfw.atlas.default_font)
|
||||
nk_style_set_font(&glfw.ctx, &glfw.atlas.default_font->handle);
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_glfw3_new_frame(void)
|
||||
{
|
||||
int i;
|
||||
double x, y;
|
||||
struct nk_context *ctx = &glfw.ctx;
|
||||
struct GLFWwindow *win = glfw.win;
|
||||
|
||||
glfwGetWindowSize(win, &glfw.width, &glfw.height);
|
||||
glfwGetFramebufferSize(win, &glfw.display_width, &glfw.display_height);
|
||||
glfw.fb_scale.x = (float)glfw.display_width/(float)glfw.width;
|
||||
glfw.fb_scale.y = (float)glfw.display_height/(float)glfw.height;
|
||||
|
||||
nk_input_begin(ctx);
|
||||
for (i = 0; i < glfw.text_len; ++i)
|
||||
nk_input_unicode(ctx, glfw.text[i]);
|
||||
|
||||
/* optional grabbing behavior */
|
||||
if (ctx->input.mouse.grab)
|
||||
glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
else if (ctx->input.mouse.ungrab)
|
||||
glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
|
||||
nk_input_key(ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_SCROLL_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_SCROLL_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_SCROLL_DOWN, glfwGetKey(win, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_SCROLL_UP, glfwGetKey(win, GLFW_KEY_PAGE_UP) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_SHIFT, glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS||
|
||||
glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS);
|
||||
|
||||
if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
|
||||
glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) {
|
||||
nk_input_key(ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_V) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_UNDO, glfwGetKey(win, GLFW_KEY_Z) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_REDO, glfwGetKey(win, GLFW_KEY_R) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_LINE_START, glfwGetKey(win, GLFW_KEY_B) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_LINE_END, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS);
|
||||
} else {
|
||||
nk_input_key(ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_COPY, 0);
|
||||
nk_input_key(ctx, NK_KEY_PASTE, 0);
|
||||
nk_input_key(ctx, NK_KEY_CUT, 0);
|
||||
nk_input_key(ctx, NK_KEY_SHIFT, 0);
|
||||
}
|
||||
|
||||
glfwGetCursorPos(win, &x, &y);
|
||||
nk_input_motion(ctx, (int)x, (int)y);
|
||||
if (ctx->input.mouse.grabbed) {
|
||||
glfwSetCursorPos(glfw.win, ctx->input.mouse.prev.x, ctx->input.mouse.prev.y);
|
||||
ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
|
||||
ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
|
||||
}
|
||||
|
||||
nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
|
||||
nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
|
||||
nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
|
||||
nk_input_scroll(ctx, glfw.scroll);
|
||||
nk_input_end(&glfw.ctx);
|
||||
glfw.text_len = 0;
|
||||
glfw.scroll = 0;
|
||||
}
|
||||
|
||||
NK_API
|
||||
void nk_glfw3_shutdown(void)
|
||||
{
|
||||
struct nk_glfw_device *dev = &glfw.ogl;
|
||||
nk_font_atlas_clear(&glfw.atlas);
|
||||
nk_free(&glfw.ctx);
|
||||
glDeleteTextures(1, &dev->font_tex);
|
||||
nk_buffer_free(&dev->cmds);
|
||||
NK_MEMSET(&glfw, 0, sizeof(glfw));
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,594 @@
|
|||
/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; -*-
|
||||
Copyright (c) 2012 Marcus Geelnard
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/* 2013-01-06 Camilla Löwy <elmindreda@glfw.org>
|
||||
*
|
||||
* Added casts from time_t to DWORD to avoid warnings on VC++.
|
||||
* Fixed time retrieval on POSIX systems.
|
||||
*/
|
||||
|
||||
#include "tinycthread.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Platform specific includes */
|
||||
#if defined(_TTHREAD_POSIX_)
|
||||
#include <signal.h>
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#elif defined(_TTHREAD_WIN32_)
|
||||
#include <process.h>
|
||||
#include <sys/timeb.h>
|
||||
#endif
|
||||
|
||||
/* Standard, good-to-have defines */
|
||||
#ifndef NULL
|
||||
#define NULL (void*)0
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
int mtx_init(mtx_t *mtx, int type)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
mtx->mAlreadyLocked = FALSE;
|
||||
mtx->mRecursive = type & mtx_recursive;
|
||||
InitializeCriticalSection(&mtx->mHandle);
|
||||
return thrd_success;
|
||||
#else
|
||||
int ret;
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
if (type & mtx_recursive)
|
||||
{
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
}
|
||||
ret = pthread_mutex_init(mtx, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
return ret == 0 ? thrd_success : thrd_error;
|
||||
#endif
|
||||
}
|
||||
|
||||
void mtx_destroy(mtx_t *mtx)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
DeleteCriticalSection(&mtx->mHandle);
|
||||
#else
|
||||
pthread_mutex_destroy(mtx);
|
||||
#endif
|
||||
}
|
||||
|
||||
int mtx_lock(mtx_t *mtx)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
EnterCriticalSection(&mtx->mHandle);
|
||||
if (!mtx->mRecursive)
|
||||
{
|
||||
while(mtx->mAlreadyLocked) Sleep(1000); /* Simulate deadlock... */
|
||||
mtx->mAlreadyLocked = TRUE;
|
||||
}
|
||||
return thrd_success;
|
||||
#else
|
||||
return pthread_mutex_lock(mtx) == 0 ? thrd_success : thrd_error;
|
||||
#endif
|
||||
}
|
||||
|
||||
int mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
|
||||
{
|
||||
/* FIXME! */
|
||||
(void)mtx;
|
||||
(void)ts;
|
||||
return thrd_error;
|
||||
}
|
||||
|
||||
int mtx_trylock(mtx_t *mtx)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
int ret = TryEnterCriticalSection(&mtx->mHandle) ? thrd_success : thrd_busy;
|
||||
if ((!mtx->mRecursive) && (ret == thrd_success) && mtx->mAlreadyLocked)
|
||||
{
|
||||
LeaveCriticalSection(&mtx->mHandle);
|
||||
ret = thrd_busy;
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
return (pthread_mutex_trylock(mtx) == 0) ? thrd_success : thrd_busy;
|
||||
#endif
|
||||
}
|
||||
|
||||
int mtx_unlock(mtx_t *mtx)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
mtx->mAlreadyLocked = FALSE;
|
||||
LeaveCriticalSection(&mtx->mHandle);
|
||||
return thrd_success;
|
||||
#else
|
||||
return pthread_mutex_unlock(mtx) == 0 ? thrd_success : thrd_error;;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
#define _CONDITION_EVENT_ONE 0
|
||||
#define _CONDITION_EVENT_ALL 1
|
||||
#endif
|
||||
|
||||
int cnd_init(cnd_t *cond)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
cond->mWaitersCount = 0;
|
||||
|
||||
/* Init critical section */
|
||||
InitializeCriticalSection(&cond->mWaitersCountLock);
|
||||
|
||||
/* Init events */
|
||||
cond->mEvents[_CONDITION_EVENT_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (cond->mEvents[_CONDITION_EVENT_ONE] == NULL)
|
||||
{
|
||||
cond->mEvents[_CONDITION_EVENT_ALL] = NULL;
|
||||
return thrd_error;
|
||||
}
|
||||
cond->mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (cond->mEvents[_CONDITION_EVENT_ALL] == NULL)
|
||||
{
|
||||
CloseHandle(cond->mEvents[_CONDITION_EVENT_ONE]);
|
||||
cond->mEvents[_CONDITION_EVENT_ONE] = NULL;
|
||||
return thrd_error;
|
||||
}
|
||||
|
||||
return thrd_success;
|
||||
#else
|
||||
return pthread_cond_init(cond, NULL) == 0 ? thrd_success : thrd_error;
|
||||
#endif
|
||||
}
|
||||
|
||||
void cnd_destroy(cnd_t *cond)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
if (cond->mEvents[_CONDITION_EVENT_ONE] != NULL)
|
||||
{
|
||||
CloseHandle(cond->mEvents[_CONDITION_EVENT_ONE]);
|
||||
}
|
||||
if (cond->mEvents[_CONDITION_EVENT_ALL] != NULL)
|
||||
{
|
||||
CloseHandle(cond->mEvents[_CONDITION_EVENT_ALL]);
|
||||
}
|
||||
DeleteCriticalSection(&cond->mWaitersCountLock);
|
||||
#else
|
||||
pthread_cond_destroy(cond);
|
||||
#endif
|
||||
}
|
||||
|
||||
int cnd_signal(cnd_t *cond)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
int haveWaiters;
|
||||
|
||||
/* Are there any waiters? */
|
||||
EnterCriticalSection(&cond->mWaitersCountLock);
|
||||
haveWaiters = (cond->mWaitersCount > 0);
|
||||
LeaveCriticalSection(&cond->mWaitersCountLock);
|
||||
|
||||
/* If we have any waiting threads, send them a signal */
|
||||
if(haveWaiters)
|
||||
{
|
||||
if (SetEvent(cond->mEvents[_CONDITION_EVENT_ONE]) == 0)
|
||||
{
|
||||
return thrd_error;
|
||||
}
|
||||
}
|
||||
|
||||
return thrd_success;
|
||||
#else
|
||||
return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
|
||||
#endif
|
||||
}
|
||||
|
||||
int cnd_broadcast(cnd_t *cond)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
int haveWaiters;
|
||||
|
||||
/* Are there any waiters? */
|
||||
EnterCriticalSection(&cond->mWaitersCountLock);
|
||||
haveWaiters = (cond->mWaitersCount > 0);
|
||||
LeaveCriticalSection(&cond->mWaitersCountLock);
|
||||
|
||||
/* If we have any waiting threads, send them a signal */
|
||||
if(haveWaiters)
|
||||
{
|
||||
if (SetEvent(cond->mEvents[_CONDITION_EVENT_ALL]) == 0)
|
||||
{
|
||||
return thrd_error;
|
||||
}
|
||||
}
|
||||
|
||||
return thrd_success;
|
||||
#else
|
||||
return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
static int _cnd_timedwait_win32(cnd_t *cond, mtx_t *mtx, DWORD timeout)
|
||||
{
|
||||
int result, lastWaiter;
|
||||
|
||||
/* Increment number of waiters */
|
||||
EnterCriticalSection(&cond->mWaitersCountLock);
|
||||
++ cond->mWaitersCount;
|
||||
LeaveCriticalSection(&cond->mWaitersCountLock);
|
||||
|
||||
/* Release the mutex while waiting for the condition (will decrease
|
||||
the number of waiters when done)... */
|
||||
mtx_unlock(mtx);
|
||||
|
||||
/* Wait for either event to become signaled due to cnd_signal() or
|
||||
cnd_broadcast() being called */
|
||||
result = WaitForMultipleObjects(2, cond->mEvents, FALSE, timeout);
|
||||
if (result == WAIT_TIMEOUT)
|
||||
{
|
||||
return thrd_timeout;
|
||||
}
|
||||
else if (result == (int)WAIT_FAILED)
|
||||
{
|
||||
return thrd_error;
|
||||
}
|
||||
|
||||
/* Check if we are the last waiter */
|
||||
EnterCriticalSection(&cond->mWaitersCountLock);
|
||||
-- cond->mWaitersCount;
|
||||
lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) &&
|
||||
(cond->mWaitersCount == 0);
|
||||
LeaveCriticalSection(&cond->mWaitersCountLock);
|
||||
|
||||
/* If we are the last waiter to be notified to stop waiting, reset the event */
|
||||
if (lastWaiter)
|
||||
{
|
||||
if (ResetEvent(cond->mEvents[_CONDITION_EVENT_ALL]) == 0)
|
||||
{
|
||||
return thrd_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Re-acquire the mutex */
|
||||
mtx_lock(mtx);
|
||||
|
||||
return thrd_success;
|
||||
}
|
||||
#endif
|
||||
|
||||
int cnd_wait(cnd_t *cond, mtx_t *mtx)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
return _cnd_timedwait_win32(cond, mtx, INFINITE);
|
||||
#else
|
||||
return pthread_cond_wait(cond, mtx) == 0 ? thrd_success : thrd_error;
|
||||
#endif
|
||||
}
|
||||
|
||||
int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
struct timespec now;
|
||||
if (clock_gettime(CLOCK_REALTIME, &now) == 0)
|
||||
{
|
||||
DWORD delta = (DWORD) ((ts->tv_sec - now.tv_sec) * 1000 +
|
||||
(ts->tv_nsec - now.tv_nsec + 500000) / 1000000);
|
||||
return _cnd_timedwait_win32(cond, mtx, delta);
|
||||
}
|
||||
else
|
||||
return thrd_error;
|
||||
#else
|
||||
int ret;
|
||||
ret = pthread_cond_timedwait(cond, mtx, ts);
|
||||
if (ret == ETIMEDOUT)
|
||||
{
|
||||
return thrd_timeout;
|
||||
}
|
||||
return ret == 0 ? thrd_success : thrd_error;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/** Information to pass to the new thread (what to run). */
|
||||
typedef struct {
|
||||
thrd_start_t mFunction; /**< Pointer to the function to be executed. */
|
||||
void * mArg; /**< Function argument for the thread function. */
|
||||
} _thread_start_info;
|
||||
|
||||
/* Thread wrapper function. */
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
static unsigned WINAPI _thrd_wrapper_function(void * aArg)
|
||||
#elif defined(_TTHREAD_POSIX_)
|
||||
static void * _thrd_wrapper_function(void * aArg)
|
||||
#endif
|
||||
{
|
||||
thrd_start_t fun;
|
||||
void *arg;
|
||||
int res;
|
||||
#if defined(_TTHREAD_POSIX_)
|
||||
void *pres;
|
||||
#endif
|
||||
|
||||
/* Get thread startup information */
|
||||
_thread_start_info *ti = (_thread_start_info *) aArg;
|
||||
fun = ti->mFunction;
|
||||
arg = ti->mArg;
|
||||
|
||||
/* The thread is responsible for freeing the startup information */
|
||||
free((void *)ti);
|
||||
|
||||
/* Call the actual client thread function */
|
||||
res = fun(arg);
|
||||
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
return res;
|
||||
#else
|
||||
pres = malloc(sizeof(int));
|
||||
if (pres != NULL)
|
||||
{
|
||||
*(int*)pres = res;
|
||||
}
|
||||
return pres;
|
||||
#endif
|
||||
}
|
||||
|
||||
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
|
||||
{
|
||||
/* Fill out the thread startup information (passed to the thread wrapper,
|
||||
which will eventually free it) */
|
||||
_thread_start_info* ti = (_thread_start_info*)malloc(sizeof(_thread_start_info));
|
||||
if (ti == NULL)
|
||||
{
|
||||
return thrd_nomem;
|
||||
}
|
||||
ti->mFunction = func;
|
||||
ti->mArg = arg;
|
||||
|
||||
/* Create the thread */
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
*thr = (HANDLE)_beginthreadex(NULL, 0, _thrd_wrapper_function, (void *)ti, 0, NULL);
|
||||
#elif defined(_TTHREAD_POSIX_)
|
||||
if(pthread_create(thr, NULL, _thrd_wrapper_function, (void *)ti) != 0)
|
||||
{
|
||||
*thr = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Did we fail to create the thread? */
|
||||
if(!*thr)
|
||||
{
|
||||
free(ti);
|
||||
return thrd_error;
|
||||
}
|
||||
|
||||
return thrd_success;
|
||||
}
|
||||
|
||||
thrd_t thrd_current(void)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
return GetCurrentThread();
|
||||
#else
|
||||
return pthread_self();
|
||||
#endif
|
||||
}
|
||||
|
||||
int thrd_detach(thrd_t thr)
|
||||
{
|
||||
/* FIXME! */
|
||||
(void)thr;
|
||||
return thrd_error;
|
||||
}
|
||||
|
||||
int thrd_equal(thrd_t thr0, thrd_t thr1)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
return thr0 == thr1;
|
||||
#else
|
||||
return pthread_equal(thr0, thr1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void thrd_exit(int res)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
ExitThread(res);
|
||||
#else
|
||||
void *pres = malloc(sizeof(int));
|
||||
if (pres != NULL)
|
||||
{
|
||||
*(int*)pres = res;
|
||||
}
|
||||
pthread_exit(pres);
|
||||
#endif
|
||||
}
|
||||
|
||||
int thrd_join(thrd_t thr, int *res)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
if (WaitForSingleObject(thr, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
return thrd_error;
|
||||
}
|
||||
if (res != NULL)
|
||||
{
|
||||
DWORD dwRes;
|
||||
GetExitCodeThread(thr, &dwRes);
|
||||
*res = dwRes;
|
||||
}
|
||||
#elif defined(_TTHREAD_POSIX_)
|
||||
void *pres;
|
||||
int ires = 0;
|
||||
if (pthread_join(thr, &pres) != 0)
|
||||
{
|
||||
return thrd_error;
|
||||
}
|
||||
if (pres != NULL)
|
||||
{
|
||||
ires = *(int*)pres;
|
||||
free(pres);
|
||||
}
|
||||
if (res != NULL)
|
||||
{
|
||||
*res = ires;
|
||||
}
|
||||
#endif
|
||||
return thrd_success;
|
||||
}
|
||||
|
||||
int thrd_sleep(const struct timespec *time_point, struct timespec *remaining)
|
||||
{
|
||||
struct timespec now;
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
DWORD delta;
|
||||
#else
|
||||
long delta;
|
||||
#endif
|
||||
|
||||
/* Get the current time */
|
||||
if (clock_gettime(CLOCK_REALTIME, &now) != 0)
|
||||
return -2; // FIXME: Some specific error code?
|
||||
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
/* Delta in milliseconds */
|
||||
delta = (DWORD) ((time_point->tv_sec - now.tv_sec) * 1000 +
|
||||
(time_point->tv_nsec - now.tv_nsec + 500000) / 1000000);
|
||||
if (delta > 0)
|
||||
{
|
||||
Sleep(delta);
|
||||
}
|
||||
#else
|
||||
/* Delta in microseconds */
|
||||
delta = (time_point->tv_sec - now.tv_sec) * 1000000L +
|
||||
(time_point->tv_nsec - now.tv_nsec + 500L) / 1000L;
|
||||
|
||||
/* On some systems, the usleep argument must be < 1000000 */
|
||||
while (delta > 999999L)
|
||||
{
|
||||
usleep(999999);
|
||||
delta -= 999999L;
|
||||
}
|
||||
if (delta > 0L)
|
||||
{
|
||||
usleep((useconds_t)delta);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We don't support waking up prematurely (yet) */
|
||||
if (remaining)
|
||||
{
|
||||
remaining->tv_sec = 0;
|
||||
remaining->tv_nsec = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void thrd_yield(void)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
Sleep(0);
|
||||
#else
|
||||
sched_yield();
|
||||
#endif
|
||||
}
|
||||
|
||||
int tss_create(tss_t *key, tss_dtor_t dtor)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
/* FIXME: The destructor function is not supported yet... */
|
||||
if (dtor != NULL)
|
||||
{
|
||||
return thrd_error;
|
||||
}
|
||||
*key = TlsAlloc();
|
||||
if (*key == TLS_OUT_OF_INDEXES)
|
||||
{
|
||||
return thrd_error;
|
||||
}
|
||||
#else
|
||||
if (pthread_key_create(key, dtor) != 0)
|
||||
{
|
||||
return thrd_error;
|
||||
}
|
||||
#endif
|
||||
return thrd_success;
|
||||
}
|
||||
|
||||
void tss_delete(tss_t key)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
TlsFree(key);
|
||||
#else
|
||||
pthread_key_delete(key);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *tss_get(tss_t key)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
return TlsGetValue(key);
|
||||
#else
|
||||
return pthread_getspecific(key);
|
||||
#endif
|
||||
}
|
||||
|
||||
int tss_set(tss_t key, void *val)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
if (TlsSetValue(key, val) == 0)
|
||||
{
|
||||
return thrd_error;
|
||||
}
|
||||
#else
|
||||
if (pthread_setspecific(key, val) != 0)
|
||||
{
|
||||
return thrd_error;
|
||||
}
|
||||
#endif
|
||||
return thrd_success;
|
||||
}
|
||||
|
||||
#if defined(_TTHREAD_EMULATE_CLOCK_GETTIME_)
|
||||
int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
struct _timeb tb;
|
||||
_ftime(&tb);
|
||||
ts->tv_sec = (time_t)tb.time;
|
||||
ts->tv_nsec = 1000000L * (long)tb.millitm;
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
ts->tv_sec = (time_t)tv.tv_sec;
|
||||
ts->tv_nsec = 1000L * (long)tv.tv_usec;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif // _TTHREAD_EMULATE_CLOCK_GETTIME_
|
||||
|
|
@ -0,0 +1,443 @@
|
|||
/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; -*-
|
||||
Copyright (c) 2012 Marcus Geelnard
|
||||
|
||||
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 _TINYCTHREAD_H_
|
||||
#define _TINYCTHREAD_H_
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @mainpage TinyCThread API Reference
|
||||
*
|
||||
* @section intro_sec Introduction
|
||||
* TinyCThread is a minimal, portable implementation of basic threading
|
||||
* classes for C.
|
||||
*
|
||||
* They closely mimic the functionality and naming of the C11 standard, and
|
||||
* should be easily replaceable with the corresponding standard variants.
|
||||
*
|
||||
* @section port_sec Portability
|
||||
* The Win32 variant uses the native Win32 API for implementing the thread
|
||||
* classes, while for other systems, the POSIX threads API (pthread) is used.
|
||||
*
|
||||
* @section misc_sec Miscellaneous
|
||||
* The following special keywords are available: #_Thread_local.
|
||||
*
|
||||
* For more detailed information, browse the different sections of this
|
||||
* documentation. A good place to start is:
|
||||
* tinycthread.h.
|
||||
*/
|
||||
|
||||
/* Which platform are we on? */
|
||||
#if !defined(_TTHREAD_PLATFORM_DEFINED_)
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
|
||||
#define _TTHREAD_WIN32_
|
||||
#else
|
||||
#define _TTHREAD_POSIX_
|
||||
#endif
|
||||
#define _TTHREAD_PLATFORM_DEFINED_
|
||||
#endif
|
||||
|
||||
/* Activate some POSIX functionality (e.g. clock_gettime and recursive mutexes) */
|
||||
#if defined(_TTHREAD_POSIX_)
|
||||
#undef _FEATURES_H
|
||||
#if !defined(_GNU_SOURCE)
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#if !defined(_POSIX_C_SOURCE) || ((_POSIX_C_SOURCE - 0) < 199309L)
|
||||
#undef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
#endif
|
||||
#if !defined(_XOPEN_SOURCE) || ((_XOPEN_SOURCE - 0) < 500)
|
||||
#undef _XOPEN_SOURCE
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Generic includes */
|
||||
#include <time.h>
|
||||
|
||||
/* Platform specific includes */
|
||||
#if defined(_TTHREAD_POSIX_)
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
#elif defined(_TTHREAD_WIN32_)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define __UNDEF_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#ifdef __UNDEF_LEAN_AND_MEAN
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#undef __UNDEF_LEAN_AND_MEAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Workaround for missing TIME_UTC: If time.h doesn't provide TIME_UTC,
|
||||
it's quite likely that libc does not support it either. Hence, fall back to
|
||||
the only other supported time specifier: CLOCK_REALTIME (and if that fails,
|
||||
we're probably emulating clock_gettime anyway, so anything goes). */
|
||||
#ifndef TIME_UTC
|
||||
#ifdef CLOCK_REALTIME
|
||||
#define TIME_UTC CLOCK_REALTIME
|
||||
#else
|
||||
#define TIME_UTC 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Workaround for missing clock_gettime (most Windows compilers, afaik) */
|
||||
#if defined(_TTHREAD_WIN32_) || defined(__APPLE_CC__)
|
||||
#define _TTHREAD_EMULATE_CLOCK_GETTIME_
|
||||
/* Emulate struct timespec */
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
struct _ttherad_timespec {
|
||||
time_t tv_sec;
|
||||
long tv_nsec;
|
||||
};
|
||||
#define timespec _ttherad_timespec
|
||||
#endif
|
||||
|
||||
/* Emulate clockid_t */
|
||||
typedef int _tthread_clockid_t;
|
||||
#define clockid_t _tthread_clockid_t
|
||||
|
||||
/* Emulate clock_gettime */
|
||||
int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts);
|
||||
#define clock_gettime _tthread_clock_gettime
|
||||
#ifndef CLOCK_REALTIME
|
||||
#define CLOCK_REALTIME 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/** TinyCThread version (major number). */
|
||||
#define TINYCTHREAD_VERSION_MAJOR 1
|
||||
/** TinyCThread version (minor number). */
|
||||
#define TINYCTHREAD_VERSION_MINOR 1
|
||||
/** TinyCThread version (full version). */
|
||||
#define TINYCTHREAD_VERSION (TINYCTHREAD_VERSION_MAJOR * 100 + TINYCTHREAD_VERSION_MINOR)
|
||||
|
||||
/**
|
||||
* @def _Thread_local
|
||||
* Thread local storage keyword.
|
||||
* A variable that is declared with the @c _Thread_local keyword makes the
|
||||
* value of the variable local to each thread (known as thread-local storage,
|
||||
* or TLS). Example usage:
|
||||
* @code
|
||||
* // This variable is local to each thread.
|
||||
* _Thread_local int variable;
|
||||
* @endcode
|
||||
* @note The @c _Thread_local keyword is a macro that maps to the corresponding
|
||||
* compiler directive (e.g. @c __declspec(thread)).
|
||||
* @note This directive is currently not supported on Mac OS X (it will give
|
||||
* a compiler error), since compile-time TLS is not supported in the Mac OS X
|
||||
* executable format. Also, some older versions of MinGW (before GCC 4.x) do
|
||||
* not support this directive.
|
||||
* @hideinitializer
|
||||
*/
|
||||
|
||||
/* FIXME: Check for a PROPER value of __STDC_VERSION__ to know if we have C11 */
|
||||
#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) && !defined(_Thread_local)
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
|
||||
#define _Thread_local __thread
|
||||
#else
|
||||
#define _Thread_local __declspec(thread)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Macros */
|
||||
#define TSS_DTOR_ITERATIONS 0
|
||||
|
||||
/* Function return values */
|
||||
#define thrd_error 0 /**< The requested operation failed */
|
||||
#define thrd_success 1 /**< The requested operation succeeded */
|
||||
#define thrd_timeout 2 /**< The time specified in the call was reached without acquiring the requested resource */
|
||||
#define thrd_busy 3 /**< The requested operation failed because a tesource requested by a test and return function is already in use */
|
||||
#define thrd_nomem 4 /**< The requested operation failed because it was unable to allocate memory */
|
||||
|
||||
/* Mutex types */
|
||||
#define mtx_plain 1
|
||||
#define mtx_timed 2
|
||||
#define mtx_try 4
|
||||
#define mtx_recursive 8
|
||||
|
||||
/* Mutex */
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
typedef struct {
|
||||
CRITICAL_SECTION mHandle; /* Critical section handle */
|
||||
int mAlreadyLocked; /* TRUE if the mutex is already locked */
|
||||
int mRecursive; /* TRUE if the mutex is recursive */
|
||||
} mtx_t;
|
||||
#else
|
||||
typedef pthread_mutex_t mtx_t;
|
||||
#endif
|
||||
|
||||
/** Create a mutex object.
|
||||
* @param mtx A mutex object.
|
||||
* @param type Bit-mask that must have one of the following six values:
|
||||
* @li @c mtx_plain for a simple non-recursive mutex
|
||||
* @li @c mtx_timed for a non-recursive mutex that supports timeout
|
||||
* @li @c mtx_try for a non-recursive mutex that supports test and return
|
||||
* @li @c mtx_plain | @c mtx_recursive (same as @c mtx_plain, but recursive)
|
||||
* @li @c mtx_timed | @c mtx_recursive (same as @c mtx_timed, but recursive)
|
||||
* @li @c mtx_try | @c mtx_recursive (same as @c mtx_try, but recursive)
|
||||
* @return @ref thrd_success on success, or @ref thrd_error if the request could
|
||||
* not be honored.
|
||||
*/
|
||||
int mtx_init(mtx_t *mtx, int type);
|
||||
|
||||
/** Release any resources used by the given mutex.
|
||||
* @param mtx A mutex object.
|
||||
*/
|
||||
void mtx_destroy(mtx_t *mtx);
|
||||
|
||||
/** Lock the given mutex.
|
||||
* Blocks until the given mutex can be locked. If the mutex is non-recursive, and
|
||||
* the calling thread already has a lock on the mutex, this call will block
|
||||
* forever.
|
||||
* @param mtx A mutex object.
|
||||
* @return @ref thrd_success on success, or @ref thrd_error if the request could
|
||||
* not be honored.
|
||||
*/
|
||||
int mtx_lock(mtx_t *mtx);
|
||||
|
||||
/** NOT YET IMPLEMENTED.
|
||||
*/
|
||||
int mtx_timedlock(mtx_t *mtx, const struct timespec *ts);
|
||||
|
||||
/** Try to lock the given mutex.
|
||||
* The specified mutex shall support either test and return or timeout. If the
|
||||
* mutex is already locked, the function returns without blocking.
|
||||
* @param mtx A mutex object.
|
||||
* @return @ref thrd_success on success, or @ref thrd_busy if the resource
|
||||
* requested is already in use, or @ref thrd_error if the request could not be
|
||||
* honored.
|
||||
*/
|
||||
int mtx_trylock(mtx_t *mtx);
|
||||
|
||||
/** Unlock the given mutex.
|
||||
* @param mtx A mutex object.
|
||||
* @return @ref thrd_success on success, or @ref thrd_error if the request could
|
||||
* not be honored.
|
||||
*/
|
||||
int mtx_unlock(mtx_t *mtx);
|
||||
|
||||
/* Condition variable */
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
typedef struct {
|
||||
HANDLE mEvents[2]; /* Signal and broadcast event HANDLEs. */
|
||||
unsigned int mWaitersCount; /* Count of the number of waiters. */
|
||||
CRITICAL_SECTION mWaitersCountLock; /* Serialize access to mWaitersCount. */
|
||||
} cnd_t;
|
||||
#else
|
||||
typedef pthread_cond_t cnd_t;
|
||||
#endif
|
||||
|
||||
/** Create a condition variable object.
|
||||
* @param cond A condition variable object.
|
||||
* @return @ref thrd_success on success, or @ref thrd_error if the request could
|
||||
* not be honored.
|
||||
*/
|
||||
int cnd_init(cnd_t *cond);
|
||||
|
||||
/** Release any resources used by the given condition variable.
|
||||
* @param cond A condition variable object.
|
||||
*/
|
||||
void cnd_destroy(cnd_t *cond);
|
||||
|
||||
/** Signal a condition variable.
|
||||
* Unblocks one of the threads that are blocked on the given condition variable
|
||||
* at the time of the call. If no threads are blocked on the condition variable
|
||||
* at the time of the call, the function does nothing and return success.
|
||||
* @param cond A condition variable object.
|
||||
* @return @ref thrd_success on success, or @ref thrd_error if the request could
|
||||
* not be honored.
|
||||
*/
|
||||
int cnd_signal(cnd_t *cond);
|
||||
|
||||
/** Broadcast a condition variable.
|
||||
* Unblocks all of the threads that are blocked on the given condition variable
|
||||
* at the time of the call. If no threads are blocked on the condition variable
|
||||
* at the time of the call, the function does nothing and return success.
|
||||
* @param cond A condition variable object.
|
||||
* @return @ref thrd_success on success, or @ref thrd_error if the request could
|
||||
* not be honored.
|
||||
*/
|
||||
int cnd_broadcast(cnd_t *cond);
|
||||
|
||||
/** Wait for a condition variable to become signaled.
|
||||
* The function atomically unlocks the given mutex and endeavors to block until
|
||||
* the given condition variable is signaled by a call to cnd_signal or to
|
||||
* cnd_broadcast. When the calling thread becomes unblocked it locks the mutex
|
||||
* before it returns.
|
||||
* @param cond A condition variable object.
|
||||
* @param mtx A mutex object.
|
||||
* @return @ref thrd_success on success, or @ref thrd_error if the request could
|
||||
* not be honored.
|
||||
*/
|
||||
int cnd_wait(cnd_t *cond, mtx_t *mtx);
|
||||
|
||||
/** Wait for a condition variable to become signaled.
|
||||
* The function atomically unlocks the given mutex and endeavors to block until
|
||||
* the given condition variable is signaled by a call to cnd_signal or to
|
||||
* cnd_broadcast, or until after the specified time. When the calling thread
|
||||
* becomes unblocked it locks the mutex before it returns.
|
||||
* @param cond A condition variable object.
|
||||
* @param mtx A mutex object.
|
||||
* @param xt A point in time at which the request will time out (absolute time).
|
||||
* @return @ref thrd_success upon success, or @ref thrd_timeout if the time
|
||||
* specified in the call was reached without acquiring the requested resource, or
|
||||
* @ref thrd_error if the request could not be honored.
|
||||
*/
|
||||
int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts);
|
||||
|
||||
/* Thread */
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
typedef HANDLE thrd_t;
|
||||
#else
|
||||
typedef pthread_t thrd_t;
|
||||
#endif
|
||||
|
||||
/** Thread start function.
|
||||
* Any thread that is started with the @ref thrd_create() function must be
|
||||
* started through a function of this type.
|
||||
* @param arg The thread argument (the @c arg argument of the corresponding
|
||||
* @ref thrd_create() call).
|
||||
* @return The thread return value, which can be obtained by another thread
|
||||
* by using the @ref thrd_join() function.
|
||||
*/
|
||||
typedef int (*thrd_start_t)(void *arg);
|
||||
|
||||
/** Create a new thread.
|
||||
* @param thr Identifier of the newly created thread.
|
||||
* @param func A function pointer to the function that will be executed in
|
||||
* the new thread.
|
||||
* @param arg An argument to the thread function.
|
||||
* @return @ref thrd_success on success, or @ref thrd_nomem if no memory could
|
||||
* be allocated for the thread requested, or @ref thrd_error if the request
|
||||
* could not be honored.
|
||||
* @note A thread’s identifier may be reused for a different thread once the
|
||||
* original thread has exited and either been detached or joined to another
|
||||
* thread.
|
||||
*/
|
||||
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
|
||||
|
||||
/** Identify the calling thread.
|
||||
* @return The identifier of the calling thread.
|
||||
*/
|
||||
thrd_t thrd_current(void);
|
||||
|
||||
/** NOT YET IMPLEMENTED.
|
||||
*/
|
||||
int thrd_detach(thrd_t thr);
|
||||
|
||||
/** Compare two thread identifiers.
|
||||
* The function determines if two thread identifiers refer to the same thread.
|
||||
* @return Zero if the two thread identifiers refer to different threads.
|
||||
* Otherwise a nonzero value is returned.
|
||||
*/
|
||||
int thrd_equal(thrd_t thr0, thrd_t thr1);
|
||||
|
||||
/** Terminate execution of the calling thread.
|
||||
* @param res Result code of the calling thread.
|
||||
*/
|
||||
void thrd_exit(int res);
|
||||
|
||||
/** Wait for a thread to terminate.
|
||||
* The function joins the given thread with the current thread by blocking
|
||||
* until the other thread has terminated.
|
||||
* @param thr The thread to join with.
|
||||
* @param res If this pointer is not NULL, the function will store the result
|
||||
* code of the given thread in the integer pointed to by @c res.
|
||||
* @return @ref thrd_success on success, or @ref thrd_error if the request could
|
||||
* not be honored.
|
||||
*/
|
||||
int thrd_join(thrd_t thr, int *res);
|
||||
|
||||
/** Put the calling thread to sleep.
|
||||
* Suspend execution of the calling thread.
|
||||
* @param time_point A point in time at which the thread will resume (absolute time).
|
||||
* @param remaining If non-NULL, this parameter will hold the remaining time until
|
||||
* time_point upon return. This will typically be zero, but if
|
||||
* the thread was woken up by a signal that is not ignored before
|
||||
* time_point was reached @c remaining will hold a positive
|
||||
* time.
|
||||
* @return 0 (zero) on successful sleep, or -1 if an interrupt occurred.
|
||||
*/
|
||||
int thrd_sleep(const struct timespec *time_point, struct timespec *remaining);
|
||||
|
||||
/** Yield execution to another thread.
|
||||
* Permit other threads to run, even if the current thread would ordinarily
|
||||
* continue to run.
|
||||
*/
|
||||
void thrd_yield(void);
|
||||
|
||||
/* Thread local storage */
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
typedef DWORD tss_t;
|
||||
#else
|
||||
typedef pthread_key_t tss_t;
|
||||
#endif
|
||||
|
||||
/** Destructor function for a thread-specific storage.
|
||||
* @param val The value of the destructed thread-specific storage.
|
||||
*/
|
||||
typedef void (*tss_dtor_t)(void *val);
|
||||
|
||||
/** Create a thread-specific storage.
|
||||
* @param key The unique key identifier that will be set if the function is
|
||||
* successful.
|
||||
* @param dtor Destructor function. This can be NULL.
|
||||
* @return @ref thrd_success on success, or @ref thrd_error if the request could
|
||||
* not be honored.
|
||||
* @note The destructor function is not supported under Windows. If @c dtor is
|
||||
* not NULL when calling this function under Windows, the function will fail
|
||||
* and return @ref thrd_error.
|
||||
*/
|
||||
int tss_create(tss_t *key, tss_dtor_t dtor);
|
||||
|
||||
/** Delete a thread-specific storage.
|
||||
* The function releases any resources used by the given thread-specific
|
||||
* storage.
|
||||
* @param key The key that shall be deleted.
|
||||
*/
|
||||
void tss_delete(tss_t key);
|
||||
|
||||
/** Get the value for a thread-specific storage.
|
||||
* @param key The thread-specific storage identifier.
|
||||
* @return The value for the current thread held in the given thread-specific
|
||||
* storage.
|
||||
*/
|
||||
void *tss_get(tss_t key);
|
||||
|
||||
/** Set the value for a thread-specific storage.
|
||||
* @param key The thread-specific storage identifier.
|
||||
* @param val The value of the thread-specific storage to set for the current
|
||||
* thread.
|
||||
* @return @ref thrd_success on success, or @ref thrd_error if the request could
|
||||
* not be honored.
|
||||
*/
|
||||
int tss_set(tss_t key, void *val);
|
||||
|
||||
|
||||
#endif /* _TINYTHREAD_H_ */
|
||||
|
|
@ -0,0 +1,247 @@
|
|||
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006-2008 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. The name of the author may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
#define _MSC_STDINT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
# include <wchar.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||
#ifndef _W64
|
||||
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// 7.18.1 Integer types
|
||||
|
||||
// 7.18.1.1 Exact-width integer types
|
||||
|
||||
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
|
||||
// realize that, e.g. char has the same size as __int8
|
||||
// so we give up on __intX for them.
|
||||
#if (_MSC_VER < 1300)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#endif
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
|
||||
// 7.18.1.2 Minimum-width integer types
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
// 7.18.1.3 Fastest minimum-width integer types
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
// 7.18.1.4 Integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
typedef signed __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else // _WIN64 ][
|
||||
typedef _W64 signed int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.1.5 Greatest-width integer types
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
|
||||
// 7.18.2 Limits of specified-width integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||
|
||||
// 7.18.2.1 Limits of exact-width integer types
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
|
||||
// 7.18.2.2 Limits of minimum-width integer types
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.2.5 Limits of greatest-width integer types
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// 7.18.3 Limits of other integer types
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
#endif // SIZE_MAX ]
|
||||
|
||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||
#ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
#endif // WCHAR_MIN ]
|
||||
#ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif // WCHAR_MAX ]
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif // __STDC_LIMIT_MACROS ]
|
||||
|
||||
|
||||
// 7.18.4 Limits of other integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
#define INTMAX_C INT64_C
|
||||
#define UINTMAX_C UINT64_C
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
|
||||
#endif // _MSC_STDINT_H_ ]
|
|
@ -0,0 +1,120 @@
|
|||
//
|
||||
// File: vk_platform.h
|
||||
//
|
||||
/*
|
||||
** Copyright (c) 2014-2015 The Khronos Group Inc.
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef VK_PLATFORM_H_
|
||||
#define VK_PLATFORM_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
/*
|
||||
***************************************************************************************************
|
||||
* Platform-specific directives and type declarations
|
||||
***************************************************************************************************
|
||||
*/
|
||||
|
||||
/* Platform-specific calling convention macros.
|
||||
*
|
||||
* Platforms should define these so that Vulkan clients call Vulkan commands
|
||||
* with the same calling conventions that the Vulkan implementation expects.
|
||||
*
|
||||
* VKAPI_ATTR - Placed before the return type in function declarations.
|
||||
* Useful for C++11 and GCC/Clang-style function attribute syntax.
|
||||
* VKAPI_CALL - Placed after the return type in function declarations.
|
||||
* Useful for MSVC-style calling convention syntax.
|
||||
* VKAPI_PTR - Placed between the '(' and '*' in function pointer types.
|
||||
*
|
||||
* Function declaration: VKAPI_ATTR void VKAPI_CALL vkCommand(void);
|
||||
* Function pointer type: typedef void (VKAPI_PTR *PFN_vkCommand)(void);
|
||||
*/
|
||||
#if defined(_WIN32)
|
||||
// On Windows, Vulkan commands use the stdcall convention
|
||||
#define VKAPI_ATTR
|
||||
#define VKAPI_CALL __stdcall
|
||||
#define VKAPI_PTR VKAPI_CALL
|
||||
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
|
||||
#error "Vulkan isn't supported for the 'armeabi' NDK ABI"
|
||||
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
|
||||
// On Android 32-bit ARM targets, Vulkan functions use the "hardfloat"
|
||||
// calling convention, i.e. float parameters are passed in registers. This
|
||||
// is true even if the rest of the application passes floats on the stack,
|
||||
// as it does by default when compiling for the armeabi-v7a NDK ABI.
|
||||
#define VKAPI_ATTR __attribute__((pcs("aapcs-vfp")))
|
||||
#define VKAPI_CALL
|
||||
#define VKAPI_PTR VKAPI_ATTR
|
||||
#else
|
||||
// On other platforms, use the default calling convention
|
||||
#define VKAPI_ATTR
|
||||
#define VKAPI_CALL
|
||||
#define VKAPI_PTR
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if !defined(VK_NO_STDINT_H)
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1600)
|
||||
typedef signed __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#endif // !defined(VK_NO_STDINT_H)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
// Platform-specific headers required by platform window system extensions.
|
||||
// These are enabled prior to #including "vulkan.h". The same enable then
|
||||
// controls inclusion of the extension interfaces in vulkan.h.
|
||||
|
||||
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
||||
#include <android/native_window.h>
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_MIR_KHR
|
||||
#include <mir_toolkit/client_types.h>
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
||||
#include <wayland-client.h>
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_WIN32_KHR
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_XCB_KHR
|
||||
#include <xcb/xcb.h>
|
||||
#endif
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,34 @@
|
|||
|
||||
set(glfw_DOCS_SOURCES
|
||||
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h"
|
||||
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h"
|
||||
"${GLFW_SOURCE_DIR}/docs/main.dox"
|
||||
"${GLFW_SOURCE_DIR}/docs/news.dox"
|
||||
"${GLFW_SOURCE_DIR}/docs/moving.dox"
|
||||
"${GLFW_SOURCE_DIR}/docs/quick.dox"
|
||||
"${GLFW_SOURCE_DIR}/docs/compile.dox"
|
||||
"${GLFW_SOURCE_DIR}/docs/build.dox"
|
||||
"${GLFW_SOURCE_DIR}/docs/intro.dox"
|
||||
"${GLFW_SOURCE_DIR}/docs/context.dox"
|
||||
"${GLFW_SOURCE_DIR}/docs/monitor.dox"
|
||||
"${GLFW_SOURCE_DIR}/docs/window.dox"
|
||||
"${GLFW_SOURCE_DIR}/docs/input.dox"
|
||||
"${GLFW_SOURCE_DIR}/docs/vulkan.dox"
|
||||
"${GLFW_SOURCE_DIR}/docs/compat.dox")
|
||||
|
||||
if (GLFW_DOCUMENT_INTERNALS)
|
||||
list(APPEND glfw_DOCS_SOURCES
|
||||
"${GLFW_SOURCE_DIR}/docs/internal.dox"
|
||||
"${GLFW_SOURCE_DIR}/src/internal.h")
|
||||
endif()
|
||||
|
||||
foreach(arg ${glfw_DOCS_SOURCES})
|
||||
set(GLFW_DOCS_SOURCES "${GLFW_DOCS_SOURCES} ${arg}")
|
||||
endforeach()
|
||||
|
||||
configure_file(Doxyfile.in Doxyfile @ONLY)
|
||||
|
||||
add_custom_target(docs ALL "${DOXYGEN_EXECUTABLE}"
|
||||
WORKING_DIRECTORY "${GLFW_BINARY_DIR}/docs"
|
||||
COMMENT "Generating HTML documentation" VERBATIM)
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,188 @@
|
|||
<doxygenlayout version="1.0">
|
||||
<!-- Generated by doxygen 1.8.3.1 -->
|
||||
<!-- Navigation index tabs for HTML output -->
|
||||
<navindex>
|
||||
<tab type="mainpage" visible="yes" title="Introduction"/>
|
||||
<tab type="pages" visible="yes" title="Guides" intro=""/>
|
||||
<tab type="modules" visible="yes" title="Reference" intro=""/>
|
||||
<tab type="namespaces" visible="yes" title="">
|
||||
<tab type="namespacelist" visible="yes" title="" intro=""/>
|
||||
<tab type="namespacemembers" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="classes" visible="no" title="">
|
||||
<tab type="classlist" visible="yes" title="" intro=""/>
|
||||
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
|
||||
<tab type="hierarchy" visible="yes" title="" intro=""/>
|
||||
<tab type="classmembers" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="files" visible="yes" title="Header Files">
|
||||
<tab type="filelist" visible="yes" title="" intro=""/>
|
||||
<tab type="globals" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="examples" visible="yes" title="" intro=""/>
|
||||
</navindex>
|
||||
|
||||
<!-- Layout definition for a class page -->
|
||||
<class>
|
||||
<briefdescription visible="yes"/>
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<inheritancegraph visible="$CLASS_GRAPH"/>
|
||||
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
|
||||
<memberdecl>
|
||||
<nestedclasses visible="yes" title=""/>
|
||||
<publictypes title=""/>
|
||||
<publicslots title=""/>
|
||||
<signals title=""/>
|
||||
<publicmethods title=""/>
|
||||
<publicstaticmethods title=""/>
|
||||
<publicattributes title=""/>
|
||||
<publicstaticattributes title=""/>
|
||||
<protectedtypes title=""/>
|
||||
<protectedslots title=""/>
|
||||
<protectedmethods title=""/>
|
||||
<protectedstaticmethods title=""/>
|
||||
<protectedattributes title=""/>
|
||||
<protectedstaticattributes title=""/>
|
||||
<packagetypes title=""/>
|
||||
<packagemethods title=""/>
|
||||
<packagestaticmethods title=""/>
|
||||
<packageattributes title=""/>
|
||||
<packagestaticattributes title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
<privatetypes title=""/>
|
||||
<privateslots title=""/>
|
||||
<privatemethods title=""/>
|
||||
<privatestaticmethods title=""/>
|
||||
<privateattributes title=""/>
|
||||
<privatestaticattributes title=""/>
|
||||
<friends title=""/>
|
||||
<related title="" subtitle=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<constructors title=""/>
|
||||
<functions title=""/>
|
||||
<related title=""/>
|
||||
<variables title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
</memberdef>
|
||||
<allmemberslink visible="yes"/>
|
||||
<usedfiles visible="$SHOW_USED_FILES"/>
|
||||
<authorsection visible="yes"/>
|
||||
</class>
|
||||
|
||||
<!-- Layout definition for a namespace page -->
|
||||
<namespace>
|
||||
<briefdescription visible="yes"/>
|
||||
<memberdecl>
|
||||
<nestednamespaces visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</namespace>
|
||||
|
||||
<!-- Layout definition for a file page -->
|
||||
<file>
|
||||
<briefdescription visible="yes"/>
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<includegraph visible="$INCLUDE_GRAPH"/>
|
||||
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
|
||||
<sourcelink visible="yes"/>
|
||||
<memberdecl>
|
||||
<classes visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection/>
|
||||
</file>
|
||||
|
||||
<!-- Layout definition for a group page -->
|
||||
<group>
|
||||
<briefdescription visible="yes"/>
|
||||
<detaileddescription title="Description"/>
|
||||
<groupgraph visible="$GROUP_GRAPHS"/>
|
||||
<memberdecl>
|
||||
<nestedgroups visible="yes" title=""/>
|
||||
<dirs visible="yes" title=""/>
|
||||
<files visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<memberdef>
|
||||
<pagedocs/>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</group>
|
||||
|
||||
<!-- Layout definition for a directory page -->
|
||||
<directory>
|
||||
<briefdescription visible="yes"/>
|
||||
<directorygraph visible="yes"/>
|
||||
<memberdecl>
|
||||
<dirs visible="yes"/>
|
||||
<files visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
</directory>
|
||||
</doxygenlayout>
|
|
@ -0,0 +1,373 @@
|
|||
/*!
|
||||
|
||||
@page build_guide Building applications
|
||||
|
||||
@tableofcontents
|
||||
|
||||
This is about compiling and linking applications that use GLFW. For information on
|
||||
how to write such applications, start with the
|
||||
[introductory tutorial](@ref quick_guide). For information on how to compile
|
||||
the GLFW library itself, see @ref compile_guide.
|
||||
|
||||
This is not a tutorial on compilation or linking. It assumes basic
|
||||
understanding of how to compile and link a C program as well as how to use the
|
||||
specific compiler of your chosen development environment. The compilation
|
||||
and linking process should be explained in your C programming material and in
|
||||
the documentation for your development environment.
|
||||
|
||||
@section build_include Including the GLFW header file
|
||||
|
||||
In the source files of your application where you use OpenGL or GLFW, you should
|
||||
include the GLFW header file, i.e.:
|
||||
|
||||
@code
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
The GLFW header declares the GLFW API and by default also includes the OpenGL
|
||||
header of your development environment, which in turn defines all the constants,
|
||||
types and function prototypes of the OpenGL API.
|
||||
|
||||
The GLFW header also defines everything necessary for your OpenGL header to
|
||||
function. For example, under Windows you are normally required to include
|
||||
`windows.h` before the OpenGL header, which would pollute your code namespace
|
||||
with the entire Win32 API.
|
||||
|
||||
Instead, the GLFW header takes care of this for you, not by including
|
||||
`windows.h`, but by duplicating only the very few necessary parts of it. It
|
||||
does this only when needed, so if `windows.h` _is_ included, the GLFW header
|
||||
does not try to redefine those symbols. The reverse is not true, i.e.
|
||||
`windows.h` cannot cope if any of its symbols have already been defined.
|
||||
|
||||
In other words:
|
||||
|
||||
- Do _not_ include the OpenGL headers yourself, as GLFW does this for you
|
||||
- Do _not_ include `windows.h` or other platform-specific headers unless you
|
||||
plan on using those APIs directly
|
||||
- If you _do_ need to include such headers, do it _before_ including
|
||||
the GLFW header and it will handle this
|
||||
|
||||
If you are using an OpenGL extension loading library such as
|
||||
[glad](https://github.com/Dav1dde/glad), the extension loader header should
|
||||
either be included _before_ the GLFW one, or the @ref GLFW_INCLUDE_NONE macro
|
||||
(described below) should be defined.
|
||||
|
||||
|
||||
@subsection build_macros GLFW header option macros
|
||||
|
||||
These macros may be defined before the inclusion of the GLFW header and affect
|
||||
its behavior.
|
||||
|
||||
@anchor GLFW_DLL
|
||||
__GLFW_DLL__ is required on Windows when using the GLFW DLL, to tell the
|
||||
compiler that the GLFW functions are defined in a DLL.
|
||||
|
||||
The following macros control which OpenGL or OpenGL ES API header is included.
|
||||
Only one of these may be defined at a time.
|
||||
|
||||
@anchor GLFW_INCLUDE_GLCOREARB
|
||||
__GLFW_INCLUDE_GLCOREARB__ makes the GLFW header include the modern
|
||||
`GL/glcorearb.h` header (`OpenGL/gl3.h` on macOS) instead of the regular OpenGL
|
||||
header.
|
||||
|
||||
@anchor GLFW_INCLUDE_ES1
|
||||
__GLFW_INCLUDE_ES1__ makes the GLFW header include the OpenGL ES 1.x `GLES/gl.h`
|
||||
header instead of the regular OpenGL header.
|
||||
|
||||
@anchor GLFW_INCLUDE_ES2
|
||||
__GLFW_INCLUDE_ES2__ makes the GLFW header include the OpenGL ES 2.0
|
||||
`GLES2/gl2.h` header instead of the regular OpenGL header.
|
||||
|
||||
@anchor GLFW_INCLUDE_ES3
|
||||
__GLFW_INCLUDE_ES3__ makes the GLFW header include the OpenGL ES 3.0
|
||||
`GLES3/gl3.h` header instead of the regular OpenGL header.
|
||||
|
||||
@anchor GLFW_INCLUDE_ES31
|
||||
__GLFW_INCLUDE_ES31__ makes the GLFW header include the OpenGL ES 3.1
|
||||
`GLES3/gl31.h` header instead of the regular OpenGL header.
|
||||
|
||||
@anchor GLFW_INCLUDE_ES32
|
||||
__GLFW_INCLUDE_ES31__ makes the GLFW header include the OpenGL ES 3.2
|
||||
`GLES3/gl32.h` header instead of the regular OpenGL header.
|
||||
|
||||
@anchor GLFW_INCLUDE_NONE
|
||||
__GLFW_INCLUDE_NONE__ makes the GLFW header not include any OpenGL or OpenGL ES
|
||||
API header. This is useful in combination with an extension loading library.
|
||||
|
||||
If none of the above inclusion macros are defined, the standard OpenGL `GL/gl.h`
|
||||
header (`OpenGL/gl.h` on macOS) is included.
|
||||
|
||||
The following macros control the inclusion of additional API headers. Any
|
||||
number of these may be defined simultaneously, and/or together with one of the
|
||||
above macros.
|
||||
|
||||
@anchor GLFW_INCLUDE_VULKAN
|
||||
__GLFW_INCLUDE_VULKAN__ makes the GLFW header include the Vulkan
|
||||
`vulkan/vulkan.h` header in addition to any selected OpenGL or OpenGL ES header.
|
||||
|
||||
@anchor GLFW_INCLUDE_GLEXT
|
||||
__GLFW_INCLUDE_GLEXT__ makes the GLFW header include the appropriate extension
|
||||
header for the OpenGL or OpenGL ES header selected above after and in addition
|
||||
to that header.
|
||||
|
||||
@anchor GLFW_INCLUDE_GLU
|
||||
__GLFW_INCLUDE_GLU__ makes the header include the GLU header in addition to the
|
||||
header selected above. This should only be used with the standard OpenGL header
|
||||
and only for compatibility with legacy code. GLU has been deprecated and should
|
||||
not be used in new code.
|
||||
|
||||
@note GLFW does not provide any of the API headers mentioned above. They must
|
||||
be provided by your development environment or your OpenGL, OpenGL ES or Vulkan
|
||||
SDK.
|
||||
|
||||
@note None of these macros may be defined during the compilation of GLFW itself.
|
||||
If your build includes GLFW and you define any these in your build files, make
|
||||
sure they are not applied to the GLFW sources.
|
||||
|
||||
|
||||
@section build_link Link with the right libraries
|
||||
|
||||
GLFW is essentially a wrapper of various platform-specific APIs and therefore
|
||||
needs to link against many different system libraries. If you are using GLFW as
|
||||
a shared library / dynamic library / DLL then it takes care of these links.
|
||||
However, if you are using GLFW as a static library then your executable will
|
||||
need to link against these libraries.
|
||||
|
||||
On Windows and macOS, the list of system libraries is static and can be
|
||||
hard-coded into your build environment. See the section for your development
|
||||
environment below. On Linux and other Unix-like operating systems, the list
|
||||
varies but can be retrieved in various ways as described below.
|
||||
|
||||
A good general introduction to linking is
|
||||
[Beginner's Guide to Linkers](http://www.lurklurk.org/linkers/linkers.html) by
|
||||
David Drysdale.
|
||||
|
||||
|
||||
@subsection build_link_win32 With MinGW or Visual C++ on Windows
|
||||
|
||||
The static version of the GLFW library is named `glfw3`. When using this
|
||||
version, it is also necessary to link with some libraries that GLFW uses.
|
||||
|
||||
When linking an application under Windows that uses the static version of GLFW,
|
||||
you must link with `opengl32`. On some versions of MinGW, you must also
|
||||
explicitly link with `gdi32`, while other versions of MinGW include it in the
|
||||
set of default libraries along with other dependencies like `user32` and
|
||||
`kernel32`. If you are using GLU, you must also link with `glu32`.
|
||||
|
||||
The link library for the GLFW DLL is named `glfw3dll`. When compiling an
|
||||
application that uses the DLL version of GLFW, you need to define the @ref
|
||||
GLFW_DLL macro _before_ any inclusion of the GLFW header. This can be done
|
||||
either with a compiler switch or by defining it in your source code.
|
||||
|
||||
An application using the GLFW DLL does not need to link against any of its
|
||||
dependencies, but you still have to link against `opengl32` if your application
|
||||
uses OpenGL and `glu32` if it uses GLU.
|
||||
|
||||
|
||||
@subsection build_link_cmake_source With CMake and GLFW source
|
||||
|
||||
This section is about using CMake to compile and link GLFW along with your
|
||||
application. If you want to use an installed binary instead, see @ref
|
||||
build_link_cmake_package.
|
||||
|
||||
With just a few changes to your `CMakeLists.txt` you can have the GLFW source
|
||||
tree built along with your application.
|
||||
|
||||
When including GLFW as part of your build, you probably don't want to build the
|
||||
GLFW tests, examples and documentation. To disable these, set the corresponding
|
||||
cache variables before adding the GLFW source tree.
|
||||
|
||||
@code
|
||||
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
|
||||
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||
@endcode
|
||||
|
||||
Then add the root directory of the GLFW source tree to your project. This
|
||||
will add the `glfw` target and the necessary cache variables to your project.
|
||||
|
||||
@code{.cmake}
|
||||
add_subdirectory(path/to/glfw)
|
||||
@endcode
|
||||
|
||||
Once GLFW has been added to the project, link against it with the `glfw` target.
|
||||
This adds all link-time dependencies of GLFW as it is currently configured,
|
||||
the include directory for the GLFW header and, when applicable, the @ref
|
||||
GLFW_DLL macro.
|
||||
|
||||
@code{.cmake}
|
||||
target_link_libraries(myapp glfw)
|
||||
@endcode
|
||||
|
||||
Note that the dependencies do not include OpenGL or GLU, as GLFW loads any
|
||||
OpenGL, OpenGL ES or Vulkan libraries it needs at runtime and does not use GLU.
|
||||
If your application calls OpenGL directly, instead of using a modern
|
||||
[extension loader library](@ref context_glext_auto) you can find it by requiring
|
||||
the OpenGL package.
|
||||
|
||||
@code{.cmake}
|
||||
find_package(OpenGL REQUIRED)
|
||||
@endcode
|
||||
|
||||
If OpenGL is found, the `OPENGL_FOUND` variable is true and the
|
||||
`OPENGL_INCLUDE_DIR` and `OPENGL_gl_LIBRARY` cache variables can be used.
|
||||
|
||||
@code{.cmake}
|
||||
target_include_directories(myapp ${OPENGL_INCLUDE_DIR})
|
||||
target_link_libraries(myapp ${OPENGL_gl_LIBRARY})
|
||||
@endcode
|
||||
|
||||
The OpenGL CMake package also looks for GLU. If GLU is found, the
|
||||
`OPENGL_GLU_FOUND` variable is true and the `OPENGL_INCLUDE_DIR` and
|
||||
`OPENGL_glu_LIBRARY` cache variables can be used.
|
||||
|
||||
@code{.cmake}
|
||||
target_link_libraries(myapp ${OPENGL_glu_LIBRARY})
|
||||
@endcode
|
||||
|
||||
@note GLU has been deprecated and should not be used in new code, but some
|
||||
legacy code requires it. See the [section on GLU](@ref moving_glu) in the
|
||||
transition guide for suggested replacements.
|
||||
|
||||
|
||||
@subsection build_link_cmake_package With CMake and installed GLFW binaries
|
||||
|
||||
This section is about using CMake to link GLFW after it has been built and
|
||||
installed. If you want to build it along with your application instead, see
|
||||
@ref build_link_cmake_source.
|
||||
|
||||
With just a few changes to your `CMakeLists.txt`, you can locate the package and
|
||||
target files generated when GLFW is installed.
|
||||
|
||||
@code{.cmake}
|
||||
find_package(glfw3 3.3 REQUIRED)
|
||||
@endcode
|
||||
|
||||
Once GLFW has been added to the project, link against it with the `glfw` target.
|
||||
This adds all link-time dependencies of GLFW as it is currently configured,
|
||||
the include directory for the GLFW header and, when applicable, the @ref
|
||||
GLFW_DLL macro.
|
||||
|
||||
@code{.cmake}
|
||||
target_link_libraries(myapp glfw)
|
||||
@endcode
|
||||
|
||||
Note that the dependencies do not include OpenGL or GLU, as GLFW loads any
|
||||
OpenGL, OpenGL ES or Vulkan libraries it needs at runtime and does not use GLU.
|
||||
If your application calls OpenGL directly, instead of using a modern
|
||||
[extension loader library](@ref context_glext_auto) you can find it by requiring
|
||||
the OpenGL package.
|
||||
|
||||
@code{.cmake}
|
||||
find_package(OpenGL REQUIRED)
|
||||
@endcode
|
||||
|
||||
If OpenGL is found, the `OPENGL_FOUND` variable is true and the
|
||||
`OPENGL_INCLUDE_DIR` and `OPENGL_gl_LIBRARY` cache variables can be used.
|
||||
|
||||
@code{.cmake}
|
||||
target_include_directories(myapp ${OPENGL_INCLUDE_DIR})
|
||||
target_link_libraries(myapp ${OPENGL_gl_LIBRARY})
|
||||
@endcode
|
||||
|
||||
The OpenGL CMake package also looks for GLU. If GLU is found, the
|
||||
`OPENGL_GLU_FOUND` variable is true and the `OPENGL_INCLUDE_DIR` and
|
||||
`OPENGL_glu_LIBRARY` cache variables can be used.
|
||||
|
||||
@code{.cmake}
|
||||
target_link_libraries(myapp ${OPENGL_glu_LIBRARY})
|
||||
@endcode
|
||||
|
||||
@note GLU has been deprecated and should not be used in new code, but some
|
||||
legacy code requires it. See the [section on GLU](@ref moving_glu) in the
|
||||
transition guide for suggested replacements.
|
||||
|
||||
|
||||
@subsection build_link_pkgconfig With makefiles and pkg-config on Unix
|
||||
|
||||
GLFW supports [pkg-config](http://www.freedesktop.org/wiki/Software/pkg-config/),
|
||||
and the `glfw3.pc` pkg-config file is generated when the GLFW library is built
|
||||
and is installed along with it. A pkg-config file describes all necessary
|
||||
compile-time and link-time flags and dependencies needed to use a library. When
|
||||
they are updated or if they differ between systems, you will get the correct
|
||||
ones automatically.
|
||||
|
||||
A typical compile and link command-line when using the static version of the
|
||||
GLFW library may look like this:
|
||||
|
||||
@code{.sh}
|
||||
cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --static --libs glfw3`
|
||||
@endcode
|
||||
|
||||
If you are using the shared version of the GLFW library, simply omit the
|
||||
`--static` flag.
|
||||
|
||||
@code{.sh}
|
||||
cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --libs glfw3`
|
||||
@endcode
|
||||
|
||||
You can also use the `glfw3.pc` file without installing it first, by using the
|
||||
`PKG_CONFIG_PATH` environment variable.
|
||||
|
||||
@code{.sh}
|
||||
env PKG_CONFIG_PATH=path/to/glfw/src cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --libs glfw3`
|
||||
@endcode
|
||||
|
||||
The dependencies do not include OpenGL or GLU, as GLFW loads any OpenGL, OpenGL
|
||||
ES or Vulkan libraries it needs at runtime and does not use GLU. On macOS, GLU
|
||||
is built into the OpenGL framework, so if you need GLU you don't need to do
|
||||
anything extra. If you need GLU and are using Linux or BSD, you should add the
|
||||
`glu` pkg-config package.
|
||||
|
||||
@code{.sh}
|
||||
cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --libs glfw3 glu`
|
||||
@endcode
|
||||
|
||||
@note GLU has been deprecated and should not be used in new code, but some
|
||||
legacy code requires it. See the [section on GLU](@ref moving_glu) in the
|
||||
transition guide for suggested replacements.
|
||||
|
||||
If you are using the static version of the GLFW library, make sure you don't
|
||||
link statically against GLU.
|
||||
|
||||
@code{.sh}
|
||||
cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --static --libs glfw3` `pkg-config --libs glu`
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection build_link_xcode With Xcode on macOS
|
||||
|
||||
If you are using the dynamic library version of GLFW, simply add it to the
|
||||
project dependencies.
|
||||
|
||||
If you are using the static library version of GLFW, add it and the Cocoa,
|
||||
OpenGL, IOKit and CoreVideo frameworks to the project as dependencies. They can
|
||||
all be found in `/System/Library/Frameworks`.
|
||||
|
||||
|
||||
@subsection build_link_osx With command-line on macOS
|
||||
|
||||
It is recommended that you use [pkg-config](@ref build_link_pkgconfig) when
|
||||
building from the command line on macOS. That way you will get any new
|
||||
dependencies added automatically. If you still wish to build manually, you need
|
||||
to add the required frameworks and libraries to your command-line yourself using
|
||||
the `-l` and `-framework` switches.
|
||||
|
||||
If you are using the dynamic GLFW library, which is named `libglfw.3.dylib`, do:
|
||||
|
||||
@code{.sh}
|
||||
cc -o myprog myprog.c -lglfw -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo
|
||||
@endcode
|
||||
|
||||
If you are using the static library, named `libglfw3.a`, substitute `-lglfw3`
|
||||
for `-lglfw`.
|
||||
|
||||
Note that you do not add the `.framework` extension to a framework when linking
|
||||
against it from the command-line.
|
||||
|
||||
The OpenGL framework contains both the OpenGL and GLU APIs, so there is nothing
|
||||
special to do when using GLU. Also note that even though your machine may have
|
||||
`libGL`-style OpenGL libraries, they are for use with the X Window System and
|
||||
will _not_ work with the macOS native version of GLFW.
|
||||
|
||||
*/
|
|
@ -0,0 +1,231 @@
|
|||
/*!
|
||||
|
||||
@page compat_guide Standards conformance
|
||||
|
||||
@tableofcontents
|
||||
|
||||
This guide describes the various API extensions used by this version of GLFW.
|
||||
It lists what are essentially implementation details, but which are nonetheless
|
||||
vital knowledge for developers intending to deploy their applications on a wide
|
||||
range of machines.
|
||||
|
||||
The information in this guide is not a part of GLFW API, but merely
|
||||
preconditions for some parts of the library to function on a given machine. Any
|
||||
part of this information may change in future versions of GLFW and that will not
|
||||
be considered a breaking API change.
|
||||
|
||||
|
||||
@section compat_x11 X11 extensions, protocols and IPC standards
|
||||
|
||||
As GLFW uses Xlib directly, without any intervening toolkit
|
||||
library, it has sole responsibility for interacting well with the many and
|
||||
varied window managers in use on Unix-like systems. In order for applications
|
||||
and window managers to work well together, a number of standards and
|
||||
conventions have been developed that regulate behavior outside the scope of the
|
||||
X11 API; most importantly the
|
||||
[Inter-Client Communication Conventions Manual](http://www.tronche.com/gui/x/icccm/)
|
||||
(ICCCM) and
|
||||
[Extended Window Manager Hints](http://standards.freedesktop.org/wm-spec/wm-spec-latest.html)
|
||||
(EWMH) standards.
|
||||
|
||||
GLFW uses the `_MOTIF_WM_HINTS` window property to support borderless windows.
|
||||
If the running window manager does not support this property, the
|
||||
`GLFW_DECORATED` hint will have no effect.
|
||||
|
||||
GLFW uses the ICCCM `WM_DELETE_WINDOW` protocol to intercept the user
|
||||
attempting to close the GLFW window. If the running window manager does not
|
||||
support this protocol, the close callback will never be called.
|
||||
|
||||
GLFW uses the EWMH `_NET_WM_PING` protocol, allowing the window manager notify
|
||||
the user when the application has stopped responding, i.e. when it has ceased to
|
||||
process events. If the running window manager does not support this protocol,
|
||||
the user will not be notified if the application locks up.
|
||||
|
||||
GLFW uses the EWMH `_NET_WM_STATE_FULLSCREEN` window state to tell the window
|
||||
manager to make the GLFW window full screen. If the running window manager does
|
||||
not support this state, full screen windows may not work properly. GLFW has
|
||||
a fallback code path in case this state is unavailable, but every window manager
|
||||
behaves slightly differently in this regard.
|
||||
|
||||
GLFW uses the EWMH `_NET_WM_BYPASS_COMPOSITOR` window property to tell a
|
||||
compositing window manager to un-redirect full screen GLFW windows. If the
|
||||
running window manager uses compositing but does not support this property then
|
||||
additional copying may be performed for each buffer swap of full screen windows.
|
||||
|
||||
GLFW uses the
|
||||
[clipboard manager protocol](http://www.freedesktop.org/wiki/ClipboardManager/)
|
||||
to push a clipboard string (i.e. selection) owned by a GLFW window about to be
|
||||
destroyed to the clipboard manager. If there is no running clipboard manager,
|
||||
the clipboard string will be unavailable once the window has been destroyed.
|
||||
|
||||
GLFW uses the
|
||||
[X drag-and-drop protocol](http://www.freedesktop.org/wiki/Specifications/XDND/)
|
||||
to provide file drop events. If the application originating the drag does not
|
||||
support this protocol, drag and drop will not work.
|
||||
|
||||
GLFW uses the XRandR 1.3 extension to provide multi-monitor support. If the
|
||||
running X server does not support this version of this extension, multi-monitor
|
||||
support will not function and only a single, desktop-spanning monitor will be
|
||||
reported.
|
||||
|
||||
GLFW uses the XRandR 1.3 and Xf86vidmode extensions to provide gamma ramp
|
||||
support. If the running X server does not support either or both of these
|
||||
extensions, gamma ramp support will not function.
|
||||
|
||||
GLFW uses the Xkb extension and detectable auto-repeat to provide keyboard
|
||||
input. If the running X server does not support this extension, a non-Xkb
|
||||
fallback path is used.
|
||||
|
||||
GLFW uses the XInput2 extension to provide raw, non-accelerated mouse motion
|
||||
when the cursor is disabled. If the running X server does not support this
|
||||
extension, regular accelerated mouse motion will be used.
|
||||
|
||||
|
||||
@section compat_glx GLX extensions
|
||||
|
||||
The GLX API is the default API used to create OpenGL contexts on Unix-like
|
||||
systems using the X Window System.
|
||||
|
||||
GLFW uses the GLX 1.3 `GLXFBConfig` functions to enumerate and select framebuffer pixel
|
||||
formats. If GLX 1.3 is not supported, @ref glfwInit will fail.
|
||||
|
||||
GLFW uses the `GLX_MESA_swap_control,` `GLX_EXT_swap_control` and
|
||||
`GLX_SGI_swap_control` extensions to provide vertical retrace synchronization
|
||||
(or _vsync_), in that order of preference. Where none of these extension are
|
||||
available, calling @ref glfwSwapInterval will have no effect.
|
||||
|
||||
GLFW uses the `GLX_ARB_multisample` extension to create contexts with
|
||||
multisampling anti-aliasing. Where this extension is unavailable, the
|
||||
`GLFW_SAMPLES` hint will have no effect.
|
||||
|
||||
GLFW uses the `GLX_ARB_create_context` extension when available, even when
|
||||
creating OpenGL contexts of version 2.1 and below. Where this extension is
|
||||
unavailable, the `GLFW_CONTEXT_VERSION_MAJOR` and `GLFW_CONTEXT_VERSION_MINOR`
|
||||
hints will only be partially supported, the `GLFW_OPENGL_DEBUG_CONTEXT` hint
|
||||
will have no effect, and setting the `GLFW_OPENGL_PROFILE` or
|
||||
`GLFW_OPENGL_FORWARD_COMPAT` hints to `GLFW_TRUE` will cause @ref
|
||||
glfwCreateWindow to fail.
|
||||
|
||||
GLFW uses the `GLX_ARB_create_context_profile` extension to provide support for
|
||||
context profiles. Where this extension is unavailable, setting the
|
||||
`GLFW_OPENGL_PROFILE` hint to anything but `GLFW_OPENGL_ANY_PROFILE`, or setting
|
||||
`GLFW_CLIENT_API` to anything but `GLFW_OPENGL_API` or `GLFW_NO_API` will cause
|
||||
@ref glfwCreateWindow to fail.
|
||||
|
||||
GLFW uses the `GLX_ARB_context_flush_control` extension to provide control over
|
||||
whether a context is flushed when it is released (made non-current). Where this
|
||||
extension is unavailable, the `GLFW_CONTEXT_RELEASE_BEHAVIOR` hint will have no
|
||||
effect and the context will always be flushed when released.
|
||||
|
||||
GLFW uses the `GLX_ARB_framebuffer_sRGB` and `GLX_EXT_framebuffer_sRGB`
|
||||
extensions to provide support for sRGB framebuffers. Where both of these
|
||||
extensions are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect.
|
||||
|
||||
|
||||
@section compat_wgl WGL extensions
|
||||
|
||||
The WGL API is used to create OpenGL contexts on Microsoft Windows and other
|
||||
implementations of the Win32 API, such as Wine.
|
||||
|
||||
GLFW uses either the `WGL_EXT_extension_string` or the
|
||||
`WGL_ARB_extension_string` extension to check for the presence of all other WGL
|
||||
extensions listed below. If both are available, the EXT one is preferred. If
|
||||
neither is available, no other extensions are used and many GLFW features
|
||||
related to context creation will have no effect or cause errors when used.
|
||||
|
||||
GLFW uses the `WGL_EXT_swap_control` extension to provide vertical retrace
|
||||
synchronization (or _vsync_). Where this extension is unavailable, calling @ref
|
||||
glfwSwapInterval will have no effect.
|
||||
|
||||
GLFW uses the `WGL_ARB_pixel_format` and `WGL_ARB_multisample` extensions to
|
||||
create contexts with multisampling anti-aliasing. Where these extensions are
|
||||
unavailable, the `GLFW_SAMPLES` hint will have no effect.
|
||||
|
||||
GLFW uses the `WGL_ARB_create_context` extension when available, even when
|
||||
creating OpenGL contexts of version 2.1 and below. Where this extension is
|
||||
unavailable, the `GLFW_CONTEXT_VERSION_MAJOR` and `GLFW_CONTEXT_VERSION_MINOR`
|
||||
hints will only be partially supported, the `GLFW_OPENGL_DEBUG_CONTEXT` hint
|
||||
will have no effect, and setting the `GLFW_OPENGL_PROFILE` or
|
||||
`GLFW_OPENGL_FORWARD_COMPAT` hints to `GLFW_TRUE` will cause @ref
|
||||
glfwCreateWindow to fail.
|
||||
|
||||
GLFW uses the `WGL_ARB_create_context_profile` extension to provide support for
|
||||
context profiles. Where this extension is unavailable, setting the
|
||||
`GLFW_OPENGL_PROFILE` hint to anything but `GLFW_OPENGL_ANY_PROFILE` will cause
|
||||
@ref glfwCreateWindow to fail.
|
||||
|
||||
GLFW uses the `WGL_ARB_context_flush_control` extension to provide control over
|
||||
whether a context is flushed when it is released (made non-current). Where this
|
||||
extension is unavailable, the `GLFW_CONTEXT_RELEASE_BEHAVIOR` hint will have no
|
||||
effect and the context will always be flushed when released.
|
||||
|
||||
GLFW uses the `WGL_ARB_framebuffer_sRGB` and `WGL_EXT_framebuffer_sRGB`
|
||||
extensions to provide support for sRGB framebuffers. Where both of these
|
||||
extension are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect.
|
||||
|
||||
|
||||
@section compat_osx OpenGL 3.2 and later on macOS
|
||||
|
||||
Support for OpenGL 3.2 and above was introduced with OS X 10.7 and even then
|
||||
only forward-compatible, core profile contexts are supported. Support for
|
||||
OpenGL 4.1 was introduced with OS X 10.9, also limited to forward-compatible,
|
||||
core profile contexts. There is also still no mechanism for requesting debug
|
||||
contexts. Versions of Mac OS X earlier than 10.7 support at most OpenGL
|
||||
version 2.1.
|
||||
|
||||
Because of this, on OS X 10.7 and later, the `GLFW_CONTEXT_VERSION_MAJOR` and
|
||||
`GLFW_CONTEXT_VERSION_MINOR` hints will cause @ref glfwCreateWindow to fail if
|
||||
given version 3.0 or 3.1, the `GLFW_OPENGL_FORWARD_COMPAT` hint must be set to
|
||||
`GLFW_TRUE` and the `GLFW_OPENGL_PROFILE` hint must be set to
|
||||
`GLFW_OPENGL_CORE_PROFILE` when creating OpenGL 3.2 and later contexts and the
|
||||
`GLFW_OPENGL_DEBUG_CONTEXT` hint is ignored.
|
||||
|
||||
Also, on Mac OS X 10.6 and below, the `GLFW_CONTEXT_VERSION_MAJOR` and
|
||||
`GLFW_CONTEXT_VERSION_MINOR` hints will fail if given a version above 2.1,
|
||||
setting the `GLFW_OPENGL_PROFILE` or `GLFW_OPENGL_FORWARD_COMPAT` hints to
|
||||
a non-default value will cause @ref glfwCreateWindow to fail and the
|
||||
`GLFW_OPENGL_DEBUG_CONTEXT` hint is ignored.
|
||||
|
||||
|
||||
@section compat_vulkan Vulkan loader and API
|
||||
|
||||
By default, GLFW uses the standard system-wide Vulkan loader to access the
|
||||
Vulkan API on all platforms except macOS. This is installed by both graphics
|
||||
drivers and Vulkan SDKs. If either the loader or at least one minimally
|
||||
functional ICD is missing, @ref glfwVulkanSupported will return `GLFW_FALSE` and
|
||||
all other Vulkan-related functions will fail with an @ref GLFW_API_UNAVAILABLE
|
||||
error.
|
||||
|
||||
|
||||
@section compat_wsi Vulkan WSI extensions
|
||||
|
||||
The Vulkan WSI extensions are used to create Vulkan surfaces for GLFW windows on
|
||||
all supported platforms.
|
||||
|
||||
GLFW uses the `VK_KHR_surface` and `VK_KHR_win32_surface` extensions to create
|
||||
surfaces on Microsoft Windows. If any of these extensions are not available,
|
||||
@ref glfwGetRequiredInstanceExtensions will return an empty list and window
|
||||
surface creation will fail.
|
||||
|
||||
GLFW uses the `VK_KHR_surface` and `VK_MVK_macos_surface` extensions to create
|
||||
surfaces on macOS. If any of these extensions are not available, @ref
|
||||
glfwGetRequiredInstanceExtensions will return an empty list and window surface
|
||||
creation will fail.
|
||||
|
||||
GLFW uses the `VK_KHR_surface` and either the `VK_KHR_xlib_surface` or
|
||||
`VK_KHR_xcb_surface` extensions to create surfaces on X11. If `VK_KHR_surface`
|
||||
or both `VK_KHR_xlib_surface` and `VK_KHR_xcb_surface` are not available, @ref
|
||||
glfwGetRequiredInstanceExtensions will return an empty list and window surface
|
||||
creation will fail.
|
||||
|
||||
GLFW uses the `VK_KHR_surface` and `VK_KHR_wayland_surface` extensions to create
|
||||
surfaces on Wayland. If any of these extensions are not available, @ref
|
||||
glfwGetRequiredInstanceExtensions will return an empty list and window surface
|
||||
creation will fail.
|
||||
|
||||
GLFW uses the `VK_KHR_surface` and `VK_KHR_mir_surface` extensions to create
|
||||
surfaces on Mir. If any of these extensions are not available, @ref
|
||||
glfwGetRequiredInstanceExtensions will return an empty list and window surface
|
||||
creation will fail.
|
||||
|
||||
*/
|
|
@ -0,0 +1,277 @@
|
|||
/*!
|
||||
|
||||
@page compile_guide Compiling GLFW
|
||||
|
||||
@tableofcontents
|
||||
|
||||
This is about compiling the GLFW library itself. For information on how to
|
||||
build applications that use GLFW, see @ref build_guide.
|
||||
|
||||
|
||||
@section compile_cmake Using CMake
|
||||
|
||||
GLFW uses [CMake](http://www.cmake.org/) to generate project files or makefiles
|
||||
for a particular development environment. If you are on a Unix-like system such
|
||||
as Linux or FreeBSD or have a package system like Fink, MacPorts, Cygwin or
|
||||
Homebrew, you can simply install its CMake package. If not, you can download
|
||||
installers for Windows and macOS from the
|
||||
[CMake website](http://www.cmake.org/).
|
||||
|
||||
@note CMake only generates project files or makefiles. It does not compile the
|
||||
actual GLFW library. To compile GLFW, first generate these files for your
|
||||
chosen development environment and then use them to compile the actual GLFW
|
||||
library.
|
||||
|
||||
|
||||
@subsection compile_deps Dependencies
|
||||
|
||||
Once you have installed CMake, make sure that all other dependencies are
|
||||
available. On some platforms, GLFW needs a few additional packages to be
|
||||
installed. See the section for your chosen platform and development environment
|
||||
below.
|
||||
|
||||
|
||||
@subsubsection compile_deps_msvc Dependencies for Visual C++ on Windows
|
||||
|
||||
The Microsoft Platform SDK that is installed along with Visual C++ already
|
||||
contains all the necessary headers, link libraries and tools except for CMake.
|
||||
Move on to @ref compile_generate.
|
||||
|
||||
|
||||
@subsubsection compile_deps_mingw Dependencies for MinGW or MinGW-w64 on Windows
|
||||
|
||||
Both the MinGW and the MinGW-w64 packages already contain all the necessary
|
||||
headers, link libraries and tools except for CMake. Move on to @ref
|
||||
compile_generate.
|
||||
|
||||
|
||||
@subsubsection compile_deps_mingw_cross Dependencies for MinGW or MinGW-w64 cross-compilation
|
||||
|
||||
Both Cygwin and many Linux distributions have MinGW or MinGW-w64 packages. For
|
||||
example, Cygwin has the `mingw64-i686-gcc` and `mingw64-x86_64-gcc` packages
|
||||
for 32- and 64-bit version of MinGW-w64, while Debian GNU/Linux and derivatives
|
||||
like Ubuntu have the `mingw-w64` package for both.
|
||||
|
||||
GLFW has CMake toolchain files in the `CMake/` directory that allow for easy
|
||||
cross-compilation of Windows binaries. To use these files you need to add a
|
||||
special parameter when generating the project files or makefiles:
|
||||
|
||||
@code{.sh}
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=<toolchain-file> .
|
||||
@endcode
|
||||
|
||||
The exact toolchain file to use depends on the prefix used by the MinGW or
|
||||
MinGW-w64 binaries on your system. You can usually see this in the /usr
|
||||
directory. For example, both the Debian/Ubuntu and Cygwin MinGW-w64 packages
|
||||
have `/usr/x86_64-w64-mingw32` for the 64-bit compilers, so the correct
|
||||
invocation would be:
|
||||
|
||||
@code{.sh}
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=CMake/x86_64-w64-mingw32.cmake .
|
||||
@endcode
|
||||
|
||||
For more details see the article
|
||||
[CMake Cross Compiling](http://www.paraview.org/Wiki/CMake_Cross_Compiling) on
|
||||
the CMake wiki.
|
||||
|
||||
Once you have this set up, move on to @ref compile_generate.
|
||||
|
||||
|
||||
@subsubsection compile_deps_xcode Dependencies for Xcode on macOS
|
||||
|
||||
Xcode comes with all necessary tools except for CMake. The required headers
|
||||
and libraries are included in the core macOS frameworks. Xcode can be
|
||||
downloaded from the Mac App Store or from the ADC Member Center.
|
||||
|
||||
Once you have Xcode installed, move on to @ref compile_generate.
|
||||
|
||||
|
||||
@subsubsection compile_deps_x11 Dependencies for Linux and X11
|
||||
|
||||
To compile GLFW for X11, you need to have the X11 packages installed, as well as
|
||||
the basic development tools like GCC and make. For example, on Ubuntu and other
|
||||
distributions based on Debian GNU/Linux, you need to install the `xorg-dev`
|
||||
package, which pulls in all X.org header packages.
|
||||
|
||||
Once you have installed the necessary packages, move on to @ref
|
||||
compile_generate.
|
||||
|
||||
|
||||
@subsection compile_deps_osmesa Dependencies for Linux and OSMesa
|
||||
|
||||
To compile GLFW for OSMesa, you need to install the OSMesa library and header
|
||||
packages. For example, on Ubuntu and other distributions based on Debian
|
||||
GNU/Linux, you need to install the `libosmesa6-dev` package. The OSMesa library
|
||||
is required at runtime for context creation and is loaded on demand.
|
||||
|
||||
Once you have installed the necessary packages, move on to @ref
|
||||
compile_generate.
|
||||
|
||||
|
||||
@subsection compile_generate Generating build files with CMake
|
||||
|
||||
Once you have all necessary dependencies it is time to generate the project
|
||||
files or makefiles for your development environment. CMake needs to know two
|
||||
paths for this: the path to the _root_ directory of the GLFW source tree (i.e.
|
||||
_not_ the `src` subdirectory) and the target path for the generated files and
|
||||
compiled binaries. If these are the same, it is called an in-tree build,
|
||||
otherwise it is called an out-of-tree build.
|
||||
|
||||
One of several advantages of out-of-tree builds is that you can generate files
|
||||
and compile for different development environments using a single source tree.
|
||||
|
||||
@note This section is about generating the project files or makefiles necessary
|
||||
to compile the GLFW library, not about compiling the actual library.
|
||||
|
||||
|
||||
@subsubsection compile_generate_cli Generating files with the CMake command-line tool
|
||||
|
||||
To make an in-tree build, enter the _root_ directory of the GLFW source tree
|
||||
(i.e. _not_ the `src` subdirectory) and run CMake. The current directory is
|
||||
used as target path, while the path provided as an argument is used to find the
|
||||
source tree.
|
||||
|
||||
@code{.sh}
|
||||
cd <glfw-root-dir>
|
||||
cmake .
|
||||
@endcode
|
||||
|
||||
To make an out-of-tree build, make a directory outside of the source tree, enter
|
||||
it and run CMake with the (relative or absolute) path to the root of the source
|
||||
tree as an argument.
|
||||
|
||||
@code{.sh}
|
||||
mkdir glfw-build
|
||||
cd glfw-build
|
||||
cmake <glfw-root-dir>
|
||||
@endcode
|
||||
|
||||
Once you have generated the project files or makefiles for your chosen
|
||||
development environment, move on to @ref compile_compile.
|
||||
|
||||
|
||||
@subsubsection compile_generate_gui Generating files with the CMake GUI
|
||||
|
||||
If you are using the GUI version, choose the root of the GLFW source tree as
|
||||
source location and the same directory or another, empty directory as the
|
||||
destination for binaries. Choose _Configure_, change any options you wish to,
|
||||
_Configure_ again to let the changes take effect and then _Generate_.
|
||||
|
||||
Once you have generated the project files or makefiles for your chosen
|
||||
development environment, move on to @ref compile_compile.
|
||||
|
||||
|
||||
@subsection compile_compile Compiling the library
|
||||
|
||||
You should now have all required dependencies and the project files or makefiles
|
||||
necessary to compile GLFW. Go ahead and compile the actual GLFW library with
|
||||
these files, as you would with any other project.
|
||||
|
||||
Once the GLFW library is compiled, you are ready to build your applications,
|
||||
linking it to the GLFW library. See @ref build_guide for more information.
|
||||
|
||||
|
||||
@subsection compile_options CMake options
|
||||
|
||||
The CMake files for GLFW provide a number of options, although not all are
|
||||
available on all supported platforms. Some of these are de facto standards
|
||||
among projects using CMake and so have no `GLFW_` prefix.
|
||||
|
||||
If you are using the GUI version of CMake, these are listed and can be changed
|
||||
from there. If you are using the command-line version of CMake you can use the
|
||||
`ccmake` ncurses GUI to set options. Some package systems like Ubuntu and other
|
||||
distributions based on Debian GNU/Linux have this tool in a separate
|
||||
`cmake-curses-gui` package.
|
||||
|
||||
Finally, if you don't want to use any GUI, you can set options from the `cmake`
|
||||
command-line with the `-D` flag.
|
||||
|
||||
@code{.sh}
|
||||
cmake -DBUILD_SHARED_LIBS=ON .
|
||||
@endcode
|
||||
|
||||
|
||||
@subsubsection compile_options_shared Shared CMake options
|
||||
|
||||
@anchor BUILD_SHARED_LIBS
|
||||
__BUILD_SHARED_LIBS__ determines whether GLFW is built as a static
|
||||
library or as a DLL / shared library / dynamic library.
|
||||
|
||||
@anchor LIB_SUFFIX
|
||||
__LIB_SUFFIX__ affects where the GLFW shared /dynamic library is installed. If
|
||||
it is empty, it is installed to `${CMAKE_INSTALL_PREFIX}/lib`. If it is set to
|
||||
`64`, it is installed to `${CMAKE_INSTALL_PREFIX}/lib64`.
|
||||
|
||||
@anchor GLFW_BUILD_EXAMPLES
|
||||
__GLFW_BUILD_EXAMPLES__ determines whether the GLFW examples are built
|
||||
along with the library.
|
||||
|
||||
@anchor GLFW_BUILD_TESTS
|
||||
__GLFW_BUILD_TESTS__ determines whether the GLFW test programs are
|
||||
built along with the library.
|
||||
|
||||
@anchor GLFW_BUILD_DOCS
|
||||
__GLFW_BUILD_DOCS__ determines whether the GLFW documentation is built along
|
||||
with the library.
|
||||
|
||||
@anchor GLFW_VULKAN_STATIC
|
||||
__GLFW_VULKAN_STATIC__ determines whether to use the Vulkan loader linked
|
||||
statically into the application.
|
||||
|
||||
|
||||
@subsubsection compile_options_win32 Windows specific CMake options
|
||||
|
||||
@anchor USE_MSVC_RUNTIME_LIBRARY_DLL
|
||||
__USE_MSVC_RUNTIME_LIBRARY_DLL__ determines whether to use the DLL version or the
|
||||
static library version of the Visual C++ runtime library. If set to `ON`, the
|
||||
DLL version of the Visual C++ library is used.
|
||||
|
||||
@anchor GLFW_USE_HYBRID_HPG
|
||||
__GLFW_USE_HYBRID_HPG__ determines whether to export the `NvOptimusEnablement` and
|
||||
`AmdPowerXpressRequestHighPerformance` symbols, which force the use of the
|
||||
high-performance GPU on Nvidia Optimus and AMD PowerXpress systems. These symbols
|
||||
need to be exported by the EXE to be detected by the driver, so the override
|
||||
will not work if GLFW is built as a DLL.
|
||||
|
||||
|
||||
@section compile_manual Compiling GLFW manually
|
||||
|
||||
If you wish to compile GLFW without its CMake build environment then you will
|
||||
have to do at least some of the platform detection yourself. GLFW needs
|
||||
a configuration macro to be defined in order to know what window system it's
|
||||
being compiled for and also has optional, platform-specific ones for various
|
||||
features.
|
||||
|
||||
When building with CMake, the `glfw_config.h` configuration header is generated
|
||||
based on the current platform and CMake options. The GLFW CMake environment
|
||||
defines @b GLFW_USE_CONFIG_H, which causes this header to be included by
|
||||
`internal.h`. Without this macro, GLFW will expect the necessary configuration
|
||||
macros to be defined on the command-line.
|
||||
|
||||
The window creation API is used to create windows, handle input, monitors, gamma
|
||||
ramps and clipboard. The options are:
|
||||
|
||||
- @b _GLFW_COCOA to use the Cocoa frameworks
|
||||
- @b _GLFW_WIN32 to use the Win32 API
|
||||
- @b _GLFW_X11 to use the X Window System
|
||||
- @b _GLFW_WAYLAND to use the Wayland API (experimental and incomplete)
|
||||
- @b _GLFW_MIR to use the Mir API (experimental and incomplete)
|
||||
- @b _GLFW_OSMESA to use the OSMesa API (headless and non-interactive)
|
||||
|
||||
If you are building GLFW as a shared library / dynamic library / DLL then you
|
||||
must also define @b _GLFW_BUILD_DLL. Otherwise, you must not define it.
|
||||
|
||||
If you are linking the Vulkan loader statically into your application then you
|
||||
must also define @b _GLFW_VULKAN_STATIC. Otherwise, GLFW will attempt to use the
|
||||
external version.
|
||||
|
||||
For the EGL context creation API, the following options are available:
|
||||
|
||||
- @b _GLFW_USE_EGLPLATFORM_H to use `EGL/eglplatform.h` for native handle
|
||||
definitions (fallback)
|
||||
|
||||
@note None of the @ref build_macros may be defined during the compilation of
|
||||
GLFW. If you define any of these in your build files, make sure they are not
|
||||
applied to the GLFW sources.
|
||||
|
||||
*/
|
|
@ -0,0 +1,344 @@
|
|||
/*!
|
||||
|
||||
@page context_guide Context guide
|
||||
|
||||
@tableofcontents
|
||||
|
||||
This guide introduces the OpenGL and OpenGL ES context related functions of
|
||||
GLFW. For details on a specific function in this category, see the @ref
|
||||
context. There are also guides for the other areas of the GLFW API.
|
||||
|
||||
- @ref intro_guide
|
||||
- @ref window_guide
|
||||
- @ref vulkan_guide
|
||||
- @ref monitor_guide
|
||||
- @ref input_guide
|
||||
|
||||
|
||||
@section context_object Context objects
|
||||
|
||||
A window object encapsulates both a top-level window and an OpenGL or OpenGL ES
|
||||
context. It is created with @ref glfwCreateWindow and destroyed with @ref
|
||||
glfwDestroyWindow or @ref glfwTerminate. See @ref window_creation for more
|
||||
information.
|
||||
|
||||
As the window and context are inseparably linked, the window object also serves
|
||||
as the context handle.
|
||||
|
||||
To test the creation of various kinds of contexts and see their properties, run
|
||||
the `glfwinfo` test program.
|
||||
|
||||
@note Vulkan does not have a context and the Vulkan instance is created via the
|
||||
Vulkan API itself. If you will be using Vulkan to render to a window, disable
|
||||
context creation by setting the [GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint)
|
||||
hint to `GLFW_NO_API`. For more information, see the @ref vulkan_guide.
|
||||
|
||||
|
||||
@subsection context_hints Context creation hints
|
||||
|
||||
There are a number of hints, specified using @ref glfwWindowHint, related to
|
||||
what kind of context is created. See
|
||||
[context related hints](@ref window_hints_ctx) in the window guide.
|
||||
|
||||
|
||||
@subsection context_sharing Context object sharing
|
||||
|
||||
When creating a window and its OpenGL or OpenGL ES context with @ref
|
||||
glfwCreateWindow, you can specify another window whose context the new one
|
||||
should share its objects (textures, vertex and element buffers, etc.) with.
|
||||
|
||||
@code
|
||||
GLFWwindow* second_window = glfwCreateWindow(640, 480, "Second Window", NULL, first_window);
|
||||
@endcode
|
||||
|
||||
Object sharing is implemented by the operating system and graphics driver. On
|
||||
platforms where it is possible to choose which types of objects are shared, GLFW
|
||||
requests that all types are shared.
|
||||
|
||||
See the relevant chapter of the [OpenGL](https://www.opengl.org/registry/) or
|
||||
[OpenGL ES](http://www.khronos.org/opengles/) reference documents for more
|
||||
information. The name and number of this chapter unfortunately varies between
|
||||
versions and APIs, but has at times been named _Shared Objects and Multiple
|
||||
Contexts_.
|
||||
|
||||
GLFW comes with a simple object sharing test program called `sharing`.
|
||||
|
||||
|
||||
@subsection context_offscreen Offscreen contexts
|
||||
|
||||
GLFW doesn't support creating contexts without an associated window. However,
|
||||
contexts with hidden windows can be created with the
|
||||
[GLFW_VISIBLE](@ref GLFW_VISIBLE_hint) window hint.
|
||||
|
||||
@code
|
||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||
|
||||
GLFWwindow* offscreen_context = glfwCreateWindow(640, 480, "", NULL, NULL);
|
||||
@endcode
|
||||
|
||||
The window never needs to be shown and its context can be used as a plain
|
||||
offscreen context. Depending on the window manager, the size of a hidden
|
||||
window's framebuffer may not be usable or modifiable, so framebuffer
|
||||
objects are recommended for rendering with such contexts.
|
||||
|
||||
You should still [process events](@ref events) as long as you have at least one
|
||||
window, even if none of them are visible.
|
||||
|
||||
@macos The first time a window is created the menu bar is created. This is not
|
||||
desirable for example when writing a command-line only application. Menu bar
|
||||
creation can be disabled with the @ref GLFW_COCOA_MENUBAR init hint.
|
||||
|
||||
|
||||
@subsection context_less Windows without contexts
|
||||
|
||||
You can disable context creation by setting the
|
||||
[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint to `GLFW_NO_API`. Windows
|
||||
without contexts must not be passed to @ref glfwMakeContextCurrent or @ref
|
||||
glfwSwapBuffers.
|
||||
|
||||
|
||||
@section context_current Current context
|
||||
|
||||
Before you can make OpenGL or OpenGL ES calls, you need to have a current
|
||||
context of the correct type. A context can only be current for a single thread
|
||||
at a time, and a thread can only have a single context current at a time.
|
||||
|
||||
The context of a window is made current with @ref glfwMakeContextCurrent.
|
||||
|
||||
@code
|
||||
glfwMakeContextCurrent(window);
|
||||
@endcode
|
||||
|
||||
The window of the current context is returned by @ref glfwGetCurrentContext.
|
||||
|
||||
@code
|
||||
GLFWwindow* window = glfwGetCurrentContext();
|
||||
@endcode
|
||||
|
||||
The following GLFW functions require a context to be current. Calling any these
|
||||
functions without a current context will generate a @ref GLFW_NO_CURRENT_CONTEXT
|
||||
error.
|
||||
|
||||
- @ref glfwSwapInterval
|
||||
- @ref glfwExtensionSupported
|
||||
- @ref glfwGetProcAddress
|
||||
|
||||
|
||||
@section context_swap Buffer swapping
|
||||
|
||||
Buffer swapping is part of the window and framebuffer, not the context. See
|
||||
@ref buffer_swap.
|
||||
|
||||
|
||||
@section context_glext OpenGL and OpenGL ES extensions
|
||||
|
||||
One of the benefits of OpenGL and OpenGL ES is their extensibility.
|
||||
Hardware vendors may include extensions in their implementations that extend the
|
||||
API before that functionality is included in a new version of the OpenGL or
|
||||
OpenGL ES specification, and some extensions are never included and remain
|
||||
as extensions until they become obsolete.
|
||||
|
||||
An extension is defined by:
|
||||
|
||||
- An extension name (e.g. `GL_ARB_debug_output`)
|
||||
- New OpenGL tokens (e.g. `GL_DEBUG_SEVERITY_HIGH_ARB`)
|
||||
- New OpenGL functions (e.g. `glGetDebugMessageLogARB`)
|
||||
|
||||
Note the `ARB` affix, which stands for Architecture Review Board and is used
|
||||
for official extensions. The extension above was created by the ARB, but there
|
||||
are many different affixes, like `NV` for Nvidia and `AMD` for, well, AMD. Any
|
||||
group may also use the generic `EXT` affix. Lists of extensions, together with
|
||||
their specifications, can be found at the
|
||||
[OpenGL Registry](http://www.opengl.org/registry/) and
|
||||
[OpenGL ES Registry](https://www.khronos.org/registry/gles/).
|
||||
|
||||
|
||||
@subsection context_glext_auto Loading extension with a loader library
|
||||
|
||||
An extension loader library is the easiest and best way to access both OpenGL and
|
||||
OpenGL ES extensions and modern versions of the core OpenGL or OpenGL ES APIs.
|
||||
They will take care of all the details of declaring and loading everything you
|
||||
need. One such library is [glad](https://github.com/Dav1dde/glad) and there are
|
||||
several others.
|
||||
|
||||
The following example will use glad but all extension loader libraries work
|
||||
similarly.
|
||||
|
||||
First you need to generate the source files using the glad Python script. This
|
||||
example generates a loader for any version of OpenGL, which is the default for
|
||||
both GLFW and glad, but loaders for OpenGL ES, as well as loaders for specific
|
||||
API versions and extension sets can be generated. The generated files are
|
||||
written to the `output` directory.
|
||||
|
||||
@code{.sh}
|
||||
python main.py --generator c --no-loader --out-path output
|
||||
@endcode
|
||||
|
||||
The `--no-loader` option is added because GLFW already provides a function for
|
||||
loading OpenGL and OpenGL ES function pointers, one that automatically uses the
|
||||
selected context creation API, and glad can call this instead of having to
|
||||
implement its own. There are several other command-line options as well. See
|
||||
the glad documentation for details.
|
||||
|
||||
Add the generated `output/src/glad.c`, `output/include/glad/glad.h` and
|
||||
`output/include/KHR/khrplatform.h` files to your build. Then you need to
|
||||
include the glad header file, which will replace the OpenGL header of your
|
||||
development environment. By including the glad header before the GLFW header,
|
||||
it suppresses the development environment's OpenGL or OpenGL ES header.
|
||||
|
||||
@code
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
Finally you need to initialize glad once you have a suitable current context.
|
||||
|
||||
@code
|
||||
window = glfwCreateWindow(640, 480, "My Window", NULL, NULL);
|
||||
if (!window)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
|
||||
@endcode
|
||||
|
||||
Once glad has been loaded, you have access to all OpenGL core and extension
|
||||
functions supported by both the context you created and the glad loader you
|
||||
generated and you are ready to start rendering.
|
||||
|
||||
You can specify a minimum required OpenGL or OpenGL ES version with
|
||||
[context hints](@ref window_hints_ctx). If your needs are more complex, you can
|
||||
check the actual OpenGL or OpenGL ES version with
|
||||
[context attributes](@ref window_attribs_ctx), or you can check whether
|
||||
a specific version is supported by the current context with the
|
||||
`GLAD_GL_VERSION_x_x` booleans.
|
||||
|
||||
@code
|
||||
if (GLAD_GL_VERSION_3_2)
|
||||
{
|
||||
// Call OpenGL 3.2+ specific code
|
||||
}
|
||||
@endcode
|
||||
|
||||
To check whether a specific extension is supported, use the `GLAD_GL_xxx`
|
||||
booleans.
|
||||
|
||||
@code
|
||||
if (GLAD_GL_ARB_debug_output)
|
||||
{
|
||||
// Use GL_ARB_debug_output
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection context_glext_manual Loading extensions manually
|
||||
|
||||
__Do not use this technique__ unless it is absolutely necessary. An
|
||||
[extension loader library](@ref context_glext_auto) will save you a ton of
|
||||
tedious, repetitive, error prone work.
|
||||
|
||||
To use a certain extension, you must first check whether the context supports
|
||||
that extension and then, if it introduces new functions, retrieve the pointers
|
||||
to those functions. GLFW provides @ref glfwExtensionSupported and @ref
|
||||
glfwGetProcAddress for manual loading of extensions and new API functions.
|
||||
|
||||
This section will demonstrate manual loading of OpenGL extensions. The loading
|
||||
of OpenGL ES extensions is identical except for the name of the extension header.
|
||||
|
||||
|
||||
@subsubsection context_glext_header The glext.h header
|
||||
|
||||
The `glext.h` extension header is a continually updated file that defines the
|
||||
interfaces for all OpenGL extensions. The latest version of this can always be
|
||||
found at the [OpenGL Registry](http://www.opengl.org/registry/). There are also
|
||||
extension headers for the various versions of OpenGL ES at the
|
||||
[OpenGL ES Registry](https://www.khronos.org/registry/gles/). It it strongly
|
||||
recommended that you use your own copy of the extension header, as the one
|
||||
included in your development environment may be several years out of date and
|
||||
may not include the extensions you wish to use.
|
||||
|
||||
The header defines function pointer types for all functions of all extensions it
|
||||
supports. These have names like `PFNGLGETDEBUGMESSAGELOGARBPROC` (for
|
||||
`glGetDebugMessageLogARB`), i.e. the name is made uppercase and `PFN` (pointer
|
||||
to function) and `PROC` (procedure) are added to the ends.
|
||||
|
||||
To include the extension header, define @ref GLFW_INCLUDE_GLEXT before including
|
||||
the GLFW header.
|
||||
|
||||
@code
|
||||
#define GLFW_INCLUDE_GLEXT
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
|
||||
@subsubsection context_glext_string Checking for extensions
|
||||
|
||||
A given machine may not actually support the extension (it may have older
|
||||
drivers or a graphics card that lacks the necessary hardware features), so it
|
||||
is necessary to check at run-time whether the context supports the extension.
|
||||
This is done with @ref glfwExtensionSupported.
|
||||
|
||||
@code
|
||||
if (glfwExtensionSupported("GL_ARB_debug_output"))
|
||||
{
|
||||
// The extension is supported by the current context
|
||||
}
|
||||
@endcode
|
||||
|
||||
The argument is a null terminated ASCII string with the extension name. If the
|
||||
extension is supported, @ref glfwExtensionSupported returns `GLFW_TRUE`,
|
||||
otherwise it returns `GLFW_FALSE`.
|
||||
|
||||
|
||||
@subsubsection context_glext_proc Fetching function pointers
|
||||
|
||||
Many extensions, though not all, require the use of new OpenGL functions.
|
||||
These functions often do not have entry points in the client API libraries of
|
||||
your operating system, making it necessary to fetch them at run time. You can
|
||||
retrieve pointers to these functions with @ref glfwGetProcAddress.
|
||||
|
||||
@code
|
||||
PFNGLGETDEBUGMESSAGELOGARBPROC pfnGetDebugMessageLog = glfwGetProcAddress("glGetDebugMessageLogARB");
|
||||
@endcode
|
||||
|
||||
In general, you should avoid giving the function pointer variables the (exact)
|
||||
same name as the function, as this may confuse your linker. Instead, you can
|
||||
use a different prefix, like above, or some other naming scheme.
|
||||
|
||||
Now that all the pieces have been introduced, here is what they might look like
|
||||
when used together.
|
||||
|
||||
@code
|
||||
#define GLFW_INCLUDE_GLEXT
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#define glGetDebugMessageLogARB pfnGetDebugMessageLog
|
||||
PFNGLGETDEBUGMESSAGELOGARBPROC pfnGetDebugMessageLog;
|
||||
|
||||
// Flag indicating whether the extension is supported
|
||||
int has_ARB_debug_output = 0;
|
||||
|
||||
void load_extensions(void)
|
||||
{
|
||||
if (glfwExtensionSupported("GL_ARB_debug_output"))
|
||||
{
|
||||
pfnGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGARBPROC)
|
||||
glfwGetProcAddress("glGetDebugMessageLogARB");
|
||||
has_ARB_debug_output = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void some_function(void)
|
||||
{
|
||||
if (has_ARB_debug_output)
|
||||
{
|
||||
// Now the extension function can be called as usual
|
||||
glGetDebugMessageLogARB(...);
|
||||
}
|
||||
}
|
||||
@endcode
|
||||
|
||||
*/
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,370 @@
|
|||
// NOTE: Please use this file to perform modifications on default style sheets.
|
||||
//
|
||||
// You need to install a few Ruby gems to generate extra.css from this file:
|
||||
// gem install less therubyracer
|
||||
//
|
||||
// Run this command to regenerate extra.css after you're finished with changes:
|
||||
// lessc --compress extra.less > extra.css
|
||||
//
|
||||
// Alternatively you can use online services to regenerate extra.css.
|
||||
|
||||
|
||||
// Default text color for page contents
|
||||
@default-text-color: hsl(0,0%,30%);
|
||||
|
||||
// Page header, footer, table rows, inline codes and definition lists
|
||||
@header-footer-background-color: hsl(0,0%,95%);
|
||||
|
||||
// Page header, footer links and navigation bar background
|
||||
@header-footer-link-color: hsl(0,0%,40%);
|
||||
|
||||
// Doxygen navigation bar links
|
||||
@navbar-link-color: @header-footer-background-color;
|
||||
|
||||
// Page content background color
|
||||
@content-background-color: hsl(0,0%,100%);
|
||||
|
||||
// Bold, italic, h1, h2, ... and table of contents
|
||||
@heading-color: hsl(0,0%,10%);
|
||||
|
||||
// Function, enum and macro definition separator
|
||||
@def-separator-color: @header-footer-background-color;
|
||||
|
||||
// Base color hue
|
||||
@base-hue: 24;
|
||||
|
||||
// Default color used for links
|
||||
@default-link-color: hsl(@base-hue,100%,50%);
|
||||
|
||||
// Doxygen navigation bar active tab
|
||||
@tab-text-color: hsl(0,0%,100%);
|
||||
@tab-background-color1: @default-link-color;
|
||||
@tab-background-color2: lighten(spin(@tab-background-color1, 10), 10%);
|
||||
|
||||
// Table borders
|
||||
@default-border-color: @default-link-color;
|
||||
|
||||
// Table header
|
||||
@table-text-color: @tab-text-color;
|
||||
@table-background-color1: @tab-background-color1;
|
||||
@table-background-color2: @tab-background-color2;
|
||||
|
||||
// Table of contents, data structure index and prototypes
|
||||
@toc-background-color1: hsl(0,0%,90%);
|
||||
@toc-background-color2: lighten(@toc-background-color1, 5%);
|
||||
|
||||
// Function prototype parameters color
|
||||
@prototype-param-color: darken(@default-link-color, 25%);
|
||||
|
||||
// Message box color: note, pre, post and invariant
|
||||
@box-note-color: hsl(103,80%,85%);
|
||||
|
||||
// Message box color: warning and attention
|
||||
@box-warning-color: hsl(34,80%,85%);
|
||||
|
||||
// Message box color: deprecated and bug
|
||||
@box-bug-color: hsl(333,80%,85%);
|
||||
|
||||
// Message box color: todo and test
|
||||
@box-todo-color: hsl(200,80%,85%);
|
||||
|
||||
// Message box helper function
|
||||
.message-box(@base-color) {
|
||||
background:linear-gradient(to bottom,lighten(@base-color, 5%) 0%,@base-color 100%);
|
||||
box-shadow:inset 0 0 32px darken(@base-color, 5%);
|
||||
color:darken(@base-color, 67%);
|
||||
border:2px solid desaturate(darken(@base-color, 10%), 20%);
|
||||
}
|
||||
|
||||
|
||||
#navrow1,#navrow2,#navrow3,#navrow4,.tablist a,.tablist a:visited,.tablist a:hover,.tablist li,.tablist li.current a,.memdoc,dl.reflist dd,div.toc li,.ah,span.lineno,span.lineno a,span.lineno a:hover,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,.doxtable code {
|
||||
background:none;
|
||||
}
|
||||
|
||||
#titlearea,.footer,.contents,div.header,.memdoc,table.doxtable td,table.doxtable th,hr,.memSeparator {
|
||||
border:none;
|
||||
}
|
||||
|
||||
.tablist a,.tablist a:visited,.tablist a:hover,.tablist li,.tablist li.current a,.reflist dt a.el,.levels span,.directory .levels span {
|
||||
text-shadow:none;
|
||||
}
|
||||
|
||||
.memdoc,dl.reflist dd {
|
||||
box-shadow:none;
|
||||
}
|
||||
|
||||
div.headertitle,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,table.doxtable code {
|
||||
padding:0;
|
||||
}
|
||||
|
||||
#nav-path,.directory .levels,span.lineno {
|
||||
display:none;
|
||||
}
|
||||
|
||||
html,#titlearea,.footer,tr.even,.directory tr.even,.doxtable tr:nth-child(even),.mdescLeft,.mdescRight,.memItemLeft,.memItemRight,code {
|
||||
background:@header-footer-background-color;
|
||||
}
|
||||
|
||||
body {
|
||||
color:@default-text-color;
|
||||
}
|
||||
|
||||
h1,h2,h2.groupheader,h3,div.toc h3,h4,h5,h6,strong,em {
|
||||
color:@heading-color;
|
||||
border-bottom:none;
|
||||
}
|
||||
|
||||
h1 {
|
||||
padding-top:0.5em;
|
||||
font-size:180%;
|
||||
}
|
||||
|
||||
h2 {
|
||||
padding-top:0.5em;
|
||||
margin-bottom:0;
|
||||
font-size:140%;
|
||||
}
|
||||
|
||||
h3 {
|
||||
padding-top:0.5em;
|
||||
margin-bottom:0;
|
||||
font-size:110%;
|
||||
}
|
||||
|
||||
.glfwheader {
|
||||
font-size:16px;
|
||||
height:64px;
|
||||
max-width:920px;
|
||||
min-width:800px;
|
||||
padding:0 32px;
|
||||
margin:0 auto;
|
||||
}
|
||||
|
||||
#glfwhome {
|
||||
line-height:64px;
|
||||
padding-right:48px;
|
||||
color:@header-footer-link-color;
|
||||
font-size:2.5em;
|
||||
background:url("http://www.glfw.org/css/arrow.png") no-repeat right;
|
||||
}
|
||||
|
||||
.glfwnavbar {
|
||||
list-style-type:none;
|
||||
margin:0 auto;
|
||||
float:right;
|
||||
}
|
||||
|
||||
#glfwhome,.glfwnavbar li {
|
||||
float:left;
|
||||
}
|
||||
|
||||
.glfwnavbar a,.glfwnavbar a:visited {
|
||||
line-height:64px;
|
||||
margin-left:2em;
|
||||
display:block;
|
||||
color:@header-footer-link-color;
|
||||
}
|
||||
|
||||
#glfwhome,.glfwnavbar a,.glfwnavbar a:visited {
|
||||
transition:.35s ease;
|
||||
}
|
||||
|
||||
#titlearea,.footer {
|
||||
color:@header-footer-link-color;
|
||||
}
|
||||
|
||||
address.footer {
|
||||
text-align:center;
|
||||
padding:2em;
|
||||
margin-top:3em;
|
||||
}
|
||||
|
||||
#top {
|
||||
background:@header-footer-link-color;
|
||||
}
|
||||
|
||||
#navrow1,#navrow2,#navrow3,#navrow4 {
|
||||
max-width:920px;
|
||||
min-width:800px;
|
||||
margin:0 auto;
|
||||
font-size:13px;
|
||||
}
|
||||
|
||||
.tablist {
|
||||
height:36px;
|
||||
display:block;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.tablist a,.tablist a:visited,.tablist a:hover,.tablist li,.tablist li.current a {
|
||||
color:@navbar-link-color;
|
||||
}
|
||||
|
||||
.tablist li.current a {
|
||||
background:linear-gradient(to bottom,@tab-background-color2 0%,@tab-background-color1 100%);
|
||||
box-shadow:inset 0 0 32px @tab-background-color1;
|
||||
text-shadow:0 -1px 1px darken(@tab-background-color1, 15%);
|
||||
color:@tab-text-color;
|
||||
}
|
||||
|
||||
.contents {
|
||||
min-height:590px;
|
||||
}
|
||||
|
||||
div.contents,div.header {
|
||||
max-width:920px;
|
||||
margin:0 auto;
|
||||
padding:0 32px;
|
||||
background:@content-background-color none;
|
||||
}
|
||||
|
||||
table.doxtable th,dl.reflist dt {
|
||||
background:linear-gradient(to bottom,@table-background-color2 0%,@table-background-color1 100%);
|
||||
box-shadow:inset 0 0 32px @table-background-color1;
|
||||
text-shadow:0 -1px 1px darken(@table-background-color1, 15%);
|
||||
color:@table-text-color;
|
||||
}
|
||||
|
||||
dl.reflist dt a.el {
|
||||
color:@default-link-color;
|
||||
padding:.2em;
|
||||
border-radius:4px;
|
||||
background-color:lighten(@default-link-color, 40%);
|
||||
}
|
||||
|
||||
div.toc {
|
||||
float:none;
|
||||
width:auto;
|
||||
}
|
||||
|
||||
div.toc h3 {
|
||||
font-size:1.17em;
|
||||
}
|
||||
|
||||
div.toc ul {
|
||||
padding-left:1.5em;
|
||||
}
|
||||
|
||||
div.toc li {
|
||||
font-size:1em;
|
||||
padding-left:0;
|
||||
list-style-type:disc;
|
||||
}
|
||||
|
||||
div.toc,.memproto,div.qindex,div.ah {
|
||||
background:linear-gradient(to bottom,@toc-background-color2 0%,@toc-background-color1 100%);
|
||||
box-shadow:inset 0 0 32px @toc-background-color1;
|
||||
text-shadow:0 1px 1px lighten(@toc-background-color2, 10%);
|
||||
color:@heading-color;
|
||||
border:2px solid @toc-background-color1;
|
||||
border-radius:4px;
|
||||
}
|
||||
|
||||
.paramname {
|
||||
color:@prototype-param-color;
|
||||
}
|
||||
|
||||
dl.reflist dt {
|
||||
border:2px solid @default-border-color;
|
||||
border-top-left-radius:4px;
|
||||
border-top-right-radius:4px;
|
||||
border-bottom:none;
|
||||
}
|
||||
|
||||
dl.reflist dd {
|
||||
border:2px solid @default-border-color;
|
||||
border-bottom-right-radius:4px;
|
||||
border-bottom-left-radius:4px;
|
||||
border-top:none;
|
||||
}
|
||||
|
||||
table.doxtable {
|
||||
border-collapse:inherit;
|
||||
border-spacing:0;
|
||||
border:2px solid @default-border-color;
|
||||
border-radius:4px;
|
||||
}
|
||||
|
||||
a,a:hover,a:visited,a:visited:hover,.contents a:visited,.el,a.el:visited,#glfwhome:hover,.tablist a:hover,span.lineno a:hover {
|
||||
color:@default-link-color;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
div.directory {
|
||||
border-collapse:inherit;
|
||||
border-spacing:0;
|
||||
border:2px solid @default-border-color;
|
||||
border-radius:4px;
|
||||
}
|
||||
|
||||
hr,.memSeparator {
|
||||
height:2px;
|
||||
background:linear-gradient(to right,@def-separator-color 0%,darken(@def-separator-color, 10%) 50%,@def-separator-color 100%);
|
||||
}
|
||||
|
||||
dl.note,dl.pre,dl.post,dl.invariant {
|
||||
.message-box(@box-note-color);
|
||||
}
|
||||
|
||||
dl.warning,dl.attention {
|
||||
.message-box(@box-warning-color);
|
||||
}
|
||||
|
||||
dl.deprecated,dl.bug {
|
||||
.message-box(@box-bug-color);
|
||||
}
|
||||
|
||||
dl.todo,dl.test {
|
||||
.message-box(@box-todo-color);
|
||||
}
|
||||
|
||||
dl.note,dl.pre,dl.post,dl.invariant,dl.warning,dl.attention,dl.deprecated,dl.bug,dl.todo,dl.test {
|
||||
border-radius:4px;
|
||||
padding:1em;
|
||||
text-shadow:0 1px 1px hsl(0,0%,100%);
|
||||
margin:1em 0;
|
||||
}
|
||||
|
||||
.note a,.pre a,.post a,.invariant a,.warning a,.attention a,.deprecated a,.bug a,.todo a,.test a,.note a:visited,.pre a:visited,.post a:visited,.invariant a:visited,.warning a:visited,.attention a:visited,.deprecated a:visited,.bug a:visited,.todo a:visited,.test a:visited {
|
||||
color:inherit;
|
||||
}
|
||||
|
||||
div.line {
|
||||
line-height:inherit;
|
||||
}
|
||||
|
||||
div.fragment,pre.fragment {
|
||||
background:hsl(0,0%,95%);
|
||||
border-radius:4px;
|
||||
border:none;
|
||||
padding:1em;
|
||||
overflow:auto;
|
||||
border-left:4px solid hsl(0,0%,80%);
|
||||
margin:1em 0;
|
||||
}
|
||||
|
||||
.lineno a,.lineno a:visited,.line,pre.fragment {
|
||||
color:@default-text-color;
|
||||
}
|
||||
|
||||
span.preprocessor,span.comment {
|
||||
color:hsl(193,100%,30%);
|
||||
}
|
||||
|
||||
a.code,a.code:visited {
|
||||
color:hsl(18,100%,45%);
|
||||
}
|
||||
|
||||
span.keyword,span.keywordtype,span.keywordflow {
|
||||
color:darken(@default-text-color, 5%);
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
span.stringliteral {
|
||||
color:hsl(261,100%,30%);
|
||||
}
|
||||
|
||||
code {
|
||||
padding:.1em;
|
||||
border-radius:4px;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<address class="footer">
|
||||
<p>
|
||||
Last update on $date for $projectname $projectnumber
|
||||
</p>
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
||||
<meta name="generator" content="Doxygen $doxygenversion"/>
|
||||
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
|
||||
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
|
||||
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
|
||||
<script type="text/javascript" src="$relpath^jquery.js"></script>
|
||||
<script type="text/javascript" src="$relpath^dynsections.js"></script>
|
||||
$treeview
|
||||
$search
|
||||
$mathjax
|
||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
||||
$extrastylesheet
|
||||
</head>
|
||||
<body>
|
||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
|
||||
<!--BEGIN TITLEAREA-->
|
||||
<div id="titlearea">
|
||||
<div class="glfwheader">
|
||||
<a href="http://www.glfw.org/" id="glfwhome">GLFW</a>
|
||||
<ul class="glfwnavbar">
|
||||
<li><a href="http://www.glfw.org/documentation.html">Documentation</a></li>
|
||||
<li><a href="http://www.glfw.org/download.html">Download</a></li>
|
||||
<li><a href="http://www.glfw.org/media.html">Media</a></li>
|
||||
<li><a href="http://www.glfw.org/community.html">Community</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!--END TITLEAREA-->
|
||||
<!-- end header part -->
|
|
@ -0,0 +1,745 @@
|
|||
/*!
|
||||
|
||||
@page input_guide Input guide
|
||||
|
||||
@tableofcontents
|
||||
|
||||
This guide introduces the input related functions of GLFW. For details on
|
||||
a specific function in this category, see the @ref input. There are also guides
|
||||
for the other areas of GLFW.
|
||||
|
||||
- @ref intro_guide
|
||||
- @ref window_guide
|
||||
- @ref context_guide
|
||||
- @ref vulkan_guide
|
||||
- @ref monitor_guide
|
||||
|
||||
GLFW provides many kinds of input. While some can only be polled, like time, or
|
||||
only received via callbacks, like scrolling, many provide both callbacks and
|
||||
polling. Callbacks are more work to use than polling but is less CPU intensive
|
||||
and guarantees that you do not miss state changes.
|
||||
|
||||
All input callbacks receive a window handle. By using the
|
||||
[window user pointer](@ref window_userptr), you can access non-global structures
|
||||
or objects from your callbacks.
|
||||
|
||||
To get a better feel for how the various events callbacks behave, run the
|
||||
`events` test program. It register every callback supported by GLFW and prints
|
||||
out all arguments provided for every event, along with time and sequence
|
||||
information.
|
||||
|
||||
|
||||
@section events Event processing
|
||||
|
||||
GLFW needs to poll the window system for events both to provide input to the
|
||||
application and to prove to the window system that the application hasn't locked
|
||||
up. Event processing is normally done each frame after
|
||||
[buffer swapping](@ref buffer_swap). Even when you have no windows, event
|
||||
polling needs to be done in order to receive monitor and joystick connection
|
||||
events.
|
||||
|
||||
There are three functions for processing pending events. @ref glfwPollEvents,
|
||||
processes only those events that have already been received and then returns
|
||||
immediately.
|
||||
|
||||
@code
|
||||
glfwPollEvents();
|
||||
@endcode
|
||||
|
||||
This is the best choice when rendering continuously, like most games do.
|
||||
|
||||
If you only need to update the contents of the window when you receive new
|
||||
input, @ref glfwWaitEvents is a better choice.
|
||||
|
||||
@code
|
||||
glfwWaitEvents();
|
||||
@endcode
|
||||
|
||||
It puts the thread to sleep until at least one event has been received and then
|
||||
processes all received events. This saves a great deal of CPU cycles and is
|
||||
useful for, for example, editing tools. There must be at least one GLFW window
|
||||
for this function to sleep.
|
||||
|
||||
If you want to wait for events but have UI elements or other tasks that need
|
||||
periodic updates, @ref glfwWaitEventsTimeout lets you specify a timeout.
|
||||
|
||||
@code
|
||||
glfwWaitEventsTimeout(0.7);
|
||||
@endcode
|
||||
|
||||
It puts the thread to sleep until at least one event has been received, or until
|
||||
the specified number of seconds have elapsed. It then processes any received
|
||||
events.
|
||||
|
||||
If the main thread is sleeping in @ref glfwWaitEvents, you can wake it from
|
||||
another thread by posting an empty event to the event queue with @ref
|
||||
glfwPostEmptyEvent.
|
||||
|
||||
@code
|
||||
glfwPostEmptyEvent();
|
||||
@endcode
|
||||
|
||||
Do not assume that callbacks will _only_ be called in response to the above
|
||||
functions. While it is necessary to process events in one or more of the ways
|
||||
above, window systems that require GLFW to register callbacks of its own can
|
||||
pass events to GLFW in response to many window system function calls. GLFW will
|
||||
pass those events on to the application callbacks before returning.
|
||||
|
||||
For example, on Windows the system function that @ref glfwSetWindowSize is
|
||||
implemented with will send window size events directly to the event callback
|
||||
that every window has and that GLFW implements for its windows. If you have set
|
||||
a [window size callback](@ref window_size) GLFW will call it in turn with the
|
||||
new size before everything returns back out of the @ref glfwSetWindowSize call.
|
||||
|
||||
|
||||
@section input_keyboard Keyboard input
|
||||
|
||||
GLFW divides keyboard input into two categories; key events and character
|
||||
events. Key events relate to actual physical keyboard keys, whereas character
|
||||
events relate to the Unicode code points generated by pressing some of them.
|
||||
|
||||
Keys and characters do not map 1:1. A single key press may produce several
|
||||
characters, and a single character may require several keys to produce. This
|
||||
may not be the case on your machine, but your users are likely not all using the
|
||||
same keyboard layout, input method or even operating system as you.
|
||||
|
||||
|
||||
@subsection input_key Key input
|
||||
|
||||
If you wish to be notified when a physical key is pressed or released or when it
|
||||
repeats, set a key callback.
|
||||
|
||||
@code
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
@endcode
|
||||
|
||||
The callback function receives the [keyboard key](@ref keys), platform-specific
|
||||
scancode, key action and [modifier bits](@ref mods).
|
||||
|
||||
@code
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
{
|
||||
if (key == GLFW_KEY_E && action == GLFW_PRESS)
|
||||
activate_airship();
|
||||
}
|
||||
@endcode
|
||||
|
||||
The action is one of `GLFW_PRESS`, `GLFW_REPEAT` or `GLFW_RELEASE`. The key
|
||||
will be `GLFW_KEY_UNKNOWN` if GLFW lacks a key token for it, for example
|
||||
_E-mail_ and _Play_ keys.
|
||||
|
||||
The scancode is unique for every key, regardless of whether it has a key token.
|
||||
Scancodes are platform-specific but consistent over time, so keys will have
|
||||
different scancodes depending on the platform but they are safe to save to disk.
|
||||
You can query the scancode for any [named key](@ref keys) on the current
|
||||
platform with @ref glfwGetKeyScancode.
|
||||
|
||||
@code
|
||||
const int scancode = glfwGetKeyScancode(GLFW_KEY_X);
|
||||
set_key_mapping(scancode, swap_weapons);
|
||||
@endcode
|
||||
|
||||
The last reported state for every [named key](@ref keys) is also saved in
|
||||
per-window state arrays that can be polled with @ref glfwGetKey.
|
||||
|
||||
@code
|
||||
int state = glfwGetKey(window, GLFW_KEY_E);
|
||||
if (state == GLFW_PRESS)
|
||||
{
|
||||
activate_airship();
|
||||
}
|
||||
@endcode
|
||||
|
||||
The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
|
||||
|
||||
This function only returns cached key event state. It does not poll the
|
||||
system for the current physical state of the key.
|
||||
|
||||
@anchor GLFW_STICKY_KEYS
|
||||
Whenever you poll state, you risk missing the state change you are looking for.
|
||||
If a pressed key is released again before you poll its state, you will have
|
||||
missed the key press. The recommended solution for this is to use a
|
||||
key callback, but there is also the `GLFW_STICKY_KEYS` input mode.
|
||||
|
||||
@code
|
||||
glfwSetInputMode(window, GLFW_STICKY_KEYS, 1);
|
||||
@endcode
|
||||
|
||||
When sticky keys mode is enabled, the pollable state of a key will remain
|
||||
`GLFW_PRESS` until the state of that key is polled with @ref glfwGetKey. Once
|
||||
it has been polled, if a key release event had been processed in the meantime,
|
||||
the state will reset to `GLFW_RELEASE`, otherwise it will remain `GLFW_PRESS`.
|
||||
|
||||
The `GLFW_KEY_LAST` constant holds the highest value of any
|
||||
[named key](@ref keys).
|
||||
|
||||
|
||||
@subsection input_char Text input
|
||||
|
||||
GLFW supports text input in the form of a stream of
|
||||
[Unicode code points](https://en.wikipedia.org/wiki/Unicode), as produced by the
|
||||
operating system text input system. Unlike key input, text input obeys keyboard
|
||||
layouts and modifier keys and supports composing characters using
|
||||
[dead keys](https://en.wikipedia.org/wiki/Dead_key). Once received, you can
|
||||
encode the code points into
|
||||
[UTF-8](https://en.wikipedia.org/wiki/UTF-8) or any other encoding you prefer.
|
||||
|
||||
Because an `unsigned int` is 32 bits long on all platforms supported by GLFW,
|
||||
you can treat the code point argument as native endian
|
||||
[UTF-32](https://en.wikipedia.org/wiki/UTF-32).
|
||||
|
||||
There are two callbacks for receiving Unicode code points. If you wish to
|
||||
offer regular text input, set a character callback.
|
||||
|
||||
@code
|
||||
glfwSetCharCallback(window, character_callback);
|
||||
@endcode
|
||||
|
||||
The callback function receives Unicode code points for key events that would
|
||||
have led to regular text input and generally behaves as a standard text field on
|
||||
that platform.
|
||||
|
||||
@code
|
||||
void character_callback(GLFWwindow* window, unsigned int codepoint)
|
||||
{
|
||||
}
|
||||
@endcode
|
||||
|
||||
If you wish to receive even those Unicode code points generated with modifier
|
||||
key combinations that a plain text field would ignore, or just want to know
|
||||
exactly what modifier keys were used, set a character with modifiers callback.
|
||||
|
||||
@code
|
||||
glfwSetCharModsCallback(window, charmods_callback);
|
||||
@endcode
|
||||
|
||||
The callback function receives Unicode code points and
|
||||
[modifier bits](@ref mods).
|
||||
|
||||
@code
|
||||
void charmods_callback(GLFWwindow* window, unsigned int codepoint, int mods)
|
||||
{
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection input_key_name Key names
|
||||
|
||||
If you wish to refer to keys by name, you can query the keyboard layout
|
||||
dependent name of printable keys with @ref glfwGetKeyName.
|
||||
|
||||
@code
|
||||
const char* key_name = glfwGetKeyName(GLFW_KEY_W, 0);
|
||||
show_tutorial_hint("Press %s to move forward", key_name);
|
||||
@endcode
|
||||
|
||||
This function can handle both [keys and scancodes](@ref input_key). If the
|
||||
specified key is `GLFW_KEY_UNKNOWN` then the scancode is used, otherwise it is
|
||||
ignored. This matches the behavior of the key callback, meaning the callback
|
||||
arguments can always be passed unmodified to this function.
|
||||
|
||||
|
||||
@section input_mouse Mouse input
|
||||
|
||||
Mouse input comes in many forms, including cursor motion, button presses and
|
||||
scrolling offsets. The cursor appearance can also be changed, either to
|
||||
a custom image or a standard cursor shape from the system theme.
|
||||
|
||||
|
||||
@subsection cursor_pos Cursor position
|
||||
|
||||
If you wish to be notified when the cursor moves over the window, set a cursor
|
||||
position callback.
|
||||
|
||||
@code
|
||||
glfwSetCursorPosCallback(window, cursor_pos_callback);
|
||||
@endcode
|
||||
|
||||
The callback functions receives the cursor position, measured in screen
|
||||
coordinates but relative to the top-left corner of the window client area. On
|
||||
platforms that provide it, the full sub-pixel cursor position is passed on.
|
||||
|
||||
@code
|
||||
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
}
|
||||
@endcode
|
||||
|
||||
The cursor position is also saved per-window and can be polled with @ref
|
||||
glfwGetCursorPos.
|
||||
|
||||
@code
|
||||
double xpos, ypos;
|
||||
glfwGetCursorPos(window, &xpos, &ypos);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection cursor_mode Cursor mode
|
||||
|
||||
@anchor GLFW_CURSOR
|
||||
The `GLFW_CURSOR` input mode provides several cursor modes for special forms of
|
||||
mouse motion input. By default, the cursor mode is `GLFW_CURSOR_NORMAL`,
|
||||
meaning the regular arrow cursor (or another cursor set with @ref glfwSetCursor)
|
||||
is used and cursor motion is not limited.
|
||||
|
||||
If you wish to implement mouse motion based camera controls or other input
|
||||
schemes that require unlimited mouse movement, set the cursor mode to
|
||||
`GLFW_CURSOR_DISABLED`.
|
||||
|
||||
@code
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
@endcode
|
||||
|
||||
This will hide the cursor and lock it to the specified window. GLFW will then
|
||||
take care of all the details of cursor re-centering and offset calculation and
|
||||
providing the application with a virtual cursor position. This virtual position
|
||||
is provided normally via both the cursor position callback and through polling.
|
||||
|
||||
@note You should not implement your own version of this functionality using
|
||||
other features of GLFW. It is not supported and will not work as robustly as
|
||||
`GLFW_CURSOR_DISABLED`.
|
||||
|
||||
If you just wish the cursor to become hidden when it is over a window, set
|
||||
the cursor mode to `GLFW_CURSOR_HIDDEN`.
|
||||
|
||||
@code
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
@endcode
|
||||
|
||||
This mode puts no limit on the motion of the cursor.
|
||||
|
||||
To exit out of either of these special modes, restore the `GLFW_CURSOR_NORMAL`
|
||||
cursor mode.
|
||||
|
||||
@code
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection cursor_object Cursor objects
|
||||
|
||||
GLFW supports creating both custom and system theme cursor images, encapsulated
|
||||
as @ref GLFWcursor objects. They are created with @ref glfwCreateCursor or @ref
|
||||
glfwCreateStandardCursor and destroyed with @ref glfwDestroyCursor, or @ref
|
||||
glfwTerminate, if any remain.
|
||||
|
||||
|
||||
@subsubsection cursor_custom Custom cursor creation
|
||||
|
||||
A custom cursor is created with @ref glfwCreateCursor, which returns a handle to
|
||||
the created cursor object. For example, this creates a 16x16 white square
|
||||
cursor with the hot-spot in the upper-left corner:
|
||||
|
||||
@code
|
||||
unsigned char pixels[16 * 16 * 4];
|
||||
memset(pixels, 0xff, sizeof(pixels));
|
||||
|
||||
GLFWimage image;
|
||||
image.width = 16;
|
||||
image.height = 16;
|
||||
image.pixels = pixels;
|
||||
|
||||
GLFWcursor* cursor = glfwCreateCursor(&image, 0, 0);
|
||||
@endcode
|
||||
|
||||
If cursor creation fails, `NULL` will be returned, so it is necessary to check
|
||||
the return value.
|
||||
|
||||
The image data is 32-bit, little-endian, non-premultiplied RGBA, i.e. eight bits
|
||||
per channel. The pixels are arranged canonically as sequential rows, starting
|
||||
from the top-left corner.
|
||||
|
||||
|
||||
@subsubsection cursor_standard Standard cursor creation
|
||||
|
||||
A cursor with a [standard shape](@ref shapes) from the current system cursor
|
||||
theme can be can be created with @ref glfwCreateStandardCursor.
|
||||
|
||||
@code
|
||||
GLFWcursor* cursor = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);
|
||||
@endcode
|
||||
|
||||
These cursor objects behave in the exact same way as those created with @ref
|
||||
glfwCreateCursor except that the system cursor theme provides the actual image.
|
||||
|
||||
|
||||
@subsubsection cursor_destruction Cursor destruction
|
||||
|
||||
When a cursor is no longer needed, destroy it with @ref glfwDestroyCursor.
|
||||
|
||||
@code
|
||||
glfwDestroyCursor(cursor);
|
||||
@endcode
|
||||
|
||||
Cursor destruction always succeeds. If the cursor is current for any window,
|
||||
that window will revert to the default cursor. This does not affect the cursor
|
||||
mode. All remaining cursors remaining are destroyed when @ref glfwTerminate is
|
||||
called.
|
||||
|
||||
|
||||
@subsubsection cursor_set Cursor setting
|
||||
|
||||
A cursor can be set as current for a window with @ref glfwSetCursor.
|
||||
|
||||
@code
|
||||
glfwSetCursor(window, cursor);
|
||||
@endcode
|
||||
|
||||
Once set, the cursor image will be used as long as the system cursor is over the
|
||||
client area of the window and the [cursor mode](@ref cursor_mode) is set
|
||||
to `GLFW_CURSOR_NORMAL`.
|
||||
|
||||
A single cursor may be set for any number of windows.
|
||||
|
||||
To revert to the default cursor, set the cursor of that window to `NULL`.
|
||||
|
||||
@code
|
||||
glfwSetCursor(window, NULL);
|
||||
@endcode
|
||||
|
||||
When a cursor is destroyed, any window that has it set will revert to the
|
||||
default cursor. This does not affect the cursor mode.
|
||||
|
||||
|
||||
@subsection cursor_enter Cursor enter/leave events
|
||||
|
||||
If you wish to be notified when the cursor enters or leaves the client area of
|
||||
a window, set a cursor enter/leave callback.
|
||||
|
||||
@code
|
||||
glfwSetCursorEnterCallback(window, cursor_enter_callback);
|
||||
@endcode
|
||||
|
||||
The callback function receives the new classification of the cursor.
|
||||
|
||||
@code
|
||||
void cursor_enter_callback(GLFWwindow* window, int entered)
|
||||
{
|
||||
if (entered)
|
||||
{
|
||||
// The cursor entered the client area of the window
|
||||
}
|
||||
else
|
||||
{
|
||||
// The cursor left the client area of the window
|
||||
}
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection input_mouse_button Mouse button input
|
||||
|
||||
If you wish to be notified when a mouse button is pressed or released, set
|
||||
a mouse button callback.
|
||||
|
||||
@code
|
||||
glfwSetMouseButtonCallback(window, mouse_button_callback);
|
||||
@endcode
|
||||
|
||||
The callback function receives the [mouse button](@ref buttons), button action
|
||||
and [modifier bits](@ref mods).
|
||||
|
||||
@code
|
||||
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
|
||||
{
|
||||
if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
|
||||
popup_menu();
|
||||
}
|
||||
@endcode
|
||||
|
||||
The action is one of `GLFW_PRESS` or `GLFW_RELEASE`.
|
||||
|
||||
Mouse button states for [named buttons](@ref buttons) are also saved in
|
||||
per-window state arrays that can be polled with @ref glfwGetMouseButton.
|
||||
|
||||
@code
|
||||
int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
|
||||
if (state == GLFW_PRESS)
|
||||
{
|
||||
upgrade_cow();
|
||||
}
|
||||
@endcode
|
||||
|
||||
The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
|
||||
|
||||
This function only returns cached mouse button event state. It does not poll
|
||||
the system for the current state of the mouse button.
|
||||
|
||||
@anchor GLFW_STICKY_MOUSE_BUTTONS
|
||||
Whenever you poll state, you risk missing the state change you are looking for.
|
||||
If a pressed mouse button is released again before you poll its state, you will have
|
||||
missed the button press. The recommended solution for this is to use a
|
||||
mouse button callback, but there is also the `GLFW_STICKY_MOUSE_BUTTONS`
|
||||
input mode.
|
||||
|
||||
@code
|
||||
glfwSetInputMode(window, GLFW_STICKY_MOUSE_BUTTONS, 1);
|
||||
@endcode
|
||||
|
||||
When sticky mouse buttons mode is enabled, the pollable state of a mouse button
|
||||
will remain `GLFW_PRESS` until the state of that button is polled with @ref
|
||||
glfwGetMouseButton. Once it has been polled, if a mouse button release event
|
||||
had been processed in the meantime, the state will reset to `GLFW_RELEASE`,
|
||||
otherwise it will remain `GLFW_PRESS`.
|
||||
|
||||
The `GLFW_MOUSE_BUTTON_LAST` constant holds the highest value of any
|
||||
[named button](@ref buttons).
|
||||
|
||||
|
||||
@subsection scrolling Scroll input
|
||||
|
||||
If you wish to be notified when the user scrolls, whether with a mouse wheel or
|
||||
touchpad gesture, set a scroll callback.
|
||||
|
||||
@code
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
@endcode
|
||||
|
||||
The callback function receives two-dimensional scroll offsets.
|
||||
|
||||
@code
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
}
|
||||
@endcode
|
||||
|
||||
A simple mouse wheel, being vertical, provides offsets along the Y-axis.
|
||||
|
||||
|
||||
@section joystick Joystick input
|
||||
|
||||
The joystick functions expose connected joysticks and controllers, with both
|
||||
referred to as joysticks. It supports up to sixteen joysticks, ranging from
|
||||
`GLFW_JOYSTICK_1`, `GLFW_JOYSTICK_2` up to and including `GLFW_JOYSTICK_16` or
|
||||
`GLFW_JOYSTICK_LAST`. You can test whether a [joystick](@ref joysticks) is
|
||||
present with @ref glfwJoystickPresent.
|
||||
|
||||
@code
|
||||
int present = glfwJoystickPresent(GLFW_JOYSTICK_1);
|
||||
@endcode
|
||||
|
||||
When GLFW is initialized, detected joysticks are added to to the beginning of
|
||||
the array. Once a joystick is detected, it keeps its assigned ID until it is
|
||||
disconnected or the library is terminated, so as joysticks are connected and
|
||||
disconnected, there may appear gaps in the IDs.
|
||||
|
||||
Joystick axis, button and hat state is updated when polled and does not require
|
||||
a window to be created or events to be processed. However, if you want joystick
|
||||
connection and disconnection events reliably delivered to the
|
||||
[joystick callback](@ref joystick_event) then you must
|
||||
[process events](@ref events).
|
||||
|
||||
To see all the properties of all connected joysticks in real-time, run the
|
||||
`joysticks` test program.
|
||||
|
||||
|
||||
@subsection joystick_axis Joystick axis states
|
||||
|
||||
The positions of all axes of a joystick are returned by @ref
|
||||
glfwGetJoystickAxes. See the reference documentation for the lifetime of the
|
||||
returned array.
|
||||
|
||||
@code
|
||||
int count;
|
||||
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_5, &count);
|
||||
@endcode
|
||||
|
||||
Each element in the returned array is a value between -1.0 and 1.0.
|
||||
|
||||
|
||||
@subsection joystick_button Joystick button states
|
||||
|
||||
The states of all buttons of a joystick are returned by @ref
|
||||
glfwGetJoystickButtons. See the reference documentation for the lifetime of the
|
||||
returned array.
|
||||
|
||||
@code
|
||||
int count;
|
||||
const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_3, &count);
|
||||
@endcode
|
||||
|
||||
Each element in the returned array is either `GLFW_PRESS` or `GLFW_RELEASE`.
|
||||
|
||||
For backward compatibility with earlier versions that did not have @ref
|
||||
glfwGetJoystickHats, the button array by default also includes all hats. See
|
||||
the reference documentation for @ref glfwGetJoystickButtons for details.
|
||||
|
||||
|
||||
@subsection joystick_hat Joystick hat states
|
||||
|
||||
The states of all hats are returned by @ref glfwGetJoystickHats. See the
|
||||
reference documentation for the lifetime of the returned array.
|
||||
|
||||
@code
|
||||
int count;
|
||||
const unsigned char* hats = glfwGetJoystickHats(GLFW_JOYSTICK_7, &count);
|
||||
@endcode
|
||||
|
||||
Each element in the returned array is one of the following:
|
||||
|
||||
Name | Value
|
||||
--------------------- | --------------------------------
|
||||
`GLFW_HAT_CENTERED` | 0
|
||||
`GLFW_HAT_UP` | 1
|
||||
`GLFW_HAT_RIGHT` | 2
|
||||
`GLFW_HAT_DOWN` | 4
|
||||
`GLFW_HAT_LEFT` | 8
|
||||
`GLFW_HAT_RIGHT_UP` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP`
|
||||
`GLFW_HAT_RIGHT_DOWN` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_DOWN`
|
||||
`GLFW_HAT_LEFT_UP` | `GLFW_HAT_LEFT` \| `GLFW_HAT_UP`
|
||||
`GLFW_HAT_LEFT_DOWN` | `GLFW_HAT_LEFT` \| `GLFW_HAT_DOWN`
|
||||
|
||||
The diagonal directions are bitwise combinations of the primary (up, right, down
|
||||
and left) directions and you can test for these individually by ANDing it with
|
||||
the corresponding direction.
|
||||
|
||||
@code
|
||||
if (hats[2] & GLFW_HAT_RIGHT)
|
||||
{
|
||||
// State of hat 2 could be right-up, right or right-down
|
||||
}
|
||||
@endcode
|
||||
|
||||
For backward compatibility with earlier versions that did not have @ref
|
||||
glfwGetJoystickHats, all hats are by default also included in the button array.
|
||||
See the reference documentation for @ref glfwGetJoystickButtons for details.
|
||||
|
||||
|
||||
@subsection joystick_name Joystick name
|
||||
|
||||
The human-readable, UTF-8 encoded name of a joystick is returned by @ref
|
||||
glfwGetJoystickName. See the reference documentation for the lifetime of the
|
||||
returned string.
|
||||
|
||||
@code
|
||||
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_4);
|
||||
@endcode
|
||||
|
||||
Joystick names are not guaranteed to be unique. Two joysticks of the same model
|
||||
and make may have the same name. Only the [joystick token](@ref joysticks) is
|
||||
guaranteed to be unique, and only until that joystick is disconnected.
|
||||
|
||||
|
||||
@subsection joystick_event Joystick configuration changes
|
||||
|
||||
If you wish to be notified when a joystick is connected or disconnected, set
|
||||
a joystick callback.
|
||||
|
||||
@code
|
||||
glfwSetJoystickCallback(joystick_callback);
|
||||
@endcode
|
||||
|
||||
The callback function receives the ID of the joystick that has been connected
|
||||
and disconnected and the event that occurred.
|
||||
|
||||
@code
|
||||
void joystick_callback(int jid, int event)
|
||||
{
|
||||
if (event == GLFW_CONNECTED)
|
||||
{
|
||||
// The joystick was connected
|
||||
}
|
||||
else if (event == GLFW_DISCONNECTED)
|
||||
{
|
||||
// The joystick was disconnected
|
||||
}
|
||||
}
|
||||
@endcode
|
||||
|
||||
For joystick connection and disconnection events to be delivered on all
|
||||
platforms, you need to call one of the [event processing](@ref events)
|
||||
functions. Joystick disconnection may also be detected and the callback
|
||||
called by joystick functions. The function will then return whatever it
|
||||
returns for a disconnected joystick.
|
||||
|
||||
|
||||
@section time Time input
|
||||
|
||||
GLFW provides high-resolution time input, in seconds, with @ref glfwGetTime.
|
||||
|
||||
@code
|
||||
double seconds = glfwGetTime();
|
||||
@endcode
|
||||
|
||||
It returns the number of seconds since the timer was started when the library
|
||||
was initialized with @ref glfwInit. The platform-specific time sources used
|
||||
usually have micro- or nanosecond resolution.
|
||||
|
||||
You can modify the reference time with @ref glfwSetTime.
|
||||
|
||||
@code
|
||||
glfwSetTime(4.0);
|
||||
@endcode
|
||||
|
||||
This sets the timer to the specified time, in seconds.
|
||||
|
||||
You can also access the raw timer value, measured in 1 / frequency
|
||||
seconds, with @ref glfwGetTimerValue.
|
||||
|
||||
@code
|
||||
uint64_t value = glfwGetTimerValue();
|
||||
@endcode
|
||||
|
||||
The frequency of the raw timer varies depending on what time sources are
|
||||
available on the machine. You can query its frequency, in Hz, with @ref
|
||||
glfwGetTimerFrequency.
|
||||
|
||||
@code
|
||||
uint64_t freqency = glfwGetTimerFrequency();
|
||||
@endcode
|
||||
|
||||
|
||||
@section clipboard Clipboard input and output
|
||||
|
||||
If the system clipboard contains a UTF-8 encoded string or if it can be
|
||||
converted to one, you can retrieve it with @ref glfwGetClipboardString. See the
|
||||
reference documentation for the lifetime of the returned string.
|
||||
|
||||
@code
|
||||
const char* text = glfwGetClipboardString(window);
|
||||
if (text)
|
||||
{
|
||||
insert_text(text);
|
||||
}
|
||||
@endcode
|
||||
|
||||
If the clipboard is empty or if its contents could not be converted, `NULL` is
|
||||
returned.
|
||||
|
||||
The contents of the system clipboard can be set to a UTF-8 encoded string with
|
||||
@ref glfwSetClipboardString.
|
||||
|
||||
@code
|
||||
glfwSetClipboardString(window, "A string with words in it");
|
||||
@endcode
|
||||
|
||||
The clipboard functions take a window handle argument because some window
|
||||
systems require a window to communicate with the system clipboard. Any valid
|
||||
window may be used.
|
||||
|
||||
|
||||
@section path_drop Path drop input
|
||||
|
||||
If you wish to receive the paths of files and/or directories dropped on
|
||||
a window, set a file drop callback.
|
||||
|
||||
@code
|
||||
glfwSetDropCallback(window, drop_callback);
|
||||
@endcode
|
||||
|
||||
The callback function receives an array of paths encoded as UTF-8.
|
||||
|
||||
@code
|
||||
void drop_callback(GLFWwindow* window, int count, const char** paths)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < count; i++)
|
||||
handle_dropped_file(paths[i]);
|
||||
}
|
||||
@endcode
|
||||
|
||||
The path array and its strings are only valid until the file drop callback
|
||||
returns, as they may have been generated specifically for that event. You need
|
||||
to make a deep copy of the array if you want to keep the paths.
|
||||
|
||||
*/
|
|
@ -0,0 +1,116 @@
|
|||
/*!
|
||||
|
||||
@page internals_guide Internal structure
|
||||
|
||||
@tableofcontents
|
||||
|
||||
There are several interfaces inside GLFW. Each interface has its own area of
|
||||
responsibility and its own naming conventions.
|
||||
|
||||
|
||||
@section internals_public Public interface
|
||||
|
||||
The most well-known is the public interface, described in the glfw3.h header
|
||||
file. This is implemented in source files shared by all platforms and these
|
||||
files contain no platform-specific code. This code usually ends up calling the
|
||||
platform and internal interfaces to do the actual work.
|
||||
|
||||
The public interface uses the OpenGL naming conventions except with GLFW and
|
||||
glfw instead of GL and gl. For struct members, where OpenGL sets no precedent,
|
||||
it use headless camel case.
|
||||
|
||||
Examples: @ref glfwCreateWindow, @ref GLFWwindow, @ref GLFWvidmode.redBits,
|
||||
`GLFW_RED_BITS`
|
||||
|
||||
|
||||
@section internals_native Native interface
|
||||
|
||||
The [native interface](@ref native) is a small set of publicly available
|
||||
but platform-specific functions, described in the glfw3native.h header file and
|
||||
used to gain access to the underlying window, context and (on some platforms)
|
||||
display handles used by the platform interface.
|
||||
|
||||
The function names of the native interface are similar to those of the public
|
||||
interface, but embeds the name of the interface that the returned handle is
|
||||
from.
|
||||
|
||||
Examples: @ref glfwGetX11Window, @ref glfwGetWGLContext
|
||||
|
||||
|
||||
@section internals_internal Internal interface
|
||||
|
||||
The internal interface consists of utility functions used by all other
|
||||
interfaces. It is shared code implemented in the same shared source files as
|
||||
the public and event interfaces. The internal interface is described in the
|
||||
internal.h header file.
|
||||
|
||||
The internal interface is in charge of GLFW's global data, which it stores in
|
||||
a `_GLFWlibrary` struct named `_glfw`.
|
||||
|
||||
The internal interface uses the same style as the public interface, except all
|
||||
global names have a leading underscore.
|
||||
|
||||
Examples: @ref _glfwIsValidContextConfig, @ref _GLFWwindow, `_glfw.currentRamp`
|
||||
|
||||
|
||||
@section internals_platform Platform interface
|
||||
|
||||
The platform interface implements all platform-specific operations as a service
|
||||
to the public interface. This includes event processing. The platform
|
||||
interface is never directly called by application code and never directly calls
|
||||
application-provided callbacks. It is also prohibited from modifying the
|
||||
platform-independent part of the internal structs. Instead, it calls the event
|
||||
interface when events interesting to GLFW are received.
|
||||
|
||||
The platform interface mirrors those parts of the public interface that needs to
|
||||
perform platform-specific operations on some or all platforms. The are also
|
||||
named the same except that the glfw function prefix is replaced by
|
||||
_glfwPlatform.
|
||||
|
||||
Examples: @ref _glfwPlatformCreateWindow
|
||||
|
||||
The platform interface also defines structs that contain platform-specific
|
||||
global and per-object state. Their names mirror those of the internal
|
||||
interface, except that an interface-specific suffix is added.
|
||||
|
||||
Examples: `_GLFWwindowX11`, `_GLFWcontextWGL`
|
||||
|
||||
These structs are incorporated as members into the internal interface structs
|
||||
using special macros that name them after the specific interface used. This
|
||||
prevents shared code from accidentally using these members.
|
||||
|
||||
Examples: `window.win32.handle`, `_glfw.x11.display`
|
||||
|
||||
|
||||
@section internals_event Event interface
|
||||
|
||||
The event interface is implemented in the same shared source files as the public
|
||||
interface and is responsible for delivering the events it receives to the
|
||||
application, either via callbacks, via window state changes or both.
|
||||
|
||||
The function names of the event interface use a `_glfwInput` prefix and the
|
||||
ObjectEvent pattern.
|
||||
|
||||
Examples: @ref _glfwInputWindowFocus, @ref _glfwInputCursorMotion
|
||||
|
||||
|
||||
@section internals_static Static functions
|
||||
|
||||
Static functions may be used by any interface and have no prefixes or suffixes.
|
||||
These use headless camel case.
|
||||
|
||||
Examples: `clearScrollOffsets`
|
||||
|
||||
|
||||
@section internals_config Configuration macros
|
||||
|
||||
GLFW uses a number of configuration macros to select at compile time which
|
||||
interfaces and code paths to use. They are defined in the glfw_config.h header file,
|
||||
which is generated from the `glfw_config.h.in` file by CMake.
|
||||
|
||||
Configuration macros the same style as tokens in the public interface, except
|
||||
with a leading underscore.
|
||||
|
||||
Examples: `_GLFW_USE_HYBRID_HPG`
|
||||
|
||||
*/
|
|
@ -0,0 +1,434 @@
|
|||
/*!
|
||||
|
||||
@page intro_guide Introduction to the API
|
||||
|
||||
@tableofcontents
|
||||
|
||||
This guide introduces the basic concepts of GLFW and describes initialization,
|
||||
error handling and API guarantees and limitations. For a broad but shallow
|
||||
tutorial, see @ref quick_guide instead. For details on a specific function in
|
||||
this category, see the @ref init.
|
||||
|
||||
There are also guides for the other areas of GLFW.
|
||||
|
||||
- @ref window_guide
|
||||
- @ref context_guide
|
||||
- @ref vulkan_guide
|
||||
- @ref monitor_guide
|
||||
- @ref input_guide
|
||||
|
||||
|
||||
@section intro_init Initialization and termination
|
||||
|
||||
Before most GLFW functions may be called, the library must be initialized.
|
||||
This initialization checks what features are available on the machine,
|
||||
enumerates monitors and joysticks, initializes the timer and performs any
|
||||
required platform-specific initialization.
|
||||
|
||||
Only the following functions may be called before the library has been
|
||||
successfully initialized, and only from the main thread.
|
||||
|
||||
- @ref glfwGetVersion
|
||||
- @ref glfwGetVersionString
|
||||
- @ref glfwGetError
|
||||
- @ref glfwSetErrorCallback
|
||||
- @ref glfwInitHint
|
||||
- @ref glfwInit
|
||||
- @ref glfwTerminate
|
||||
|
||||
Calling any other function before successful initialization will cause a @ref
|
||||
GLFW_NOT_INITIALIZED error.
|
||||
|
||||
|
||||
@subsection intro_init_init Initializing GLFW
|
||||
|
||||
The library is initialized with @ref glfwInit, which returns `GLFW_FALSE` if an
|
||||
error occurred.
|
||||
|
||||
@code
|
||||
if (!glfwInit())
|
||||
{
|
||||
// Handle initialization failure
|
||||
}
|
||||
@endcode
|
||||
|
||||
If any part of initialization fails, any parts that succeeded are terminated as
|
||||
if @ref glfwTerminate had been called. The library only needs to be initialized
|
||||
once and additional calls to an already initialized library will simply return
|
||||
`GLFW_TRUE` immediately.
|
||||
|
||||
Once the library has been successfully initialized, it should be terminated
|
||||
before the application exits. Modern systems are very good at freeing resources
|
||||
allocated by programs that simply exit, but GLFW sometimes has to change global
|
||||
system settings and these might not be restored without termination.
|
||||
|
||||
|
||||
@subsection init_hints Initialization hints
|
||||
|
||||
There are a number of hints that can be set before initialization, that affect
|
||||
how the library behaves.
|
||||
|
||||
The values you set are not affected by initialization or termination, but they
|
||||
are only read during initialization. Once GLFW has been initialized, setting
|
||||
new hint values will not affect behavior until the next time it is terminated
|
||||
and initialized.
|
||||
|
||||
Some hints are platform specific. These are always valid to set on any
|
||||
platform but they will only affect their specific platform. Other platforms
|
||||
will simply ignore them. Setting these hints requires no platform specific
|
||||
headers or calls.
|
||||
|
||||
@anchor GLFW_JOYSTICK_HAT_BUTTONS
|
||||
__GLFW_JOYSTICK_HAT_BUTTONS__ specifies whether to also expose joystick hats as
|
||||
buttons, for compatibility with earlier versions of GLFW that did not have @ref
|
||||
glfwGetJoystickHats.
|
||||
|
||||
|
||||
@subsubsection init_hints_osx macOS specific hints
|
||||
|
||||
@anchor GLFW_COCOA_CHDIR_RESOURCES
|
||||
__GLFW_COCOA_CHDIR_RESOURCES__ specifies whether to set the current directory to
|
||||
the application to the `Contents/Resources` subdirectory of the application's
|
||||
bundle, if present.
|
||||
|
||||
@anchor GLFW_COCOA_MENUBAR
|
||||
__GLFW_COCOA_MENUBAR__ specifies whether to create a basic menu bar, either from
|
||||
a nib or manually, when the first window is created, which is when AppKit is
|
||||
initialized.
|
||||
|
||||
|
||||
@subsubsection init_hints_values Supported and default values
|
||||
|
||||
Init hint | Default value | Supported values
|
||||
------------------------------- | ------------- | ----------------
|
||||
@ref GLFW_JOYSTICK_HAT_BUTTONS | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
@ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
@ref GLFW_COCOA_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
|
||||
|
||||
@subsection intro_init_terminate Terminating GLFW
|
||||
|
||||
Before your application exits, you should terminate the GLFW library if it has
|
||||
been initialized. This is done with @ref glfwTerminate.
|
||||
|
||||
@code
|
||||
glfwTerminate();
|
||||
@endcode
|
||||
|
||||
This will destroy any remaining window, monitor and cursor objects, restore any
|
||||
modified gamma ramps, re-enable the screensaver if it had been disabled and free
|
||||
any other resources allocated by GLFW.
|
||||
|
||||
Once the library is terminated, it is as if it had never been initialized and
|
||||
you will need to initialize it again before being able to use GLFW. If the
|
||||
library was not initialized or had already been terminated, it return
|
||||
immediately.
|
||||
|
||||
|
||||
@section error_handling Error handling
|
||||
|
||||
Some GLFW functions have return values that indicate an error, but this is often
|
||||
not very helpful when trying to figure out _why_ the error occurred. Other
|
||||
functions have no return value reserved for errors, so error notification needs
|
||||
a separate channel. Finally, far from all GLFW functions have return values.
|
||||
|
||||
The last error code for the calling thread can be queried at any time with @ref
|
||||
glfwGetError.
|
||||
|
||||
@code
|
||||
int error = glfwGetError();
|
||||
@endcode
|
||||
|
||||
If no error has occurred since the last call, @ref GLFW_NO_ERROR is returned.
|
||||
The error is cleared before the function returns.
|
||||
|
||||
The error code indicates the general category of the error. Some error codes,
|
||||
such as @ref GLFW_NOT_INITIALIZED has only a single meaning, whereas others like
|
||||
@ref GLFW_PLATFORM_ERROR are used for many different errors.
|
||||
|
||||
GLFW usually has much more information about the error than its general category
|
||||
at the point where it occurred. This is where the error callback comes in.
|
||||
This callback is called whenever an error occurs. It is set with @ref
|
||||
glfwSetErrorCallback, a function that may be called regardless of whether GLFW
|
||||
is initialized.
|
||||
|
||||
@code
|
||||
glfwSetErrorCallback(error_callback);
|
||||
@endcode
|
||||
|
||||
The error callback receives a human-readable description of the error and (when
|
||||
possible) its cause. The description encoded as UTF-8. The callback is also
|
||||
provided with an [error code](@ref errors).
|
||||
|
||||
@code
|
||||
void error_callback(int error, const char* description)
|
||||
{
|
||||
puts(description);
|
||||
}
|
||||
@endcode
|
||||
|
||||
The error callback is called after the error code is set, so calling @ref
|
||||
glfwGetError from within the error callback returns the same value as the
|
||||
callback argument.
|
||||
|
||||
__Reported errors are never fatal.__ As long as GLFW was successfully
|
||||
initialized, it will remain initialized and in a safe state until terminated
|
||||
regardless of how many errors occur. If an error occurs during initialization
|
||||
that causes @ref glfwInit to fail, any part of the library that was initialized
|
||||
will be safely terminated.
|
||||
|
||||
The description string is only valid until the error callback returns, as it may
|
||||
have been generated specifically for that error. This lets GLFW provide much
|
||||
more specific error descriptions but means you must make a copy if you want to
|
||||
keep the description string.
|
||||
|
||||
Do not rely on a currently invalid call to generate a specific error, as in the
|
||||
future that same call may generate a different error or become valid.
|
||||
|
||||
|
||||
@section coordinate_systems Coordinate systems
|
||||
|
||||
GLFW has two primary coordinate systems: the _virtual screen_ and the window
|
||||
_client area_ or _content area_. Both use the same unit: _virtual screen
|
||||
coordinates_, or just _screen coordinates_, which don't necessarily correspond
|
||||
to pixels.
|
||||
|
||||
<img src="spaces.svg" width="90%" />
|
||||
|
||||
Both the virtual screen and the client area coordinate systems have the X-axis
|
||||
pointing to the right and the Y-axis pointing down.
|
||||
|
||||
Window and monitor positions are specified as the position of the upper-left
|
||||
corners of their content areas relative to the virtual screen, while cursor
|
||||
positions are specified relative to a window's client area.
|
||||
|
||||
Because the origin of the window's client area coordinate system is also the
|
||||
point from which the window position is specified, you can translate client area
|
||||
coordinates to the virtual screen by adding the window position. The window
|
||||
frame, when present, extends out from the client area but does not affect the
|
||||
window position.
|
||||
|
||||
Almost all positions and sizes in GLFW are measured in screen coordinates
|
||||
relative to one of the two origins above. This includes cursor positions,
|
||||
window positions and sizes, window frame sizes, monitor positions and video mode
|
||||
resolutions.
|
||||
|
||||
Two exceptions are the [monitor physical size](@ref monitor_size), which is
|
||||
measured in millimetres, and [framebuffer size](@ref window_fbsize), which is
|
||||
measured in pixels.
|
||||
|
||||
Pixels and screen coordinates may map 1:1 on your machine, but they won't on
|
||||
every other machine, for example on a Mac with a Retina display. The ratio
|
||||
between screen coordinates and pixels may also change at run-time depending on
|
||||
which monitor the window is currently considered to be on.
|
||||
|
||||
|
||||
@section guarantees_limitations Guarantees and limitations
|
||||
|
||||
This section describes the conditions under which GLFW can be expected to
|
||||
function, barring bugs in the operating system or drivers. Use of GLFW outside
|
||||
of these limits may work on some platforms, or on some machines, or some of the
|
||||
time, or on some versions of GLFW, but it may break at any time and this will
|
||||
not be considered a bug.
|
||||
|
||||
|
||||
@subsection lifetime Pointer lifetimes
|
||||
|
||||
GLFW will never free any pointer you provide to it and you must never free any
|
||||
pointer it provides to you.
|
||||
|
||||
Many GLFW functions return pointers to dynamically allocated structures, strings
|
||||
or arrays, and some callbacks are provided with strings or arrays. These are
|
||||
always managed by GLFW and should never be freed by the application. The
|
||||
lifetime of these pointers is documented for each GLFW function and callback.
|
||||
If you need to keep this data, you must copy it before its lifetime expires.
|
||||
|
||||
Many GLFW functions accept pointers to structures or strings allocated by the
|
||||
application. These are never freed by GLFW and are always the responsibility of
|
||||
the application. If GLFW needs to keep the data in these structures or strings,
|
||||
it is copied before the function returns.
|
||||
|
||||
Pointer lifetimes are guaranteed not to be shortened in future minor or patch
|
||||
releases.
|
||||
|
||||
|
||||
@subsection reentrancy Reentrancy
|
||||
|
||||
GLFW event processing and object destruction are not reentrant. This means that
|
||||
the following functions must not be called from any callback function:
|
||||
|
||||
- @ref glfwDestroyWindow
|
||||
- @ref glfwDestroyCursor
|
||||
- @ref glfwPollEvents
|
||||
- @ref glfwWaitEvents
|
||||
- @ref glfwWaitEventsTimeout
|
||||
- @ref glfwTerminate
|
||||
|
||||
These functions may be made reentrant in future minor or patch releases, but
|
||||
functions not on this list will not be made non-reentrant.
|
||||
|
||||
|
||||
@subsection thread_safety Thread safety
|
||||
|
||||
Most GLFW functions must only be called from the main thread, but some may be
|
||||
called from any thread. However, no GLFW function may be called from any thread
|
||||
but the main thread until GLFW has been successfully initialized, including
|
||||
functions that may called before initialization.
|
||||
|
||||
The reference documentation for every GLFW function states whether it is limited
|
||||
to the main thread.
|
||||
|
||||
Initialization and termination, event processing and the creation and
|
||||
destruction of windows, contexts and cursors are all limited to the main thread
|
||||
due to limitations of one or several platforms.
|
||||
|
||||
Because event processing must be performed on the main thread, all callbacks
|
||||
except for the error callback will only be called on that thread. The error
|
||||
callback may be called on any thread, as any GLFW function may generate errors.
|
||||
|
||||
The posting of empty events may be done from any thread. The window user
|
||||
pointer and close flag may also be accessed and modified from any thread, but
|
||||
this is not synchronized by GLFW. The following window related functions may
|
||||
be called from any thread:
|
||||
|
||||
- @ref glfwPostEmptyEvent
|
||||
- @ref glfwGetWindowUserPointer
|
||||
- @ref glfwSetWindowUserPointer
|
||||
- @ref glfwWindowShouldClose
|
||||
- @ref glfwSetWindowShouldClose
|
||||
|
||||
Rendering may be done on any thread. The following context related functions
|
||||
may be called from any thread:
|
||||
|
||||
- @ref glfwMakeContextCurrent
|
||||
- @ref glfwGetCurrentContext
|
||||
- @ref glfwSwapBuffers
|
||||
- @ref glfwSwapInterval
|
||||
- @ref glfwExtensionSupported
|
||||
- @ref glfwGetProcAddress
|
||||
|
||||
The raw timer may be queried from any thread. The following raw timer related
|
||||
functions may be called from any thread:
|
||||
|
||||
- @ref glfwGetTimerFrequency
|
||||
- @ref glfwGetTimerValue
|
||||
|
||||
The regular timer may be used from any thread, but the reading and writing of
|
||||
the timer offset is not synchronized by GLFW. The following timer related
|
||||
functions may be called from any thread:
|
||||
|
||||
- @ref glfwGetTime
|
||||
- @ref glfwSetTime
|
||||
|
||||
Library version information may be queried from any thread. The following
|
||||
version related functions may be called from any thread:
|
||||
|
||||
- @ref glfwGetVersion
|
||||
- @ref glfwGetVersionString
|
||||
|
||||
Vulkan objects may be created and information queried from any thread. The
|
||||
following Vulkan related functions may be called from any thread:
|
||||
|
||||
- @ref glfwVulkanSupported
|
||||
- @ref glfwGetRequiredInstanceExtensions
|
||||
- @ref glfwGetInstanceProcAddress
|
||||
- @ref glfwGetPhysicalDevicePresentationSupport
|
||||
- @ref glfwCreateWindowSurface
|
||||
|
||||
GLFW uses no synchronization objects internally except for thread-local storage
|
||||
to keep track of the current context for each thread. Synchronization is left
|
||||
to the application.
|
||||
|
||||
Functions that may currently be called from any thread will always remain so,
|
||||
but functions that are currently limited to the main thread may be updated to
|
||||
allow calls from any thread in future releases.
|
||||
|
||||
|
||||
@subsection compatibility Version compatibility
|
||||
|
||||
GLFW guarantees source and binary backward compatibility with earlier minor
|
||||
versions of the API. This means that you can drop in a newer version of the
|
||||
library and existing programs will continue to compile and existing binaries
|
||||
will continue to run.
|
||||
|
||||
Once a function or constant has been added, the signature of that function or
|
||||
value of that constant will remain unchanged until the next major version of
|
||||
GLFW. No compatibility of any kind is guaranteed between major versions.
|
||||
|
||||
Undocumented behavior, i.e. behavior that is not described in the documentation,
|
||||
may change at any time until it is documented.
|
||||
|
||||
If the reference documentation and the implementation differ, the reference
|
||||
documentation is correct and the implementation will be fixed in the next
|
||||
release.
|
||||
|
||||
|
||||
@subsection event_order Event order
|
||||
|
||||
The order of arrival of related events is not guaranteed to be consistent
|
||||
across platforms. The exception is synthetic key and mouse button release
|
||||
events, which are always delivered after the window defocus event.
|
||||
|
||||
|
||||
@section intro_version Version management
|
||||
|
||||
GLFW provides mechanisms for identifying what version of GLFW your application
|
||||
was compiled against as well as what version it is currently running against.
|
||||
If you are loading GLFW dynamically (not just linking dynamically), you can use
|
||||
this to verify that the library binary is compatible with your application.
|
||||
|
||||
|
||||
@subsection intro_version_compile Compile-time version
|
||||
|
||||
The compile-time version of GLFW is provided by the GLFW header with the
|
||||
`GLFW_VERSION_MAJOR`, `GLFW_VERSION_MINOR` and `GLFW_VERSION_REVISION` macros.
|
||||
|
||||
@code
|
||||
printf("Compiled against GLFW %i.%i.%i\n",
|
||||
GLFW_VERSION_MAJOR,
|
||||
GLFW_VERSION_MINOR,
|
||||
GLFW_VERSION_REVISION);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection intro_version_runtime Run-time version
|
||||
|
||||
The run-time version can be retrieved with @ref glfwGetVersion, a function that
|
||||
may be called regardless of whether GLFW is initialized.
|
||||
|
||||
@code
|
||||
int major, minor, revision;
|
||||
glfwGetVersion(&major, &minor, &revision);
|
||||
|
||||
printf("Running against GLFW %i.%i.%i\n", major, minor, revision);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection intro_version_string Version string
|
||||
|
||||
GLFW 3 also provides a compile-time generated version string that describes the
|
||||
version, platform, compiler and any platform-specific compile-time options.
|
||||
This is primarily intended for submitting bug reports, to allow developers to
|
||||
see which code paths are enabled in a binary.
|
||||
|
||||
The version string is returned by @ref glfwGetVersionString, a function that may
|
||||
be called regardless of whether GLFW is initialized.
|
||||
|
||||
__Do not use the version string__ to parse the GLFW library version. The @ref
|
||||
glfwGetVersion function already provides the version of the running library
|
||||
binary.
|
||||
|
||||
The format of the string is as follows:
|
||||
- The version of GLFW
|
||||
- The name of the window system API
|
||||
- The name of the context creation API
|
||||
- Any additional options or APIs
|
||||
|
||||
For example, when compiling GLFW 3.0 with MinGW using the Win32 and WGL
|
||||
back ends, the version string may look something like this:
|
||||
|
||||
@code
|
||||
3.0.0 Win32 WGL MinGW
|
||||
@endcode
|
||||
|
||||
*/
|
|
@ -0,0 +1,47 @@
|
|||
/*!
|
||||
|
||||
@mainpage notitle
|
||||
|
||||
@section main_intro Introduction
|
||||
|
||||
GLFW is a free, Open Source, multi-platform library for OpenGL, OpenGL ES and
|
||||
Vulkan application development. It provides a simple, platform-independent API
|
||||
for creating windows, contexts and surfaces, reading input, handling events, etc.
|
||||
|
||||
See @ref news_33 for release highlights or the
|
||||
[version history](http://www.glfw.org/changelog.html) for details.
|
||||
|
||||
@ref quick_guide is a guide for users new to GLFW. It takes you through how to
|
||||
write a small but complete program.
|
||||
|
||||
There are guides for each section of the API:
|
||||
|
||||
- @ref intro_guide – initialization, error handling and high-level design
|
||||
- @ref window_guide – creating and working with windows and framebuffers
|
||||
- @ref context_guide – working with OpenGL and OpenGL ES contexts
|
||||
- @ref vulkan_guide - working with Vulkan objects and extensions
|
||||
- @ref monitor_guide – enumerating and working with monitors and video modes
|
||||
- @ref input_guide – receiving events, polling and processing input
|
||||
|
||||
Once you have written a program, see @ref compile_guide and @ref build_guide.
|
||||
|
||||
The [reference documentation](modules.html) provides more detailed information
|
||||
about specific functions.
|
||||
|
||||
@ref moving_guide explains what has changed and how to update existing code to
|
||||
use the new API.
|
||||
|
||||
There is a section on @ref guarantees_limitations for pointer lifetimes,
|
||||
reentrancy, thread safety, event order and backward and forward compatibility.
|
||||
|
||||
The [FAQ](http://www.glfw.org/faq.html) answers many common questions about the
|
||||
design, implementation and use of GLFW.
|
||||
|
||||
Finally, @ref compat_guide explains what APIs, standards and protocols GLFW uses
|
||||
and what happens when they are not present on a given machine.
|
||||
|
||||
This documentation was generated with Doxygen. The sources for it are available
|
||||
in both the [source distribution](http://www.glfw.org/download.html) and
|
||||
[GitHub repository](https://github.com/glfw/glfw).
|
||||
|
||||
*/
|
|
@ -0,0 +1,224 @@
|
|||
/*!
|
||||
|
||||
@page monitor_guide Monitor guide
|
||||
|
||||
@tableofcontents
|
||||
|
||||
This guide introduces the monitor related functions of GLFW. For details on
|
||||
a specific function in this category, see the @ref monitor. There are also
|
||||
guides for the other areas of GLFW.
|
||||
|
||||
- @ref intro_guide
|
||||
- @ref window_guide
|
||||
- @ref context_guide
|
||||
- @ref vulkan_guide
|
||||
- @ref input_guide
|
||||
|
||||
|
||||
@section monitor_object Monitor objects
|
||||
|
||||
A monitor object represents a currently connected monitor and is represented as
|
||||
a pointer to the [opaque](https://en.wikipedia.org/wiki/Opaque_data_type) type
|
||||
@ref GLFWmonitor. Monitor objects cannot be created or destroyed by the
|
||||
application and retain their addresses until the monitors they represent are
|
||||
disconnected or until the library is [terminated](@ref intro_init_terminate).
|
||||
|
||||
Each monitor has a current video mode, a list of supported video modes,
|
||||
a virtual position, a human-readable name, an estimated physical size and
|
||||
a gamma ramp. One of the monitors is the primary monitor.
|
||||
|
||||
The virtual position of a monitor is in
|
||||
[screen coordinates](@ref coordinate_systems) and, together with the current
|
||||
video mode, describes the viewports that the connected monitors provide into the
|
||||
virtual desktop that spans them.
|
||||
|
||||
To see how GLFW views your monitor setup and its available video modes, run the
|
||||
`monitors` test program.
|
||||
|
||||
|
||||
@subsection monitor_monitors Retrieving monitors
|
||||
|
||||
The primary monitor is returned by @ref glfwGetPrimaryMonitor. It is the user's
|
||||
preferred monitor and is usually the one with global UI elements like task bar
|
||||
or menu bar.
|
||||
|
||||
@code
|
||||
GLFWmonitor* primary = glfwGetPrimaryMonitor();
|
||||
@endcode
|
||||
|
||||
You can retrieve all currently connected monitors with @ref glfwGetMonitors.
|
||||
See the reference documentation for the lifetime of the returned array.
|
||||
|
||||
@code
|
||||
int count;
|
||||
GLFWmonitor** monitors = glfwGetMonitors(&count);
|
||||
@endcode
|
||||
|
||||
The primary monitor is always the first monitor in the returned array, but other
|
||||
monitors may be moved to a different index when a monitor is connected or
|
||||
disconnected.
|
||||
|
||||
|
||||
@subsection monitor_event Monitor configuration changes
|
||||
|
||||
If you wish to be notified when a monitor is connected or disconnected, set
|
||||
a monitor callback.
|
||||
|
||||
@code
|
||||
glfwSetMonitorCallback(monitor_callback);
|
||||
@endcode
|
||||
|
||||
The callback function receives the handle for the monitor that has been
|
||||
connected or disconnected and the event that occurred.
|
||||
|
||||
@code
|
||||
void monitor_callback(GLFWmonitor* monitor, int event)
|
||||
{
|
||||
if (event == GLFW_CONNECTED)
|
||||
{
|
||||
// The monitor was connected
|
||||
}
|
||||
else if (event == GLFW_DISCONNECTED)
|
||||
{
|
||||
// The monitor was disconnected
|
||||
}
|
||||
}
|
||||
@endcode
|
||||
|
||||
If a monitor is disconnected, any windows that are full screen on it get forced
|
||||
into windowed mode.
|
||||
|
||||
|
||||
@section monitor_properties Monitor properties
|
||||
|
||||
Each monitor has a current video mode, a list of supported video modes,
|
||||
a virtual position, a human-readable name, an estimated physical size and
|
||||
a gamma ramp.
|
||||
|
||||
|
||||
@subsection monitor_modes Video modes
|
||||
|
||||
GLFW generally does a good job selecting a suitable video mode when you create
|
||||
a full screen window, change its video mode or or make a windowed one full
|
||||
screen, but it is sometimes useful to know exactly which video modes are
|
||||
supported.
|
||||
|
||||
Video modes are represented as @ref GLFWvidmode structures. You can get an
|
||||
array of the video modes supported by a monitor with @ref glfwGetVideoModes.
|
||||
See the reference documentation for the lifetime of the returned array.
|
||||
|
||||
@code
|
||||
int count;
|
||||
GLFWvidmode* modes = glfwGetVideoModes(monitor, &count);
|
||||
@endcode
|
||||
|
||||
To get the current video mode of a monitor call @ref glfwGetVideoMode. See the
|
||||
reference documentation for the lifetime of the returned pointer.
|
||||
|
||||
@code
|
||||
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
||||
@endcode
|
||||
|
||||
The resolution of a video mode is specified in
|
||||
[screen coordinates](@ref coordinate_systems), not pixels.
|
||||
|
||||
|
||||
@subsection monitor_size Physical size
|
||||
|
||||
The physical size of a monitor in millimetres, or an estimation of it, can be
|
||||
retrieved with @ref glfwGetMonitorPhysicalSize. This has no relation to its
|
||||
current _resolution_, i.e. the width and height of its current
|
||||
[video mode](@ref monitor_modes).
|
||||
|
||||
@code
|
||||
int widthMM, heightMM;
|
||||
glfwGetMonitorPhysicalSize(monitor, &widthMM, &heightMM);
|
||||
@endcode
|
||||
|
||||
This can, for example, be used together with the current video mode to calculate
|
||||
the DPI of a monitor.
|
||||
|
||||
@code
|
||||
const double dpi = mode->width / (widthMM / 25.4);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection monitor_pos Virtual position
|
||||
|
||||
The position of the monitor on the virtual desktop, in
|
||||
[screen coordinates](@ref coordinate_systems), can be retrieved with @ref
|
||||
glfwGetMonitorPos.
|
||||
|
||||
@code
|
||||
int xpos, ypos;
|
||||
glfwGetMonitorPos(monitor, &xpos, &ypos);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection monitor_name Human-readable name
|
||||
|
||||
The human-readable, UTF-8 encoded name of a monitor is returned by @ref
|
||||
glfwGetMonitorName. See the reference documentation for the lifetime of the
|
||||
returned string.
|
||||
|
||||
@code
|
||||
const char* name = glfwGetMonitorName(monitor);
|
||||
@endcode
|
||||
|
||||
Monitor names are not guaranteed to be unique. Two monitors of the same model
|
||||
and make may have the same name. Only the monitor handle is guaranteed to be
|
||||
unique, and only until that monitor is disconnected.
|
||||
|
||||
|
||||
@subsection monitor_gamma Gamma ramp
|
||||
|
||||
The gamma ramp of a monitor can be set with @ref glfwSetGammaRamp, which accepts
|
||||
a monitor handle and a pointer to a @ref GLFWgammaramp structure.
|
||||
|
||||
@code
|
||||
GLFWgammaramp ramp;
|
||||
unsigned short red[256], green[256], blue[256];
|
||||
|
||||
ramp.size = 256;
|
||||
ramp.red = red;
|
||||
ramp.green = green;
|
||||
ramp.blue = blue;
|
||||
|
||||
for (i = 0; i < ramp.size; i++)
|
||||
{
|
||||
// Fill out gamma ramp arrays as desired
|
||||
}
|
||||
|
||||
glfwSetGammaRamp(monitor, &ramp);
|
||||
@endcode
|
||||
|
||||
The gamma ramp data is copied before the function returns, so there is no need
|
||||
to keep it around once the ramp has been set.
|
||||
|
||||
It is recommended that your gamma ramp have the same size as the current gamma
|
||||
ramp for that monitor.
|
||||
|
||||
The current gamma ramp for a monitor is returned by @ref glfwGetGammaRamp. See
|
||||
the reference documentation for the lifetime of the returned structure.
|
||||
|
||||
@code
|
||||
const GLFWgammaramp* ramp = glfwGetGammaRamp(monitor);
|
||||
@endcode
|
||||
|
||||
If you wish to set a regular gamma ramp, you can have GLFW calculate it for you
|
||||
from the desired exponent with @ref glfwSetGamma, which in turn calls @ref
|
||||
glfwSetGammaRamp with the resulting ramp.
|
||||
|
||||
@code
|
||||
glfwSetGamma(monitor, 1.0);
|
||||
@endcode
|
||||
|
||||
To experiment with gamma correction via the @ref glfwSetGamma function, run the
|
||||
`gamma` test program.
|
||||
|
||||
@note The software controlled gamma ramp is applied _in addition_ to the
|
||||
hardware gamma correction, which today is usually an approximation of sRGB
|
||||
gamma. This means that setting a perfectly linear ramp, or gamma 1.0, will
|
||||
produce the default (usually sRGB-like) behavior.
|
||||
|
||||
*/
|
|
@ -0,0 +1,513 @@
|
|||
/*!
|
||||
|
||||
@page moving_guide Moving from GLFW 2 to 3
|
||||
|
||||
@tableofcontents
|
||||
|
||||
This is a transition guide for moving from GLFW 2 to 3. It describes what has
|
||||
changed or been removed, but does _not_ include
|
||||
[new features](@ref news) unless they are required when moving an existing code
|
||||
base onto the new API. For example, the new multi-monitor functions are
|
||||
required to create full screen windows with GLFW 3.
|
||||
|
||||
|
||||
@section moving_removed Changed and removed features
|
||||
|
||||
@subsection moving_renamed_files Renamed library and header file
|
||||
|
||||
The GLFW 3 header is named @ref glfw3.h and moved to the `GLFW` directory, to
|
||||
avoid collisions with the headers of other major versions. Similarly, the GLFW
|
||||
3 library is named `glfw3,` except when it's installed as a shared library on
|
||||
Unix-like systems, where it uses the
|
||||
[soname](https://en.wikipedia.org/wiki/soname) `libglfw.so.3`.
|
||||
|
||||
@par Old syntax
|
||||
@code
|
||||
#include <GL/glfw.h>
|
||||
@endcode
|
||||
|
||||
@par New syntax
|
||||
@code
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection moving_threads Removal of threading functions
|
||||
|
||||
The threading functions have been removed, including the per-thread sleep
|
||||
function. They were fairly primitive, under-used, poorly integrated and took
|
||||
time away from the focus of GLFW (i.e. context, input and window). There are
|
||||
better threading libraries available and native threading support is available
|
||||
in both [C++11](http://en.cppreference.com/w/cpp/thread) and
|
||||
[C11](http://en.cppreference.com/w/c/thread), both of which are gaining
|
||||
traction.
|
||||
|
||||
If you wish to use the C++11 or C11 facilities but your compiler doesn't yet
|
||||
support them, see the
|
||||
[TinyThread++](https://gitorious.org/tinythread/tinythreadpp) and
|
||||
[TinyCThread](https://github.com/tinycthread/tinycthread) projects created by
|
||||
the original author of GLFW. These libraries implement a usable subset of the
|
||||
threading APIs in C++11 and C11, and in fact some GLFW 3 test programs use
|
||||
TinyCThread.
|
||||
|
||||
However, GLFW 3 has better support for _use from multiple threads_ than GLFW
|
||||
2 had. Contexts can be made current on any thread, although only a single
|
||||
thread at a time, and the documentation explicitly states which functions may be
|
||||
used from any thread and which must only be used from the main thread.
|
||||
|
||||
@par Removed functions
|
||||
`glfwSleep`, `glfwCreateThread`, `glfwDestroyThread`, `glfwWaitThread`,
|
||||
`glfwGetThreadID`, `glfwCreateMutex`, `glfwDestroyMutex`, `glfwLockMutex`,
|
||||
`glfwUnlockMutex`, `glfwCreateCond`, `glfwDestroyCond`, `glfwWaitCond`,
|
||||
`glfwSignalCond`, `glfwBroadcastCond` and `glfwGetNumberOfProcessors`.
|
||||
|
||||
@par Removed types
|
||||
`GLFWthreadfun`
|
||||
|
||||
|
||||
@subsection moving_image Removal of image and texture loading
|
||||
|
||||
The image and texture loading functions have been removed. They only supported
|
||||
the Targa image format, making them mostly useful for beginner level examples.
|
||||
To become of sufficiently high quality to warrant keeping them in GLFW 3, they
|
||||
would need not only to support other formats, but also modern extensions to
|
||||
OpenGL texturing. This would either add a number of external
|
||||
dependencies (libjpeg, libpng, etc.), or force GLFW to ship with inline versions
|
||||
of these libraries.
|
||||
|
||||
As there already are libraries doing this, it is unnecessary both to duplicate
|
||||
the work and to tie the duplicate to GLFW. The resulting library would also be
|
||||
platform-independent, as both OpenGL and stdio are available wherever GLFW is.
|
||||
|
||||
@par Removed functions
|
||||
`glfwReadImage`, `glfwReadMemoryImage`, `glfwFreeImage`, `glfwLoadTexture2D`,
|
||||
`glfwLoadMemoryTexture2D` and `glfwLoadTextureImage2D`.
|
||||
|
||||
|
||||
@subsection moving_stdcall Removal of GLFWCALL macro
|
||||
|
||||
The `GLFWCALL` macro, which made callback functions use
|
||||
[__stdcall](http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx) on Windows,
|
||||
has been removed. GLFW is written in C, not Pascal. Removing this macro means
|
||||
there's one less thing for application programmers to remember, i.e. the
|
||||
requirement to mark all callback functions with `GLFWCALL`. It also simplifies
|
||||
the creation of DLLs and DLL link libraries, as there's no need to explicitly
|
||||
disable `@n` entry point suffixes.
|
||||
|
||||
@par Old syntax
|
||||
@code
|
||||
void GLFWCALL callback_function(...);
|
||||
@endcode
|
||||
|
||||
@par New syntax
|
||||
@code
|
||||
void callback_function(...);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection moving_window_handles Window handle parameters
|
||||
|
||||
Because GLFW 3 supports multiple windows, window handle parameters have been
|
||||
added to all window-related GLFW functions and callbacks. The handle of
|
||||
a newly created window is returned by @ref glfwCreateWindow (formerly
|
||||
`glfwOpenWindow`). Window handles are pointers to the
|
||||
[opaque](https://en.wikipedia.org/wiki/Opaque_data_type) type @ref GLFWwindow.
|
||||
|
||||
@par Old syntax
|
||||
@code
|
||||
glfwSetWindowTitle("New Window Title");
|
||||
@endcode
|
||||
|
||||
@par New syntax
|
||||
@code
|
||||
glfwSetWindowTitle(window, "New Window Title");
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection moving_monitor Explicit monitor selection
|
||||
|
||||
GLFW 3 provides support for multiple monitors. To request a full screen mode window,
|
||||
instead of passing `GLFW_FULLSCREEN` you specify which monitor you wish the
|
||||
window to use. The @ref glfwGetPrimaryMonitor function returns the monitor that
|
||||
GLFW 2 would have selected, but there are many other
|
||||
[monitor functions](@ref monitor_guide). Monitor handles are pointers to the
|
||||
[opaque](https://en.wikipedia.org/wiki/Opaque_data_type) type @ref GLFWmonitor.
|
||||
|
||||
@par Old basic full screen
|
||||
@code
|
||||
glfwOpenWindow(640, 480, 8, 8, 8, 0, 24, 0, GLFW_FULLSCREEN);
|
||||
@endcode
|
||||
|
||||
@par New basic full screen
|
||||
@code
|
||||
window = glfwCreateWindow(640, 480, "My Window", glfwGetPrimaryMonitor(), NULL);
|
||||
@endcode
|
||||
|
||||
@note The framebuffer bit depth parameters of `glfwOpenWindow` have been turned
|
||||
into [window hints](@ref window_hints), but as they have been given
|
||||
[sane defaults](@ref window_hints_values) you rarely need to set these hints.
|
||||
|
||||
|
||||
@subsection moving_autopoll Removal of automatic event polling
|
||||
|
||||
GLFW 3 does not automatically poll for events in @ref glfwSwapBuffers, meaning
|
||||
you need to call @ref glfwPollEvents or @ref glfwWaitEvents yourself. Unlike
|
||||
buffer swap, which acts on a single window, the event processing functions act
|
||||
on all windows at once.
|
||||
|
||||
@par Old basic main loop
|
||||
@code
|
||||
while (...)
|
||||
{
|
||||
// Process input
|
||||
// Render output
|
||||
glfwSwapBuffers();
|
||||
}
|
||||
@endcode
|
||||
|
||||
@par New basic main loop
|
||||
@code
|
||||
while (...)
|
||||
{
|
||||
// Process input
|
||||
// Render output
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection moving_context Explicit context management
|
||||
|
||||
Each GLFW 3 window has its own OpenGL context and only you, the application
|
||||
programmer, can know which context should be current on which thread at any
|
||||
given time. Therefore, GLFW 3 leaves that decision to you.
|
||||
|
||||
This means that you need to call @ref glfwMakeContextCurrent after creating
|
||||
a window before you can call any OpenGL functions.
|
||||
|
||||
|
||||
@subsection moving_hidpi Separation of window and framebuffer sizes
|
||||
|
||||
Window positions and sizes now use screen coordinates, which may not be the same
|
||||
as pixels on machines with high-DPI monitors. This is important as OpenGL uses
|
||||
pixels, not screen coordinates. For example, the rectangle specified with
|
||||
`glViewport` needs to use pixels. Therefore, framebuffer size functions have
|
||||
been added. You can retrieve the size of the framebuffer of a window with @ref
|
||||
glfwGetFramebufferSize function. A framebuffer size callback has also been
|
||||
added, which can be set with @ref glfwSetFramebufferSizeCallback.
|
||||
|
||||
@par Old basic viewport setup
|
||||
@code
|
||||
glfwGetWindowSize(&width, &height);
|
||||
glViewport(0, 0, width, height);
|
||||
@endcode
|
||||
|
||||
@par New basic viewport setup
|
||||
@code
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
glViewport(0, 0, width, height);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection moving_window_close Window closing changes
|
||||
|
||||
The `GLFW_OPENED` window parameter has been removed. As long as the window has
|
||||
not been destroyed, whether through @ref glfwDestroyWindow or @ref
|
||||
glfwTerminate, the window is "open".
|
||||
|
||||
A user attempting to close a window is now just an event like any other. Unlike
|
||||
GLFW 2, windows and contexts created with GLFW 3 will never be destroyed unless
|
||||
you choose them to be. Each window now has a close flag that is set to
|
||||
`GLFW_TRUE` when the user attempts to close that window. By default, nothing else
|
||||
happens and the window stays visible. It is then up to you to either destroy
|
||||
the window, take some other action or simply ignore the request.
|
||||
|
||||
You can query the close flag at any time with @ref glfwWindowShouldClose and set
|
||||
it at any time with @ref glfwSetWindowShouldClose.
|
||||
|
||||
@par Old basic main loop
|
||||
@code
|
||||
while (glfwGetWindowParam(GLFW_OPENED))
|
||||
{
|
||||
...
|
||||
}
|
||||
@endcode
|
||||
|
||||
@par New basic main loop
|
||||
@code
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
...
|
||||
}
|
||||
@endcode
|
||||
|
||||
The close callback no longer returns a value. Instead, it is called after the
|
||||
close flag has been set so it can override its value, if it chooses to, before
|
||||
event processing completes. You may however not call @ref glfwDestroyWindow
|
||||
from the close callback (or any other window related callback).
|
||||
|
||||
@par Old syntax
|
||||
@code
|
||||
int GLFWCALL window_close_callback(void);
|
||||
@endcode
|
||||
|
||||
@par New syntax
|
||||
@code
|
||||
void window_close_callback(GLFWwindow* window);
|
||||
@endcode
|
||||
|
||||
@note GLFW never clears the close flag to `GLFW_FALSE`, meaning you can use it
|
||||
for other reasons to close the window as well, for example the user choosing
|
||||
Quit from an in-game menu.
|
||||
|
||||
|
||||
@subsection moving_hints Persistent window hints
|
||||
|
||||
The `glfwOpenWindowHint` function has been renamed to @ref glfwWindowHint.
|
||||
|
||||
Window hints are no longer reset to their default values on window creation, but
|
||||
instead retain their values until modified by @ref glfwWindowHint or @ref
|
||||
glfwDefaultWindowHints, or until the library is terminated and re-initialized.
|
||||
|
||||
|
||||
@subsection moving_video_modes Video mode enumeration
|
||||
|
||||
Video mode enumeration is now per-monitor. The @ref glfwGetVideoModes function
|
||||
now returns all available modes for a specific monitor instead of requiring you
|
||||
to guess how large an array you need. The `glfwGetDesktopMode` function, which
|
||||
had poorly defined behavior, has been replaced by @ref glfwGetVideoMode, which
|
||||
returns the current mode of a monitor.
|
||||
|
||||
|
||||
@subsection moving_char_up Removal of character actions
|
||||
|
||||
The action parameter of the [character callback](@ref GLFWcharfun) has been
|
||||
removed. This was an artefact of the origin of GLFW, i.e. being developed in
|
||||
English by a Swede. However, many keyboard layouts require more than one key to
|
||||
produce characters with diacritical marks. Even the Swedish keyboard layout
|
||||
requires this for uncommon cases like ü.
|
||||
|
||||
@par Old syntax
|
||||
@code
|
||||
void GLFWCALL character_callback(int character, int action);
|
||||
@endcode
|
||||
|
||||
@par New syntax
|
||||
@code
|
||||
void character_callback(GLFWwindow* window, int character);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection moving_cursorpos Cursor position changes
|
||||
|
||||
The `glfwGetMousePos` function has been renamed to @ref glfwGetCursorPos,
|
||||
`glfwSetMousePos` to @ref glfwSetCursorPos and `glfwSetMousePosCallback` to @ref
|
||||
glfwSetCursorPosCallback.
|
||||
|
||||
The cursor position is now `double` instead of `int`, both for the direct
|
||||
functions and for the callback. Some platforms can provide sub-pixel cursor
|
||||
movement and this data is now passed on to the application where available. On
|
||||
platforms where this is not provided, the decimal part is zero.
|
||||
|
||||
GLFW 3 only allows you to position the cursor within a window using @ref
|
||||
glfwSetCursorPos (formerly `glfwSetMousePos`) when that window is active.
|
||||
Unless the window is active, the function fails silently.
|
||||
|
||||
|
||||
@subsection moving_wheel Wheel position replaced by scroll offsets
|
||||
|
||||
The `glfwGetMouseWheel` function has been removed. Scrolling is the input of
|
||||
offsets and has no absolute position. The mouse wheel callback has been
|
||||
replaced by a [scroll callback](@ref GLFWscrollfun) that receives
|
||||
two-dimensional floating point scroll offsets. This allows you to receive
|
||||
precise scroll data from for example modern touchpads.
|
||||
|
||||
@par Old syntax
|
||||
@code
|
||||
void GLFWCALL mouse_wheel_callback(int position);
|
||||
@endcode
|
||||
|
||||
@par New syntax
|
||||
@code
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
@endcode
|
||||
|
||||
@par Removed functions
|
||||
`glfwGetMouseWheel`
|
||||
|
||||
|
||||
@subsection moving_repeat Key repeat action
|
||||
|
||||
The `GLFW_KEY_REPEAT` enable has been removed and key repeat is always enabled
|
||||
for both keys and characters. A new key action, `GLFW_REPEAT`, has been added
|
||||
to allow the [key callback](@ref GLFWkeyfun) to distinguish an initial key press
|
||||
from a repeat. Note that @ref glfwGetKey still returns only `GLFW_PRESS` or
|
||||
`GLFW_RELEASE`.
|
||||
|
||||
|
||||
@subsection moving_keys Physical key input
|
||||
|
||||
GLFW 3 key tokens map to physical keys, unlike in GLFW 2 where they mapped to
|
||||
the values generated by the current keyboard layout. The tokens are named
|
||||
according to the values they would have using the standard US layout, but this
|
||||
is only a convenience, as most programmers are assumed to know that layout.
|
||||
This means that (for example) `GLFW_KEY_LEFT_BRACKET` is always a single key and
|
||||
is the same key in the same place regardless of what keyboard layouts the users
|
||||
of your program has.
|
||||
|
||||
The key input facility was never meant for text input, although using it that
|
||||
way worked slightly better in GLFW 2. If you were using it to input text, you
|
||||
should be using the character callback instead, on both GLFW 2 and 3. This will
|
||||
give you the characters being input, as opposed to the keys being pressed.
|
||||
|
||||
GLFW 3 has key tokens for all keys on a standard 105 key keyboard, so instead of
|
||||
having to remember whether to check for `'a'` or `'A'`, you now check for
|
||||
`GLFW_KEY_A`.
|
||||
|
||||
|
||||
@subsection moving_joystick Joystick function changes
|
||||
|
||||
The `glfwGetJoystickPos` function has been renamed to @ref glfwGetJoystickAxes.
|
||||
|
||||
The `glfwGetJoystickParam` function and the `GLFW_PRESENT`, `GLFW_AXES` and
|
||||
`GLFW_BUTTONS` tokens have been replaced by the @ref glfwJoystickPresent
|
||||
function as well as axis and button counts returned by the @ref
|
||||
glfwGetJoystickAxes and @ref glfwGetJoystickButtons functions.
|
||||
|
||||
|
||||
@subsection moving_mbcs Win32 MBCS support
|
||||
|
||||
The Win32 port of GLFW 3 will not compile in
|
||||
[MBCS mode](http://msdn.microsoft.com/en-us/library/5z097dxa.aspx).
|
||||
However, because the use of the Unicode version of the Win32 API doesn't affect
|
||||
the process as a whole, but only those windows created using it, it's perfectly
|
||||
possible to call MBCS functions from other parts of the same application.
|
||||
Therefore, even if an application using GLFW has MBCS mode code, there's no need
|
||||
for GLFW itself to support it.
|
||||
|
||||
|
||||
@subsection moving_windows Support for versions of Windows older than XP
|
||||
|
||||
All explicit support for version of Windows older than XP has been removed.
|
||||
There is no code that actively prevents GLFW 3 from running on these earlier
|
||||
versions, but it uses Win32 functions that those versions lack.
|
||||
|
||||
Windows XP was released in 2001, and by now (January 2015) it has not only
|
||||
replaced almost all earlier versions of Windows, but is itself rapidly being
|
||||
replaced by Windows 7 and 8. The MSDN library doesn't even provide
|
||||
documentation for version older than Windows 2000, making it difficult to
|
||||
maintain compatibility with these versions even if it was deemed worth the
|
||||
effort.
|
||||
|
||||
The Win32 API has also not stood still, and GLFW 3 uses many functions only
|
||||
present on Windows XP or later. Even supporting an OS as new as XP (new
|
||||
from the perspective of GLFW 2, which still supports Windows 95) requires
|
||||
runtime checking for a number of functions that are present only on modern
|
||||
version of Windows.
|
||||
|
||||
|
||||
@subsection moving_syskeys Capture of system-wide hotkeys
|
||||
|
||||
The ability to disable and capture system-wide hotkeys like Alt+Tab has been
|
||||
removed. Modern applications, whether they're games, scientific visualisations
|
||||
or something else, are nowadays expected to be good desktop citizens and allow
|
||||
these hotkeys to function even when running in full screen mode.
|
||||
|
||||
|
||||
@subsection moving_terminate Automatic termination
|
||||
|
||||
GLFW 3 does not register @ref glfwTerminate with `atexit` at initialization,
|
||||
because `exit` calls registered functions from the calling thread and while it
|
||||
is permitted to call `exit` from any thread, @ref glfwTerminate must only be
|
||||
called from the main thread.
|
||||
|
||||
To release all resources allocated by GLFW, you should call @ref glfwTerminate
|
||||
yourself, from the main thread, before the program terminates. Note that this
|
||||
destroys all windows not already destroyed with @ref glfwDestroyWindow,
|
||||
invalidating any window handles you may still have.
|
||||
|
||||
|
||||
@subsection moving_glu GLU header inclusion
|
||||
|
||||
GLFW 3 does not by default include the GLU header and GLU itself has been
|
||||
deprecated by [Khronos](https://en.wikipedia.org/wiki/Khronos_Group). __New
|
||||
projects should not use GLU__, but if you need it for legacy code that
|
||||
has been moved to GLFW 3, you can request that the GLFW header includes it by
|
||||
defining @ref GLFW_INCLUDE_GLU before the inclusion of the GLFW header.
|
||||
|
||||
@par Old syntax
|
||||
@code
|
||||
#include <GL/glfw.h>
|
||||
@endcode
|
||||
|
||||
@par New syntax
|
||||
@code
|
||||
#define GLFW_INCLUDE_GLU
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
There are many libraries that offer replacements for the functionality offered
|
||||
by GLU. For the matrix helper functions, see math libraries like
|
||||
[GLM](https://github.com/g-truc/glm) (for C++),
|
||||
[linmath.h](https://github.com/datenwolf/linmath.h) (for C) and others. For the
|
||||
tessellation functions, see for example
|
||||
[libtess2](https://github.com/memononen/libtess2).
|
||||
|
||||
|
||||
@section moving_tables Name change tables
|
||||
|
||||
|
||||
@subsection moving_renamed_functions Renamed functions
|
||||
|
||||
| GLFW 2 | GLFW 3 | Notes |
|
||||
| --------------------------- | ----------------------------- | ----- |
|
||||
| `glfwOpenWindow` | @ref glfwCreateWindow | All channel bit depths are now hints
|
||||
| `glfwCloseWindow` | @ref glfwDestroyWindow | |
|
||||
| `glfwOpenWindowHint` | @ref glfwWindowHint | Now accepts all `GLFW_*_BITS` tokens |
|
||||
| `glfwEnable` | @ref glfwSetInputMode | |
|
||||
| `glfwDisable` | @ref glfwSetInputMode | |
|
||||
| `glfwGetMousePos` | @ref glfwGetCursorPos | |
|
||||
| `glfwSetMousePos` | @ref glfwSetCursorPos | |
|
||||
| `glfwSetMousePosCallback` | @ref glfwSetCursorPosCallback | |
|
||||
| `glfwSetMouseWheelCallback` | @ref glfwSetScrollCallback | Accepts two-dimensional scroll offsets as doubles |
|
||||
| `glfwGetJoystickPos` | @ref glfwGetJoystickAxes | |
|
||||
| `glfwGetWindowParam` | @ref glfwGetWindowAttrib | |
|
||||
| `glfwGetGLVersion` | @ref glfwGetWindowAttrib | Use `GLFW_CONTEXT_VERSION_MAJOR`, `GLFW_CONTEXT_VERSION_MINOR` and `GLFW_CONTEXT_REVISION` |
|
||||
| `glfwGetDesktopMode` | @ref glfwGetVideoMode | Returns the current mode of a monitor |
|
||||
| `glfwGetJoystickParam` | @ref glfwJoystickPresent | The axis and button counts are provided by @ref glfwGetJoystickAxes and @ref glfwGetJoystickButtons |
|
||||
|
||||
|
||||
@subsection moving_renamed_types Renamed types
|
||||
|
||||
| GLFW 2 | GLFW 3 | Notes |
|
||||
| ------------------- | --------------------- | |
|
||||
| `GLFWmousewheelfun` | @ref GLFWscrollfun | |
|
||||
| `GLFWmouseposfun` | @ref GLFWcursorposfun | |
|
||||
|
||||
|
||||
@subsection moving_renamed_tokens Renamed tokens
|
||||
|
||||
| GLFW 2 | GLFW 3 | Notes |
|
||||
| --------------------------- | ---------------------------- | ----- |
|
||||
| `GLFW_OPENGL_VERSION_MAJOR` | `GLFW_CONTEXT_VERSION_MAJOR` | Renamed as it applies to OpenGL ES as well |
|
||||
| `GLFW_OPENGL_VERSION_MINOR` | `GLFW_CONTEXT_VERSION_MINOR` | Renamed as it applies to OpenGL ES as well |
|
||||
| `GLFW_FSAA_SAMPLES` | `GLFW_SAMPLES` | Renamed to match the OpenGL API |
|
||||
| `GLFW_ACTIVE` | `GLFW_FOCUSED` | Renamed to match the window focus callback |
|
||||
| `GLFW_WINDOW_NO_RESIZE` | `GLFW_RESIZABLE` | The default has been inverted |
|
||||
| `GLFW_MOUSE_CURSOR` | `GLFW_CURSOR` | Used with @ref glfwSetInputMode |
|
||||
| `GLFW_KEY_ESC` | `GLFW_KEY_ESCAPE` | |
|
||||
| `GLFW_KEY_DEL` | `GLFW_KEY_DELETE` | |
|
||||
| `GLFW_KEY_PAGEUP` | `GLFW_KEY_PAGE_UP` | |
|
||||
| `GLFW_KEY_PAGEDOWN` | `GLFW_KEY_PAGE_DOWN` | |
|
||||
| `GLFW_KEY_KP_NUM_LOCK` | `GLFW_KEY_NUM_LOCK` | |
|
||||
| `GLFW_KEY_LCTRL` | `GLFW_KEY_LEFT_CONTROL` | |
|
||||
| `GLFW_KEY_LSHIFT` | `GLFW_KEY_LEFT_SHIFT` | |
|
||||
| `GLFW_KEY_LALT` | `GLFW_KEY_LEFT_ALT` | |
|
||||
| `GLFW_KEY_LSUPER` | `GLFW_KEY_LEFT_SUPER` | |
|
||||
| `GLFW_KEY_RCTRL` | `GLFW_KEY_RIGHT_CONTROL` | |
|
||||
| `GLFW_KEY_RSHIFT` | `GLFW_KEY_RIGHT_SHIFT` | |
|
||||
| `GLFW_KEY_RALT` | `GLFW_KEY_RIGHT_ALT` | |
|
||||
| `GLFW_KEY_RSUPER` | `GLFW_KEY_RIGHT_SUPER` | |
|
||||
|
||||
*/
|
|
@ -0,0 +1,456 @@
|
|||
/*!
|
||||
|
||||
@page news New features
|
||||
|
||||
@section news_33 New features in 3.3
|
||||
|
||||
|
||||
@subsection news_33_geterror Error query
|
||||
|
||||
GLFW now supports querying the last error code for the calling thread with @ref
|
||||
glfwGetError.
|
||||
|
||||
@see @ref error_handling
|
||||
|
||||
|
||||
@subsection news_33_maximize Window maximization callback
|
||||
|
||||
GLFW now supports window maximization notifications with @ref
|
||||
glfwSetWindowMaximizeCallback.
|
||||
|
||||
|
||||
@subsection news_33_keyscancode Platform-specific key scancode query
|
||||
|
||||
GLFW now supports querying the platform dependent scancode of any key with
|
||||
@ref glfwGetKeyScancode.
|
||||
|
||||
|
||||
@subsection news_33_setwindowattrib Support for updating window attributes
|
||||
|
||||
GLFW now supports changing the [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
|
||||
[GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib),
|
||||
[GLFW_FLOATING](@ref GLFW_FLOATING_attrib) and
|
||||
[GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) attributes for existing
|
||||
windows with @ref glfwSetWindowAttrib.
|
||||
|
||||
|
||||
@subsection news_33_joyhats Support for joystick hats
|
||||
|
||||
GLFW now supports querying the hats of a joystick with @ref glfwGetJoystickHats
|
||||
and controlling whether hats are also exposed as buttons with the @ref
|
||||
GLFW_JOYSTICK_HAT_BUTTONS init hint.
|
||||
|
||||
|
||||
@subsection news_33_inithint Support for initialization hints
|
||||
|
||||
GLFW now supports setting library initialization hints with @ref glfwInitHint.
|
||||
Currently the macOS specific @ref
|
||||
GLFW_COCOA_CHDIR_RESOURCES and @ref GLFW_COCOA_MENUBAR init hints are supported,
|
||||
replacing the corresponding compile-time options.
|
||||
|
||||
|
||||
@subsection news_33_centercursor Cursor centering window hint
|
||||
|
||||
GLFW now supports controlling whether the cursor is centered over newly created
|
||||
full screen windows with the [GLFW_CENTER_CURSOR](@ref GLFW_CENTER_CURSOR_hint)
|
||||
window hint.
|
||||
|
||||
|
||||
@subsection news_33_rawmotion Support for raw mouse motion
|
||||
|
||||
GLFW now supports raw mouse motion in disabled cursor mode on platforms where
|
||||
this is available.
|
||||
|
||||
|
||||
@subsection news_33_moltenvk Support for Vulkan on macOS via MoltenVK
|
||||
|
||||
GLFW now supports the `VK_MVK_macos_surface` window surface creation extension
|
||||
provided by [MoltenVK](https://moltengl.com/moltenvk/).
|
||||
|
||||
|
||||
@subsection news_33_osmesa OSMesa backend for headless software rendering
|
||||
|
||||
GLFW now supports creating offscreen OpenGL contexts using
|
||||
[OSMesa](https://www.mesa3d.org/osmesa.html) by setting
|
||||
[GLFW_CONTEXT_CREATION_API](@ref GLFW_CONTEXT_CREATION_API_hint) to
|
||||
`GLFW_OSMESA_CONTEXT_API`.
|
||||
|
||||
There is also a new headless backend that uses OSMesa as its native context
|
||||
creation API, intended for automated testing. This backend does not provide
|
||||
input.
|
||||
|
||||
|
||||
@section news_32 New features in 3.2
|
||||
|
||||
|
||||
@subsection news_32_vulkan Support for Vulkan
|
||||
|
||||
GLFW now supports basic integration with Vulkan with @ref glfwVulkanSupported,
|
||||
@ref glfwGetRequiredInstanceExtensions, @ref glfwGetInstanceProcAddress, @ref
|
||||
glfwGetPhysicalDevicePresentationSupport and @ref glfwCreateWindowSurface.
|
||||
Vulkan header inclusion can be selected with
|
||||
@ref GLFW_INCLUDE_VULKAN.
|
||||
|
||||
|
||||
@subsection news_32_setwindowmonitor Window mode switching
|
||||
|
||||
GLFW now supports switching between windowed and full screen modes and updating
|
||||
the monitor and desired resolution and refresh rate of full screen windows with
|
||||
@ref glfwSetWindowMonitor.
|
||||
|
||||
|
||||
@subsection news_32_maximize Window maxmimization support
|
||||
|
||||
GLFW now supports window maximization with @ref glfwMaximizeWindow and the
|
||||
@ref GLFW_MAXIMIZED window hint and attribute.
|
||||
|
||||
|
||||
@subsection news_32_focus Window input focus control
|
||||
|
||||
GLFW now supports giving windows input focus with @ref glfwFocusWindow.
|
||||
|
||||
|
||||
@subsection news_32_sizelimits Window size limit support
|
||||
|
||||
GLFW now supports setting both absolute and relative window size limits with
|
||||
@ref glfwSetWindowSizeLimits and @ref glfwSetWindowAspectRatio.
|
||||
|
||||
|
||||
@subsection news_32_keyname Localized key names
|
||||
|
||||
GLFW now supports querying the localized name of printable keys with @ref
|
||||
glfwGetKeyName, either by key token or by scancode.
|
||||
|
||||
|
||||
@subsection news_32_waittimeout Wait for events with timeout
|
||||
|
||||
GLFW now supports waiting for events for a set amount of time with @ref
|
||||
glfwWaitEventsTimeout.
|
||||
|
||||
|
||||
@subsection news_32_icon Window icon support
|
||||
|
||||
GLFW now supports setting the icon of windows with @ref glfwSetWindowIcon.
|
||||
|
||||
|
||||
@subsection news_32_timer Raw timer access
|
||||
|
||||
GLFW now supports raw timer values with @ref glfwGetTimerValue and @ref
|
||||
glfwGetTimerFrequency.
|
||||
|
||||
|
||||
@subsection news_32_joystick Joystick connection callback
|
||||
|
||||
GLFW now supports notifying when a joystick has been connected or disconnected
|
||||
with @ref glfwSetJoystickCallback.
|
||||
|
||||
|
||||
@subsection news_32_noapi Context-less windows
|
||||
|
||||
GLFW now supports creating windows without a OpenGL or OpenGL ES context by
|
||||
setting the [GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint to `GLFW_NO_API`.
|
||||
|
||||
|
||||
@subsection news_32_contextapi Run-time context creation API selection
|
||||
|
||||
GLFW now supports selecting and querying the context creation API at run-time
|
||||
with the @ref GLFW_CONTEXT_CREATION_API hint and attribute.
|
||||
|
||||
|
||||
@subsection news_32_noerror Error-free context creation
|
||||
|
||||
GLFW now supports creating and querying OpenGL and OpenGL ES contexts that do
|
||||
not emit errors with the @ref GLFW_CONTEXT_NO_ERROR hint, provided the machine
|
||||
supports the `GL_KHR_no_error` extension.
|
||||
|
||||
|
||||
@subsection news_32_cmake CMake config-file package support
|
||||
|
||||
GLFW now supports being used as a
|
||||
[config-file package](@ref build_link_cmake_package) from other projects for
|
||||
easy linking with the library and its dependencies.
|
||||
|
||||
|
||||
@section news_31 New features in 3.1
|
||||
|
||||
These are the release highlights. For a full list of changes see the
|
||||
[version history](http://www.glfw.org/changelog.html).
|
||||
|
||||
|
||||
@subsection news_31_cursor Custom mouse cursor images
|
||||
|
||||
GLFW now supports creating and setting both custom cursor images and standard
|
||||
cursor shapes. They are created with @ref glfwCreateCursor or @ref
|
||||
glfwCreateStandardCursor, set with @ref glfwSetCursor and destroyed with @ref
|
||||
glfwDestroyCursor.
|
||||
|
||||
@see @ref cursor_object
|
||||
|
||||
|
||||
@subsection news_31_drop Path drop event
|
||||
|
||||
GLFW now provides a callback for receiving the paths of files and directories
|
||||
dropped onto GLFW windows. The callback is set with @ref glfwSetDropCallback.
|
||||
|
||||
@see @ref path_drop
|
||||
|
||||
|
||||
@subsection news_31_emptyevent Main thread wake-up
|
||||
|
||||
GLFW now provides the @ref glfwPostEmptyEvent function for posting an empty
|
||||
event from another thread to the main thread event queue, causing @ref
|
||||
glfwWaitEvents to return.
|
||||
|
||||
@see @ref events
|
||||
|
||||
|
||||
@subsection news_31_framesize Window frame size query
|
||||
|
||||
GLFW now supports querying the size, on each side, of the frame around the
|
||||
client area of a window, with @ref glfwGetWindowFrameSize.
|
||||
|
||||
@see [Window size](@ref window_size)
|
||||
|
||||
|
||||
@subsection news_31_autoiconify Simultaneous multi-monitor rendering
|
||||
|
||||
GLFW now supports disabling auto-iconification of full screen windows with
|
||||
the [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_hint) window hint. This is
|
||||
intended for people building multi-monitor installations, where you need windows
|
||||
to stay in full screen despite losing input focus.
|
||||
|
||||
|
||||
@subsection news_31_floating Floating windows
|
||||
|
||||
GLFW now supports floating windows, also called topmost or always on top, for
|
||||
easier debugging with the @ref GLFW_FLOATING window hint and attribute.
|
||||
|
||||
|
||||
@subsection news_31_focused Initially unfocused windows
|
||||
|
||||
GLFW now supports preventing a windowed mode window from gaining input focus on
|
||||
creation, with the [GLFW_FOCUSED](@ref GLFW_FOCUSED_hint) window hint.
|
||||
|
||||
|
||||
@subsection news_31_direct Direct access for window attributes and cursor position
|
||||
|
||||
GLFW now queries the window input focus, visibility and iconification attributes
|
||||
and the cursor position directly instead of returning cached data.
|
||||
|
||||
|
||||
@subsection news_31_charmods Character with modifiers callback
|
||||
|
||||
GLFW now provides a callback for character events with modifier key bits. The
|
||||
callback is set with @ref glfwSetCharModsCallback. Unlike the regular character
|
||||
callback, this will report character events that will not result in a character
|
||||
being input, for example if the Control key is held down.
|
||||
|
||||
@see @ref input_char
|
||||
|
||||
|
||||
@subsection news_31_single Single buffered framebuffers
|
||||
|
||||
GLFW now supports the creation of single buffered windows, with the @ref
|
||||
GLFW_DOUBLEBUFFER hint.
|
||||
|
||||
|
||||
@subsection news_31_glext Macro for including extension header
|
||||
|
||||
GLFW now includes the extension header appropriate for the chosen OpenGL or
|
||||
OpenGL ES header when @ref GLFW_INCLUDE_GLEXT is defined. GLFW does not provide
|
||||
these headers. They must be provided by your development environment or your
|
||||
OpenGL or OpenGL ES SDK.
|
||||
|
||||
|
||||
@subsection news_31_release Context release behaviors
|
||||
|
||||
GLFW now supports controlling and querying whether the pipeline is flushed when
|
||||
a context is made non-current, with the @ref GLFW_CONTEXT_RELEASE_BEHAVIOR hint
|
||||
and attribute, provided the machine supports the `GL_KHR_context_flush_control`
|
||||
extension.
|
||||
|
||||
|
||||
@subsection news_31_wayland (Experimental) Wayland support
|
||||
|
||||
GLFW now has an _experimental_ Wayland display protocol backend that can be
|
||||
selected on Linux with a CMake option.
|
||||
|
||||
|
||||
@subsection news_31_mir (Experimental) Mir support
|
||||
|
||||
GLFW now has an _experimental_ Mir display server backend that can be selected
|
||||
on Linux with a CMake option.
|
||||
|
||||
|
||||
@section news_30 New features in 3.0
|
||||
|
||||
These are the release highlights. For a full list of changes see the
|
||||
[version history](http://www.glfw.org/changelog.html).
|
||||
|
||||
|
||||
@subsection news_30_cmake CMake build system
|
||||
|
||||
GLFW now uses the CMake build system instead of the various makefiles and
|
||||
project files used by earlier versions. CMake is available for all platforms
|
||||
supported by GLFW, is present in most package systems and can generate
|
||||
makefiles and/or project files for most popular development environments.
|
||||
|
||||
For more information on how to use CMake, see the
|
||||
[CMake manual](http://cmake.org/cmake/help/documentation.html).
|
||||
|
||||
|
||||
@subsection news_30_multiwnd Multi-window support
|
||||
|
||||
GLFW now supports the creation of multiple windows, each with their own OpenGL
|
||||
or OpenGL ES context, and all window functions now take a window handle. Event
|
||||
callbacks are now per-window and are provided with the handle of the window that
|
||||
received the event. The @ref glfwMakeContextCurrent function has been added to
|
||||
select which context is current on a given thread.
|
||||
|
||||
|
||||
@subsection news_30_multimon Multi-monitor support
|
||||
|
||||
GLFW now explicitly supports multiple monitors. They can be enumerated with
|
||||
@ref glfwGetMonitors, queried with @ref glfwGetVideoModes, @ref
|
||||
glfwGetMonitorPos, @ref glfwGetMonitorName and @ref glfwGetMonitorPhysicalSize,
|
||||
and specified at window creation to make the newly created window full screen on
|
||||
that specific monitor.
|
||||
|
||||
|
||||
@subsection news_30_unicode Unicode support
|
||||
|
||||
All string arguments to GLFW functions and all strings returned by GLFW now use
|
||||
the UTF-8 encoding. This includes the window title, error string, clipboard
|
||||
text, monitor and joystick names as well as the extension function arguments (as
|
||||
ASCII is a subset of UTF-8).
|
||||
|
||||
|
||||
@subsection news_30_clipboard Clipboard text I/O
|
||||
|
||||
GLFW now supports reading and writing plain text to and from the system
|
||||
clipboard, with the @ref glfwGetClipboardString and @ref glfwSetClipboardString
|
||||
functions.
|
||||
|
||||
|
||||
@subsection news_30_gamma Gamma ramp support
|
||||
|
||||
GLFW now supports setting and reading back the gamma ramp of monitors, with the
|
||||
@ref glfwGetGammaRamp and @ref glfwSetGammaRamp functions. There is also @ref
|
||||
glfwSetGamma, which generates a ramp from a gamma value and then sets it.
|
||||
|
||||
|
||||
@subsection news_30_gles OpenGL ES support
|
||||
|
||||
GLFW now supports the creation of OpenGL ES contexts, by setting the
|
||||
[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint to `GLFW_OPENGL_ES_API`, where
|
||||
creation of such contexts are supported. Note that GLFW _does not implement_
|
||||
OpenGL ES, so your driver must provide support in a way usable by GLFW. Modern
|
||||
Nvidia and Intel drivers support creation of OpenGL ES context using the GLX and
|
||||
WGL APIs, while AMD provides an EGL implementation instead.
|
||||
|
||||
|
||||
@subsection news_30_egl (Experimental) EGL support
|
||||
|
||||
GLFW now has an experimental EGL context creation back end that can be selected
|
||||
through CMake options.
|
||||
|
||||
|
||||
@subsection news_30_hidpi High-DPI support
|
||||
|
||||
GLFW now supports high-DPI monitors on both Windows and macOS, giving windows
|
||||
full resolution framebuffers where other UI elements are scaled up. To achieve
|
||||
this, @ref glfwGetFramebufferSize and @ref glfwSetFramebufferSizeCallback have
|
||||
been added. These work with pixels, while the rest of the GLFW API works with
|
||||
screen coordinates. This is important as OpenGL uses pixels, not screen
|
||||
coordinates.
|
||||
|
||||
|
||||
@subsection news_30_error Error callback
|
||||
|
||||
GLFW now has an error callback, which can provide your application with much
|
||||
more detailed diagnostics than was previously possible. The callback is passed
|
||||
an error code and a description string.
|
||||
|
||||
|
||||
@subsection news_30_wndptr Per-window user pointer
|
||||
|
||||
Each window now has a user-defined pointer, retrieved with @ref
|
||||
glfwGetWindowUserPointer and set with @ref glfwSetWindowUserPointer, to make it
|
||||
easier to integrate GLFW into C++ code.
|
||||
|
||||
|
||||
@subsection news_30_iconifyfun Window iconification callback
|
||||
|
||||
Each window now has a callback for iconification and restoration events,
|
||||
which is set with @ref glfwSetWindowIconifyCallback.
|
||||
|
||||
|
||||
@subsection news_30_wndposfun Window position callback
|
||||
|
||||
Each window now has a callback for position events, which is set with @ref
|
||||
glfwSetWindowPosCallback.
|
||||
|
||||
|
||||
@subsection news_30_wndpos Window position query
|
||||
|
||||
The position of a window can now be retrieved using @ref glfwGetWindowPos.
|
||||
|
||||
|
||||
@subsection news_30_focusfun Window focus callback
|
||||
|
||||
Each windows now has a callback for focus events, which is set with @ref
|
||||
glfwSetWindowFocusCallback.
|
||||
|
||||
|
||||
@subsection news_30_enterleave Cursor enter/leave callback
|
||||
|
||||
Each window now has a callback for when the mouse cursor enters or leaves its
|
||||
client area, which is set with @ref glfwSetCursorEnterCallback.
|
||||
|
||||
|
||||
@subsection news_30_wndtitle Initial window title
|
||||
|
||||
The title of a window is now specified at creation time, as one of the arguments
|
||||
to @ref glfwCreateWindow.
|
||||
|
||||
|
||||
@subsection news_30_hidden Hidden windows
|
||||
|
||||
Windows can now be hidden with @ref glfwHideWindow, shown using @ref
|
||||
glfwShowWindow and created initially hidden with the @ref GLFW_VISIBLE window
|
||||
hint and attribute. This allows for off-screen rendering in a way compatible
|
||||
with most drivers, as well as moving a window to a specific position before
|
||||
showing it.
|
||||
|
||||
|
||||
@subsection news_30_undecorated Undecorated windows
|
||||
|
||||
Windowed mode windows can now be created without decorations, e.g. things like
|
||||
a frame, a title bar, with the @ref GLFW_DECORATED window hint and attribute.
|
||||
This allows for the creation of things like splash screens.
|
||||
|
||||
|
||||
@subsection news_30_keymods Modifier key bit masks
|
||||
|
||||
[Modifier key bit mask](@ref mods) parameters have been added to the
|
||||
[mouse button](@ref GLFWmousebuttonfun) and [key](@ref GLFWkeyfun) callbacks.
|
||||
|
||||
|
||||
@subsection news_30_scancode Platform-specific scancodes
|
||||
|
||||
A scancode parameter has been added to the [key callback](@ref GLFWkeyfun). Keys
|
||||
that don't have a [key token](@ref keys) still get passed on with the key
|
||||
parameter set to `GLFW_KEY_UNKNOWN`. These scancodes will vary between machines
|
||||
and are intended to be used for key bindings.
|
||||
|
||||
|
||||
@subsection news_30_jsname Joystick names
|
||||
|
||||
The name of a joystick can now be retrieved using @ref glfwGetJoystickName.
|
||||
|
||||
|
||||
@subsection news_30_doxygen Doxygen documentation
|
||||
|
||||
You are reading it.
|
||||
|
||||
*/
|
|
@ -0,0 +1,364 @@
|
|||
/*!
|
||||
|
||||
@page quick_guide Getting started
|
||||
|
||||
@tableofcontents
|
||||
|
||||
This guide takes you through writing a simple application using GLFW 3. The
|
||||
application will create a window and OpenGL context, render a rotating triangle
|
||||
and exit when the user closes the window or presses _Escape_. This guide will
|
||||
introduce a few of the most commonly used functions, but there are many more.
|
||||
|
||||
This guide assumes no experience with earlier versions of GLFW. If you
|
||||
have used GLFW 2 in the past, read @ref moving_guide, as some functions
|
||||
behave differently in GLFW 3.
|
||||
|
||||
|
||||
@section quick_steps Step by step
|
||||
|
||||
@subsection quick_include Including the GLFW header
|
||||
|
||||
In the source files of your application where you use OpenGL or GLFW, you need
|
||||
to include the GLFW 3 header file.
|
||||
|
||||
@code
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
This defines all the constants, types and function prototypes of the GLFW API.
|
||||
It also includes the OpenGL header from your development environment and
|
||||
defines all the constants and types necessary for it to work on your platform
|
||||
without including any platform-specific headers.
|
||||
|
||||
In other words:
|
||||
|
||||
- Do _not_ include the OpenGL header yourself, as GLFW does this for you in
|
||||
a platform-independent way
|
||||
- Do _not_ include `windows.h` or other platform-specific headers unless
|
||||
you plan on using those APIs yourself
|
||||
- If you _do_ need to include such headers, include them _before_ the GLFW
|
||||
header and it will detect this
|
||||
|
||||
On some platforms supported by GLFW the OpenGL header and link library only
|
||||
expose older versions of OpenGL. The most extreme case is Windows, which only
|
||||
exposes OpenGL 1.2. The easiest way to work around this is to use an
|
||||
[extension loader library](@ref context_glext_auto).
|
||||
|
||||
If you are using such a library then you should include its header _before_ the
|
||||
GLFW header. This lets it replace the OpenGL header included by GLFW without
|
||||
conflicts. This example uses
|
||||
[glad](https://github.com/Dav1dde/glad), but the same rule applies to all such
|
||||
libraries.
|
||||
|
||||
@code
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection quick_init_term Initializing and terminating GLFW
|
||||
|
||||
Before you can use most GLFW functions, the library must be initialized. On
|
||||
successful initialization, `GLFW_TRUE` is returned. If an error occurred,
|
||||
`GLFW_FALSE` is returned.
|
||||
|
||||
@code
|
||||
if (!glfwInit())
|
||||
{
|
||||
// Initialization failed
|
||||
}
|
||||
@endcode
|
||||
|
||||
Note that `GLFW_TRUE` and `GLFW_FALSE` are and will always be just one and zero.
|
||||
|
||||
When you are done using GLFW, typically just before the application exits, you
|
||||
need to terminate GLFW.
|
||||
|
||||
@code
|
||||
glfwTerminate();
|
||||
@endcode
|
||||
|
||||
This destroys any remaining windows and releases any other resources allocated by
|
||||
GLFW. After this call, you must initialize GLFW again before using any GLFW
|
||||
functions that require it.
|
||||
|
||||
|
||||
@subsection quick_capture_error Setting an error callback
|
||||
|
||||
Most events are reported through callbacks, whether it's a key being pressed,
|
||||
a GLFW window being moved, or an error occurring. Callbacks are simply
|
||||
C functions (or C++ static methods) that are called by GLFW with arguments
|
||||
describing the event.
|
||||
|
||||
In case a GLFW function fails, an error is reported to the GLFW error callback.
|
||||
You can receive these reports with an error callback. This function must have
|
||||
the signature below. This simple error callback just prints the error
|
||||
description to `stderr`.
|
||||
|
||||
@code
|
||||
void error_callback(int error, const char* description)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", description);
|
||||
}
|
||||
@endcode
|
||||
|
||||
Callback functions must be set, so GLFW knows to call them. The function to set
|
||||
the error callback is one of the few GLFW functions that may be called before
|
||||
initialization, which lets you be notified of errors both during and after
|
||||
initialization.
|
||||
|
||||
@code
|
||||
glfwSetErrorCallback(error_callback);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection quick_create_window Creating a window and context
|
||||
|
||||
The window and its OpenGL context are created with a single call to @ref
|
||||
glfwCreateWindow, which returns a handle to the created combined window and
|
||||
context object
|
||||
|
||||
@code
|
||||
GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", NULL, NULL);
|
||||
if (!window)
|
||||
{
|
||||
// Window or OpenGL context creation failed
|
||||
}
|
||||
@endcode
|
||||
|
||||
This creates a 640 by 480 windowed mode window with an OpenGL context. If
|
||||
window or OpenGL context creation fails, `NULL` will be returned. You should
|
||||
always check the return value. While window creation rarely fails, context
|
||||
creation depends on properly installed drivers and may fail even on machines
|
||||
with the necessary hardware.
|
||||
|
||||
By default, the OpenGL context GLFW creates may have any version. You can
|
||||
require a minimum OpenGL version by setting the `GLFW_CONTEXT_VERSION_MAJOR` and
|
||||
`GLFW_CONTEXT_VERSION_MINOR` hints _before_ creation. If the required minimum
|
||||
version is not supported on the machine, context (and window) creation fails.
|
||||
|
||||
@code
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", NULL, NULL);
|
||||
if (!window)
|
||||
{
|
||||
// Window or context creation failed
|
||||
}
|
||||
@endcode
|
||||
|
||||
The window handle is passed to all window related functions and is provided to
|
||||
along to all window related callbacks, so they can tell which window received
|
||||
the event.
|
||||
|
||||
When a window and context is no longer needed, destroy it.
|
||||
|
||||
@code
|
||||
glfwDestroyWindow(window);
|
||||
@endcode
|
||||
|
||||
Once this function is called, no more events will be delivered for that window
|
||||
and its handle becomes invalid.
|
||||
|
||||
|
||||
@subsection quick_context_current Making the OpenGL context current
|
||||
|
||||
Before you can use the OpenGL API, you must have a current OpenGL context.
|
||||
|
||||
@code
|
||||
glfwMakeContextCurrent(window);
|
||||
@endcode
|
||||
|
||||
The context will remain current until you make another context current or until
|
||||
the window owning the current context is destroyed.
|
||||
|
||||
If you are using an [extension loader library](@ref context_glext_auto) to
|
||||
access modern OpenGL then this is when to initialize it, as the loader needs
|
||||
a current context to load from. This example uses
|
||||
[glad](https://github.com/Dav1dde/glad), but the same rule applies to all such
|
||||
libraries.
|
||||
|
||||
@code
|
||||
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection quick_window_close Checking the window close flag
|
||||
|
||||
Each window has a flag indicating whether the window should be closed.
|
||||
|
||||
When the user attempts to close the window, either by pressing the close widget
|
||||
in the title bar or using a key combination like Alt+F4, this flag is set to 1.
|
||||
Note that __the window isn't actually closed__, so you are expected to monitor
|
||||
this flag and either destroy the window or give some kind of feedback to the
|
||||
user.
|
||||
|
||||
@code
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Keep running
|
||||
}
|
||||
@endcode
|
||||
|
||||
You can be notified when the user is attempting to close the window by setting
|
||||
a close callback with @ref glfwSetWindowCloseCallback. The callback will be
|
||||
called immediately after the close flag has been set.
|
||||
|
||||
You can also set it yourself with @ref glfwSetWindowShouldClose. This can be
|
||||
useful if you want to interpret other kinds of input as closing the window, like
|
||||
for example pressing the _Escape_ key.
|
||||
|
||||
|
||||
@subsection quick_key_input Receiving input events
|
||||
|
||||
Each window has a large number of callbacks that can be set to receive all the
|
||||
various kinds of events. To receive key press and release events, create a key
|
||||
callback function.
|
||||
|
||||
@code
|
||||
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
{
|
||||
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||
}
|
||||
@endcode
|
||||
|
||||
The key callback, like other window related callbacks, are set per-window.
|
||||
|
||||
@code
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
@endcode
|
||||
|
||||
In order for event callbacks to be called when events occur, you need to process
|
||||
events as described below.
|
||||
|
||||
|
||||
@subsection quick_render Rendering with OpenGL
|
||||
|
||||
Once you have a current OpenGL context, you can use OpenGL normally. In this
|
||||
tutorial, a multi-colored rotating triangle will be rendered. The framebuffer
|
||||
size needs to be retrieved for `glViewport`.
|
||||
|
||||
@code
|
||||
int width, height;
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
glViewport(0, 0, width, height);
|
||||
@endcode
|
||||
|
||||
You can also set a framebuffer size callback using @ref
|
||||
glfwSetFramebufferSizeCallback and be notified when the size changes.
|
||||
|
||||
Actual rendering with OpenGL is outside the scope of this tutorial, but there
|
||||
are [many](https://open.gl/) [excellent](http://learnopengl.com/)
|
||||
[tutorial](http://openglbook.com/) [sites](http://ogldev.atspace.co.uk/) that
|
||||
teach modern OpenGL. Some of them use GLFW to create the context and window
|
||||
while others use GLUT or SDL, but remember that OpenGL itself always works the
|
||||
same.
|
||||
|
||||
|
||||
@subsection quick_timer Reading the timer
|
||||
|
||||
To create smooth animation, a time source is needed. GLFW provides a timer that
|
||||
returns the number of seconds since initialization. The time source used is the
|
||||
most accurate on each platform and generally has micro- or nanosecond
|
||||
resolution.
|
||||
|
||||
@code
|
||||
double time = glfwGetTime();
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection quick_swap_buffers Swapping buffers
|
||||
|
||||
GLFW windows by default use double buffering. That means that each window has
|
||||
two rendering buffers; a front buffer and a back buffer. The front buffer is
|
||||
the one being displayed and the back buffer the one you render to.
|
||||
|
||||
When the entire frame has been rendered, the buffers need to be swapped with one
|
||||
another, so the back buffer becomes the front buffer and vice versa.
|
||||
|
||||
@code
|
||||
glfwSwapBuffers(window);
|
||||
@endcode
|
||||
|
||||
The swap interval indicates how many frames to wait until swapping the buffers,
|
||||
commonly known as _vsync_. By default, the swap interval is zero, meaning
|
||||
buffer swapping will occur immediately. On fast machines, many of those frames
|
||||
will never be seen, as the screen is still only updated typically 60-75 times
|
||||
per second, so this wastes a lot of CPU and GPU cycles.
|
||||
|
||||
Also, because the buffers will be swapped in the middle the screen update,
|
||||
leading to [screen tearing](https://en.wikipedia.org/wiki/Screen_tearing).
|
||||
|
||||
For these reasons, applications will typically want to set the swap interval to
|
||||
one. It can be set to higher values, but this is usually not recommended,
|
||||
because of the input latency it leads to.
|
||||
|
||||
@code
|
||||
glfwSwapInterval(1);
|
||||
@endcode
|
||||
|
||||
This function acts on the current context and will fail unless a context is
|
||||
current.
|
||||
|
||||
|
||||
@subsection quick_process_events Processing events
|
||||
|
||||
GLFW needs to communicate regularly with the window system both in order to
|
||||
receive events and to show that the application hasn't locked up. Event
|
||||
processing must be done regularly while you have visible windows and is normally
|
||||
done each frame after buffer swapping.
|
||||
|
||||
There are two methods for processing pending events; polling and waiting. This
|
||||
example will use event polling, which processes only those events that have
|
||||
already been received and then returns immediately.
|
||||
|
||||
@code
|
||||
glfwPollEvents();
|
||||
@endcode
|
||||
|
||||
This is the best choice when rendering continually, like most games do. If
|
||||
instead you only need to update your rendering once you have received new input,
|
||||
@ref glfwWaitEvents is a better choice. It waits until at least one event has
|
||||
been received, putting the thread to sleep in the meantime, and then processes
|
||||
all received events. This saves a great deal of CPU cycles and is useful for,
|
||||
for example, many kinds of editing tools.
|
||||
|
||||
|
||||
@section quick_example Putting it together
|
||||
|
||||
Now that you know how to initialize GLFW, create a window and poll for
|
||||
keyboard input, it's possible to create a simple program.
|
||||
|
||||
This program creates a 640 by 480 windowed mode window and starts a loop that
|
||||
clears the screen, renders a triangle and processes events until the user either
|
||||
presses _Escape_ or closes the window.
|
||||
|
||||
@snippet simple.c code
|
||||
|
||||
The program above can be found in the
|
||||
[source package](http://www.glfw.org/download.html) as `examples/simple.c`
|
||||
and is compiled along with all other examples when you build GLFW. If you
|
||||
built GLFW from the source package then already have this as `simple.exe` on
|
||||
Windows, `simple` on Linux or `simple.app` on macOS.
|
||||
|
||||
This tutorial used only a few of the many functions GLFW provides. There are
|
||||
guides for each of the areas covered by GLFW. Each guide will introduce all the
|
||||
functions for that category.
|
||||
|
||||
- @ref intro_guide
|
||||
- @ref window_guide
|
||||
- @ref context_guide
|
||||
- @ref monitor_guide
|
||||
- @ref input_guide
|
||||
|
||||
You can access reference documentation for any GLFW function by clicking it and
|
||||
the reference for each function links to related functions and guide sections.
|
||||
|
||||
The tutorial ends here. Once you have written a program that uses GLFW, you
|
||||
will need to compile and link it. How to do that depends on the development
|
||||
environment you are using and is best explained by the documentation for that
|
||||
environment. To learn about the details that are specific to GLFW, see
|
||||
@ref build_guide.
|
||||
|
||||
*/
|
|
@ -0,0 +1,872 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="688.48718"
|
||||
height="327.98221"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="spaces.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path3888"
|
||||
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
transform="scale(1.1) rotate(180) translate(1,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.5611424"
|
||||
inkscape:cx="344.24359"
|
||||
inkscape:cy="163.9911"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="svg2"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1021"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
units="px"
|
||||
showborder="false"
|
||||
inkscape:showpageshadow="false" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-12.627039,-339.86462)">
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#0000ff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:3,3;stroke-dashoffset:0"
|
||||
id="rect2985"
|
||||
width="687.36469"
|
||||
height="326.85971"
|
||||
x="13.188287"
|
||||
y="340.42587"
|
||||
inkscape:export-filename="/home/elmindreda/projects/glfw/glfw/docs/spaces.png"
|
||||
inkscape:export-xdpi="109.89113"
|
||||
inkscape:export-ydpi="109.89113" />
|
||||
<rect
|
||||
style="fill:#f3fff3;fill-opacity:1;stroke:#00b800;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect3757"
|
||||
width="318.05698"
|
||||
height="277.04684"
|
||||
x="38.315689"
|
||||
y="366.05841"
|
||||
inkscape:export-filename="/home/elmindreda/projects/glfw/glfw/docs/spaces.png"
|
||||
inkscape:export-xdpi="109.89113"
|
||||
inkscape:export-ydpi="109.89113" />
|
||||
<rect
|
||||
style="fill:#f3fff3;fill-opacity:1;stroke:#00b800;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect3767"
|
||||
width="319.01456"
|
||||
height="198.09369"
|
||||
x="356.36722"
|
||||
y="366.01291"
|
||||
inkscape:export-filename="/home/elmindreda/projects/glfw/glfw/docs/spaces.png"
|
||||
inkscape:export-xdpi="109.89113"
|
||||
inkscape:export-ydpi="109.89113" />
|
||||
<g
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
id="text3769">
|
||||
<path
|
||||
d="m 365.3732,374.63632 0,2.73926 1.24023,0 c 0.45898,0 0.8138,-0.11881 1.06446,-0.35645 0.25064,-0.23762 0.37597,-0.57616 0.37597,-1.01562 0,-0.43619 -0.12533,-0.77311 -0.37597,-1.01074 -0.25066,-0.23763 -0.60548,-0.35644 -1.06446,-0.35645 l -1.24023,0 m -0.98633,-0.81054 2.22656,0 c 0.81706,0 1.43392,0.18555 1.85059,0.55664 0.41992,0.36784 0.62988,0.9082 0.62988,1.62109 0,0.7194 -0.20996,1.26302 -0.62988,1.63086 -0.41667,0.36784 -1.03353,0.55176 -1.85059,0.55176 l -1.24023,0 0,2.92968 -0.98633,0 0,-7.29003"
|
||||
style="font-size:10px"
|
||||
id="path3281" />
|
||||
<path
|
||||
d="m 373.37613,376.48691 c -0.10092,-0.0586 -0.21159,-0.10091 -0.33203,-0.12696 -0.11719,-0.0293 -0.2474,-0.0439 -0.39063,-0.0439 -0.50781,0 -0.89844,0.16602 -1.17187,0.49805 -0.27019,0.32878 -0.40528,0.80241 -0.40528,1.42089 l 0,2.88086 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.1888,-0.33202 0.43457,-0.57779 0.73731,-0.7373 0.30273,-0.16276 0.67057,-0.24414 1.10351,-0.24414 0.0618,0 0.13021,0.005 0.20508,0.0147 0.0749,0.007 0.15788,0.0179 0.24903,0.0342 l 0.005,0.92285"
|
||||
style="font-size:10px"
|
||||
id="path3283" />
|
||||
<path
|
||||
d="m 374.32828,375.64706 0.89844,0 0,5.46875 -0.89844,0 0,-5.46875 m 0,-2.1289 0.89844,0 0,1.13769 -0.89844,0 0,-1.13769"
|
||||
style="font-size:10px"
|
||||
id="path3285" />
|
||||
<path
|
||||
d="m 381.35953,376.69687 c 0.2246,-0.40364 0.49316,-0.70149 0.80566,-0.89356 0.3125,-0.19205 0.68033,-0.28808 1.10352,-0.28808 0.56965,0 1.0091,0.2002 1.31836,0.60058 0.30923,0.39714 0.46385,0.96355 0.46386,1.69922 l 0,3.30078 -0.90332,0 0,-3.27148 c 0,-0.52408 -0.0928,-0.91308 -0.27832,-1.16699 -0.18555,-0.2539 -0.46875,-0.38086 -0.84961,-0.38086 -0.4655,0 -0.83334,0.15463 -1.10351,0.46387 -0.27019,0.30924 -0.40528,0.73079 -0.40528,1.26464 l 0,3.09082 -0.90332,0 0,-3.27148 c 0,-0.52734 -0.0928,-0.91634 -0.27832,-1.16699 -0.18555,-0.2539 -0.472,-0.38086 -0.85937,-0.38086 -0.45899,0 -0.82357,0.15625 -1.09375,0.46875 -0.27019,0.30925 -0.40528,0.72917 -0.40527,1.25976 l 0,3.09082 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.20507,-0.33528 0.45084,-0.58267 0.7373,-0.74218 0.28646,-0.1595 0.62662,-0.23926 1.02051,-0.23926 0.39713,0 0.73404,0.10092 1.01074,0.30273 0.27994,0.20183 0.48665,0.4948 0.62012,0.87891"
|
||||
style="font-size:10px"
|
||||
id="path3287" />
|
||||
<path
|
||||
d="m 389.33316,378.36679 c -0.72591,0 -1.22884,0.083 -1.50879,0.24902 -0.27995,0.16602 -0.41992,0.44923 -0.41992,0.84961 0,0.31902 0.10416,0.57292 0.3125,0.76172 0.21159,0.18555 0.49804,0.27832 0.85937,0.27832 0.49805,0 0.89681,-0.17578 1.19629,-0.52734 0.30273,-0.35482 0.4541,-0.82519 0.45411,-1.41113 l 0,-0.2002 -0.89356,0 m 1.79199,-0.37109 0,3.12011 -0.89843,0 0,-0.83007 c -0.20509,0.33203 -0.46062,0.5778 -0.76661,0.7373 -0.30599,0.15625 -0.68034,0.23438 -1.12304,0.23438 -0.5599,0 -1.00586,-0.15625 -1.33789,-0.46875 -0.32878,-0.31576 -0.49317,-0.73731 -0.49317,-1.26465 0,-0.61523 0.20508,-1.0791 0.61524,-1.3916 0.41341,-0.3125 1.02864,-0.46875 1.8457,-0.46875 l 1.25977,0 0,-0.0879 c -10e-6,-0.41341 -0.13673,-0.73242 -0.41016,-0.95704 -0.27019,-0.22786 -0.65105,-0.34179 -1.14258,-0.34179 -0.3125,0 -0.61686,0.0374 -0.91309,0.1123 -0.29622,0.0749 -0.58105,0.18718 -0.85449,0.33692 l 0,-0.83008 c 0.32878,-0.12695 0.64779,-0.22135 0.95703,-0.28321 0.30925,-0.0651 0.61035,-0.0977 0.90332,-0.0977 0.79102,0 1.38184,0.20508 1.77247,0.61523 0.39062,0.41016 0.58593,1.03191 0.58593,1.86524"
|
||||
style="font-size:10px"
|
||||
id="path3289" />
|
||||
<path
|
||||
d="m 396.14957,376.48691 c -0.10092,-0.0586 -0.2116,-0.10091 -0.33203,-0.12696 -0.1172,-0.0293 -0.2474,-0.0439 -0.39063,-0.0439 -0.50781,0 -0.89844,0.16602 -1.17187,0.49805 -0.27019,0.32878 -0.40528,0.80241 -0.40528,1.42089 l 0,2.88086 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.1888,-0.33202 0.43457,-0.57779 0.73731,-0.7373 0.30273,-0.16276 0.67057,-0.24414 1.10351,-0.24414 0.0618,0 0.13021,0.005 0.20508,0.0147 0.0749,0.007 0.15787,0.0179 0.24902,0.0342 l 0.005,0.92285"
|
||||
style="font-size:10px"
|
||||
id="path3291" />
|
||||
<path
|
||||
d="m 399.37711,381.62363 c -0.25391,0.65104 -0.50131,1.07584 -0.74219,1.27441 -0.24089,0.19857 -0.56315,0.29785 -0.9668,0.29785 l -0.71777,0 0,-0.75195 0.52734,0 c 0.2474,0 0.43945,-0.0586 0.57617,-0.17578 0.13672,-0.11719 0.28809,-0.39388 0.45411,-0.83008 l 0.16113,-0.41016 -2.21192,-5.38086 0.95215,0 1.70899,4.27735 1.70898,-4.27735 0.95215,0 -2.40234,5.97657"
|
||||
style="font-size:10px"
|
||||
id="path3293" />
|
||||
<path
|
||||
d="m 410.46109,376.69687 c 0.2246,-0.40364 0.49316,-0.70149 0.80566,-0.89356 0.3125,-0.19205 0.68034,-0.28808 1.10352,-0.28808 0.56965,0 1.00911,0.2002 1.31836,0.60058 0.30924,0.39714 0.46386,0.96355 0.46387,1.69922 l 0,3.30078 -0.90332,0 0,-3.27148 c -1e-5,-0.52408 -0.0928,-0.91308 -0.27832,-1.16699 -0.18556,-0.2539 -0.46876,-0.38086 -0.84961,-0.38086 -0.4655,0 -0.83334,0.15463 -1.10352,0.46387 -0.27019,0.30924 -0.40528,0.73079 -0.40527,1.26464 l 0,3.09082 -0.90332,0 0,-3.27148 c -10e-6,-0.52734 -0.0928,-0.91634 -0.27832,-1.16699 -0.18555,-0.2539 -0.47201,-0.38086 -0.85938,-0.38086 -0.45899,0 -0.82357,0.15625 -1.09375,0.46875 -0.27018,0.30925 -0.40527,0.72917 -0.40527,1.25976 l 0,3.09082 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.20507,-0.33528 0.45084,-0.58267 0.7373,-0.74218 0.28646,-0.1595 0.62663,-0.23926 1.02051,-0.23926 0.39713,0 0.73405,0.10092 1.01074,0.30273 0.27995,0.20183 0.48665,0.4948 0.62012,0.87891"
|
||||
style="font-size:10px"
|
||||
id="path3295" />
|
||||
<path
|
||||
d="m 418.06851,376.27695 c -0.48177,0 -0.86263,0.1888 -1.14258,0.5664 -0.27995,0.37436 -0.41992,0.88868 -0.41992,1.54297 0,0.6543 0.13835,1.17025 0.41504,1.54785 0.27995,0.37435 0.66243,0.56153 1.14746,0.56153 0.47851,0 0.85775,-0.1888 1.1377,-0.56641 0.27994,-0.3776 0.41991,-0.89192 0.41992,-1.54297 -10e-6,-0.64778 -0.13998,-1.16048 -0.41992,-1.53808 -0.27995,-0.38086 -0.65919,-0.57129 -1.1377,-0.57129 m 0,-0.76172 c 0.78125,0 1.39485,0.25391 1.84082,0.76172 0.44596,0.50781 0.66894,1.21094 0.66895,2.10937 -1e-5,0.89519 -0.22299,1.59831 -0.66895,2.10938 -0.44597,0.50781 -1.05957,0.76172 -1.84082,0.76172 -0.78451,0 -1.39974,-0.25391 -1.8457,-0.76172 -0.44271,-0.51107 -0.66406,-1.21419 -0.66406,-2.10938 0,-0.89843 0.22135,-1.60156 0.66406,-2.10937 0.44596,-0.50781 1.06119,-0.76172 1.8457,-0.76172"
|
||||
style="font-size:10px"
|
||||
id="path3297" />
|
||||
<path
|
||||
d="m 426.60855,377.81503 0,3.30078 -0.89844,0 0,-3.27148 c 0,-0.51757 -0.10091,-0.90494 -0.30273,-1.16211 -0.20183,-0.25716 -0.50456,-0.38574 -0.9082,-0.38574 -0.48503,0 -0.86752,0.15463 -1.14746,0.46387 -0.27995,0.30924 -0.41993,0.73079 -0.41993,1.26464 l 0,3.09082 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.21484,-0.32877 0.46712,-0.57454 0.75684,-0.7373 0.29297,-0.16276 0.62988,-0.24414 1.01074,-0.24414 0.62825,0 1.10351,0.19532 1.42578,0.58594 0.32226,0.38737 0.4834,0.95866 0.4834,1.71386"
|
||||
style="font-size:10px"
|
||||
id="path3299" />
|
||||
<path
|
||||
d="m 428.41031,375.64706 0.89844,0 0,5.46875 -0.89844,0 0,-5.46875 m 0,-2.1289 0.89844,0 0,1.13769 -0.89844,0 0,-1.13769"
|
||||
style="font-size:10px"
|
||||
id="path3301" />
|
||||
<path
|
||||
d="m 432.07242,374.09433 0,1.55273 1.85058,0 0,0.69825 -1.85058,0 0,2.96875 c 0,0.44596 0.0602,0.73242 0.18066,0.85937 0.1237,0.12696 0.37272,0.19043 0.74707,0.19043 l 0.92285,0 0,0.75195 -0.92285,0 c -0.69336,0 -1.17187,-0.12858 -1.43554,-0.38574 -0.26368,-0.26041 -0.39551,-0.73242 -0.39551,-1.41601 l 0,-2.96875 -0.65918,0 0,-0.69825 0.65918,0 0,-1.55273 0.90332,0"
|
||||
style="font-size:10px"
|
||||
id="path3303" />
|
||||
<path
|
||||
d="m 437.22867,376.27695 c -0.48178,0 -0.86263,0.1888 -1.14258,0.5664 -0.27995,0.37436 -0.41992,0.88868 -0.41992,1.54297 0,0.6543 0.13834,1.17025 0.41504,1.54785 0.27994,0.37435 0.66243,0.56153 1.14746,0.56153 0.47851,0 0.85774,-0.1888 1.13769,-0.56641 0.27995,-0.3776 0.41992,-0.89192 0.41993,-1.54297 -1e-5,-0.64778 -0.13998,-1.16048 -0.41993,-1.53808 -0.27995,-0.38086 -0.65918,-0.57129 -1.13769,-0.57129 m 0,-0.76172 c 0.78124,0 1.39485,0.25391 1.84082,0.76172 0.44596,0.50781 0.66894,1.21094 0.66894,2.10937 0,0.89519 -0.22298,1.59831 -0.66894,2.10938 -0.44597,0.50781 -1.05958,0.76172 -1.84082,0.76172 -0.78451,0 -1.39974,-0.25391 -1.8457,-0.76172 -0.44271,-0.51107 -0.66407,-1.21419 -0.66407,-2.10938 0,-0.89843 0.22136,-1.60156 0.66407,-2.10937 0.44596,-0.50781 1.06119,-0.76172 1.8457,-0.76172"
|
||||
style="font-size:10px"
|
||||
id="path3305" />
|
||||
<path
|
||||
d="m 444.39175,376.48691 c -0.10091,-0.0586 -0.21159,-0.10091 -0.33203,-0.12696 -0.11719,-0.0293 -0.2474,-0.0439 -0.39062,-0.0439 -0.50782,0 -0.89844,0.16602 -1.17188,0.49805 -0.27018,0.32878 -0.40527,0.80241 -0.40527,1.42089 l 0,2.88086 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.1888,-0.33202 0.43457,-0.57779 0.7373,-0.7373 0.30274,-0.16276 0.67057,-0.24414 1.10352,-0.24414 0.0618,0 0.1302,0.005 0.20508,0.0147 0.0749,0.007 0.15787,0.0179 0.24902,0.0342 l 0.005,0.92285"
|
||||
style="font-size:10px"
|
||||
id="path3307" />
|
||||
<path
|
||||
d="m 449.39664,380.2955 0,2.90039 -0.90332,0 0,-7.54883 0.90332,0 0,0.83008 c 0.1888,-0.32551 0.42643,-0.5664 0.71289,-0.72265 0.28971,-0.1595 0.63476,-0.23926 1.03515,-0.23926 0.66406,0 1.2028,0.26368 1.61621,0.79101 0.41667,0.52735 0.625,1.22071 0.625,2.08008 0,0.85938 -0.20833,1.55274 -0.625,2.08008 -0.41341,0.52734 -0.95215,0.79102 -1.61621,0.79102 -0.40039,0 -0.74544,-0.0781 -1.03515,-0.23438 -0.28646,-0.1595 -0.52409,-0.40202 -0.71289,-0.72754 m 3.05664,-1.90918 c -1e-5,-0.6608 -0.13673,-1.17838 -0.41016,-1.55273 -0.27019,-0.3776 -0.64291,-0.5664 -1.11816,-0.56641 -0.47527,1e-5 -0.84961,0.18881 -1.12305,0.56641 -0.27018,0.37435 -0.40527,0.89193 -0.40527,1.55273 0,0.66081 0.13509,1.18002 0.40527,1.55762 0.27344,0.37435 0.64778,0.56152 1.12305,0.56152 0.47525,0 0.84797,-0.18717 1.11816,-0.56152 0.27343,-0.3776 0.41015,-0.89681 0.41016,-1.55762"
|
||||
style="font-size:10px"
|
||||
id="path3309" />
|
||||
<path
|
||||
d="m 456.99429,376.27695 c -0.48177,0 -0.86263,0.1888 -1.14257,0.5664 -0.27995,0.37436 -0.41993,0.88868 -0.41993,1.54297 0,0.6543 0.13835,1.17025 0.41504,1.54785 0.27995,0.37435 0.66243,0.56153 1.14746,0.56153 0.47852,0 0.85775,-0.1888 1.1377,-0.56641 0.27994,-0.3776 0.41992,-0.89192 0.41992,-1.54297 0,-0.64778 -0.13998,-1.16048 -0.41992,-1.53808 -0.27995,-0.38086 -0.65918,-0.57129 -1.1377,-0.57129 m 0,-0.76172 c 0.78125,0 1.39486,0.25391 1.84082,0.76172 0.44596,0.50781 0.66894,1.21094 0.66895,2.10937 -10e-6,0.89519 -0.22299,1.59831 -0.66895,2.10938 -0.44596,0.50781 -1.05957,0.76172 -1.84082,0.76172 -0.7845,0 -1.39974,-0.25391 -1.8457,-0.76172 -0.44271,-0.51107 -0.66406,-1.21419 -0.66406,-2.10938 0,-0.89843 0.22135,-1.60156 0.66406,-2.10937 0.44596,-0.50781 1.0612,-0.76172 1.8457,-0.76172"
|
||||
style="font-size:10px"
|
||||
id="path3311" />
|
||||
<path
|
||||
d="m 464.47476,375.8082 0,0.84961 c -0.25391,-0.13021 -0.51758,-0.22786 -0.79101,-0.29297 -0.27344,-0.0651 -0.55665,-0.0976 -0.84961,-0.0977 -0.44597,1e-5 -0.78126,0.0684 -1.00586,0.20508 -0.22136,0.13672 -0.33204,0.3418 -0.33203,0.61523 -10e-6,0.20834 0.0798,0.37273 0.23925,0.49317 0.15951,0.11719 0.48015,0.22949 0.96192,0.33691 l 0.30762,0.0684 c 0.63801,0.13672 1.09049,0.33041 1.35742,0.58106 0.27017,0.24739 0.40527,0.59407 0.40527,1.04004 0,0.50781 -0.20183,0.90983 -0.60547,1.20605 -0.40039,0.29622 -0.95215,0.44434 -1.65527,0.44434 -0.29297,0 -0.59896,-0.0293 -0.91797,-0.0879 -0.31576,-0.0553 -0.64942,-0.13998 -1.00098,-0.25391 l 0,-0.92774 c 0.33203,0.17253 0.65918,0.30274 0.98145,0.39063 0.32226,0.0846 0.64127,0.12695 0.95703,0.12695 0.42317,0 0.74869,-0.0716 0.97656,-0.21484 0.22786,-0.14648 0.3418,-0.35156 0.3418,-0.61524 0,-0.24413 -0.083,-0.43131 -0.24902,-0.56152 -0.16277,-0.13021 -0.52247,-0.25553 -1.07911,-0.37598 l -0.3125,-0.0732 c -0.55664,-0.11718 -0.95866,-0.29622 -1.20605,-0.53711 -0.2474,-0.24413 -0.37109,-0.57779 -0.37109,-1.00097 0,-0.51432 0.18229,-0.91146 0.54687,-1.19141 0.36458,-0.27994 0.88216,-0.41992 1.55274,-0.41992 0.33202,0 0.64452,0.0244 0.9375,0.0732 0.29296,0.0488 0.56314,0.12208 0.81054,0.21973"
|
||||
style="font-size:10px"
|
||||
id="path3313" />
|
||||
<path
|
||||
d="m 466.20328,375.64706 0.89844,0 0,5.46875 -0.89844,0 0,-5.46875 m 0,-2.1289 0.89844,0 0,1.13769 -0.89844,0 0,-1.13769"
|
||||
style="font-size:10px"
|
||||
id="path3315" />
|
||||
<path
|
||||
d="m 469.86539,374.09433 0,1.55273 1.85058,0 0,0.69825 -1.85058,0 0,2.96875 c 0,0.44596 0.0602,0.73242 0.18066,0.85937 0.1237,0.12696 0.37272,0.19043 0.74707,0.19043 l 0.92285,0 0,0.75195 -0.92285,0 c -0.69336,0 -1.17188,-0.12858 -1.43555,-0.38574 -0.26367,-0.26041 -0.3955,-0.73242 -0.3955,-1.41601 l 0,-2.96875 -0.65918,0 0,-0.69825 0.65918,0 0,-1.55273 0.90332,0"
|
||||
style="font-size:10px"
|
||||
id="path3317" />
|
||||
<path
|
||||
d="m 472.9025,375.64706 0.89843,0 0,5.46875 -0.89843,0 0,-5.46875 m 0,-2.1289 0.89843,0 0,1.13769 -0.89843,0 0,-1.13769"
|
||||
style="font-size:10px"
|
||||
id="path3319" />
|
||||
<path
|
||||
d="m 477.79507,376.27695 c -0.48177,0 -0.86263,0.1888 -1.14257,0.5664 -0.27995,0.37436 -0.41993,0.88868 -0.41993,1.54297 0,0.6543 0.13835,1.17025 0.41504,1.54785 0.27995,0.37435 0.66244,0.56153 1.14746,0.56153 0.47852,0 0.85775,-0.1888 1.1377,-0.56641 0.27994,-0.3776 0.41992,-0.89192 0.41992,-1.54297 0,-0.64778 -0.13998,-1.16048 -0.41992,-1.53808 -0.27995,-0.38086 -0.65918,-0.57129 -1.1377,-0.57129 m 0,-0.76172 c 0.78125,0 1.39486,0.25391 1.84082,0.76172 0.44596,0.50781 0.66894,1.21094 0.66895,2.10937 -1e-5,0.89519 -0.22299,1.59831 -0.66895,2.10938 -0.44596,0.50781 -1.05957,0.76172 -1.84082,0.76172 -0.7845,0 -1.39974,-0.25391 -1.8457,-0.76172 -0.44271,-0.51107 -0.66406,-1.21419 -0.66406,-2.10938 0,-0.89843 0.22135,-1.60156 0.66406,-2.10937 0.44596,-0.50781 1.0612,-0.76172 1.8457,-0.76172"
|
||||
style="font-size:10px"
|
||||
id="path3321" />
|
||||
<path
|
||||
d="m 486.33511,377.81503 0,3.30078 -0.89843,0 0,-3.27148 c -1e-5,-0.51757 -0.10092,-0.90494 -0.30274,-1.16211 -0.20183,-0.25716 -0.50456,-0.38574 -0.9082,-0.38574 -0.48503,0 -0.86752,0.15463 -1.14746,0.46387 -0.27995,0.30924 -0.41993,0.73079 -0.41992,1.26464 l 0,3.09082 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.21484,-0.32877 0.46712,-0.57454 0.75683,-0.7373 0.29297,-0.16276 0.62988,-0.24414 1.01074,-0.24414 0.62825,0 1.10351,0.19532 1.42579,0.58594 0.32226,0.38737 0.48339,0.95866 0.48339,1.71386"
|
||||
style="font-size:10px"
|
||||
id="path3323" />
|
||||
</g>
|
||||
<g
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#00b800;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
id="text3773">
|
||||
<path
|
||||
d="m 242.85294,625.22699 0,1.1543 c -0.44923,-0.21484 -0.87306,-0.375 -1.27149,-0.48047 -0.39844,-0.10546 -0.78321,-0.1582 -1.1543,-0.15821 -0.64453,10e-6 -1.14258,0.12501 -1.49414,0.375 -0.34765,0.25001 -0.52148,0.60548 -0.52148,1.06641 0,0.38673 0.11523,0.67969 0.3457,0.87891 0.23438,0.19532 0.67578,0.35352 1.32422,0.47461 l 0.71485,0.14648 c 0.8828,0.16797 1.53319,0.46485 1.95117,0.89063 0.42187,0.42187 0.6328,0.98828 0.63281,1.69921 -1e-5,0.84766 -0.28516,1.49024 -0.85547,1.92774 -0.56641,0.4375 -1.39844,0.65625 -2.49609,0.65625 -0.41407,0 -0.85547,-0.0469 -1.32422,-0.14063 -0.46485,-0.0937 -0.94727,-0.23242 -1.44727,-0.41601 l 0,-1.21875 c 0.48047,0.26953 0.95117,0.47266 1.41211,0.60937 0.46094,0.13672 0.91406,0.20508 1.35938,0.20508 0.67577,0 1.19726,-0.13281 1.56445,-0.39844 0.36718,-0.26562 0.55078,-0.64453 0.55078,-1.13671 0,-0.42969 -0.13282,-0.76563 -0.39844,-1.00782 -0.26172,-0.24218 -0.69336,-0.42382 -1.29492,-0.54492 l -0.7207,-0.14062 c -0.88282,-0.17578 -1.52149,-0.45117 -1.91602,-0.82618 -0.39453,-0.37499 -0.59179,-0.89647 -0.59179,-1.56445 0,-0.77343 0.27148,-1.3828 0.81445,-1.82812 0.54687,-0.44531 1.29882,-0.66796 2.25586,-0.66797 0.41015,10e-6 0.82812,0.0371 1.25391,0.11133 0.42577,0.0742 0.86132,0.18555 1.30664,0.33398"
|
||||
style=""
|
||||
id="path3355" />
|
||||
<path
|
||||
d="m 250.79239,630.13715 0,0.52734 -4.95703,0 c 0.0469,0.74219 0.26953,1.3086 0.66797,1.69922 0.40234,0.38672 0.96093,0.58008 1.67578,0.58008 0.41406,0 0.81445,-0.0508 1.20117,-0.15235 0.39062,-0.10156 0.77734,-0.2539 1.16016,-0.45703 l 0,1.01953 c -0.38673,0.16407 -0.78321,0.28907 -1.18946,0.375 -0.40625,0.0859 -0.81836,0.12891 -1.23633,0.12891 -1.04687,0 -1.87695,-0.30469 -2.49023,-0.91406 -0.60938,-0.60938 -0.91406,-1.43359 -0.91406,-2.47266 0,-1.07421 0.28906,-1.92578 0.86719,-2.55469 0.58202,-0.6328 1.36523,-0.94921 2.3496,-0.94922 0.88281,10e-6 1.58008,0.28517 2.0918,0.85547 0.51562,0.56641 0.77343,1.3379 0.77344,2.31446 m -1.07813,-0.31641 c -0.008,-0.58984 -0.17383,-1.06054 -0.49804,-1.41211 -0.32032,-0.35156 -0.7461,-0.52734 -1.27735,-0.52734 -0.60156,0 -1.08398,0.16992 -1.44726,0.50976 -0.35938,0.33985 -0.56641,0.81837 -0.6211,1.43555 l 3.84375,-0.006"
|
||||
style=""
|
||||
id="path3357" />
|
||||
<path
|
||||
d="m 257.28458,627.37738 0,1.00781 c -0.3047,-0.16796 -0.61134,-0.29296 -0.91993,-0.375 -0.30469,-0.0859 -0.61328,-0.1289 -0.92578,-0.1289 -0.69922,0 -1.24219,0.22266 -1.6289,0.66797 -0.38672,0.44141 -0.58008,1.0625 -0.58008,1.86328 0,0.80078 0.19336,1.42383 0.58008,1.86914 0.38671,0.4414 0.92968,0.66211 1.6289,0.66211 0.3125,0 0.62109,-0.041 0.92578,-0.12305 0.30859,-0.0859 0.61523,-0.21289 0.91993,-0.38086 l 0,0.99609 c -0.30079,0.14063 -0.61329,0.2461 -0.9375,0.31641 -0.32032,0.0703 -0.66212,0.10547 -1.02539,0.10547 -0.98829,0 -1.77344,-0.31055 -2.35547,-0.93164 -0.58204,-0.62109 -0.87305,-1.45898 -0.87305,-2.51367 0,-1.07031 0.29297,-1.91211 0.87891,-2.52539 0.58984,-0.61328 1.39648,-0.91992 2.41992,-0.91993 0.33203,10e-6 0.65624,0.0352 0.97265,0.10547 0.31641,0.0664 0.62305,0.16798 0.91993,0.30469"
|
||||
style=""
|
||||
id="path3359" />
|
||||
<path
|
||||
d="m 261.71426,627.88129 c -0.57812,0 -1.03515,0.22656 -1.37109,0.67968 -0.33594,0.44923 -0.50391,1.06641 -0.50391,1.85157 0,0.78516 0.16602,1.4043 0.49805,1.85742 0.33594,0.44922 0.79492,0.67383 1.37695,0.67383 0.57422,0 1.0293,-0.22656 1.36524,-0.67969 0.33593,-0.45312 0.5039,-1.07031 0.5039,-1.85156 0,-0.77734 -0.16797,-1.39258 -0.5039,-1.84571 -0.33594,-0.45702 -0.79102,-0.68554 -1.36524,-0.68554 m 0,-0.91407 c 0.9375,10e-6 1.67383,0.3047 2.20899,0.91407 0.53515,0.60938 0.80273,1.45313 0.80273,2.53125 0,1.07422 -0.26758,1.91797 -0.80273,2.53125 -0.53516,0.60937 -1.27149,0.91406 -2.20899,0.91406 -0.94141,0 -1.67969,-0.30469 -2.21484,-0.91406 -0.53125,-0.61328 -0.79688,-1.45703 -0.79687,-2.53125 -10e-6,-1.07812 0.26562,-1.92187 0.79687,-2.53125 0.53515,-0.60937 1.27343,-0.91406 2.21484,-0.91407"
|
||||
style=""
|
||||
id="path3361" />
|
||||
<path
|
||||
d="m 271.96231,629.72699 0,3.96094 -1.07812,0 0,-3.92578 c -10e-6,-0.62109 -0.1211,-1.08594 -0.36329,-1.39454 -0.24219,-0.30858 -0.60547,-0.46288 -1.08984,-0.46289 -0.58203,10e-6 -1.04102,0.18556 -1.37695,0.55664 -0.33594,0.3711 -0.50391,0.87696 -0.50391,1.51758 l 0,3.70899 -1.08398,0 0,-6.5625 1.08398,0 0,1.01953 c 0.25781,-0.39453 0.56055,-0.68945 0.9082,-0.88477 0.35156,-0.1953 0.75586,-0.29296 1.2129,-0.29297 0.7539,10e-6 1.32421,0.23439 1.71093,0.70313 0.38672,0.46485 0.58007,1.15039 0.58008,2.05664"
|
||||
style=""
|
||||
id="path3363" />
|
||||
<path
|
||||
d="m 278.44278,628.12152 0,-3.55078 1.07812,0 0,9.11719 -1.07812,0 0,-0.98438 c -0.22657,0.39063 -0.51368,0.68164 -0.86133,0.87305 -0.34375,0.1875 -0.75781,0.28125 -1.24219,0.28125 -0.79297,0 -1.43945,-0.31641 -1.93945,-0.94922 -0.49609,-0.63281 -0.74414,-1.46484 -0.74414,-2.49609 0,-1.03125 0.24805,-1.86328 0.74414,-2.4961 0.5,-0.6328 1.14648,-0.94921 1.93945,-0.94922 0.48438,10e-6 0.89844,0.0957 1.24219,0.28711 0.34765,0.18751 0.63476,0.47657 0.86133,0.86719 m -3.67383,2.29102 c 0,0.79297 0.16211,1.41601 0.48633,1.86914 0.32812,0.44922 0.77734,0.67383 1.34766,0.67383 0.5703,0 1.01952,-0.22461 1.34765,-0.67383 0.32812,-0.45313 0.49218,-1.07617 0.49219,-1.86914 -1e-5,-0.79297 -0.16407,-1.41406 -0.49219,-1.86328 -0.32813,-0.45312 -0.77735,-0.67969 -1.34765,-0.67969 -0.57032,0 -1.01954,0.22657 -1.34766,0.67969 -0.32422,0.44922 -0.48633,1.07031 -0.48633,1.86328"
|
||||
style=""
|
||||
id="path3365" />
|
||||
<path
|
||||
d="m 284.72403,630.3891 c -0.8711,0 -1.47461,0.0996 -1.81055,0.29883 -0.33594,0.19922 -0.50391,0.53906 -0.5039,1.01953 -1e-5,0.38281 0.12499,0.6875 0.375,0.91406 0.2539,0.22266 0.59765,0.33399 1.03125,0.33399 0.59765,0 1.07616,-0.21094 1.43554,-0.63282 0.36328,-0.42578 0.54492,-0.99023 0.54493,-1.69336 l 0,-0.24023 -1.07227,0 m 2.15039,-0.44531 0,3.74414 -1.07812,0 0,-0.9961 c -0.2461,0.39844 -0.55274,0.69336 -0.91993,0.88477 -0.36719,0.1875 -0.81641,0.28125 -1.34765,0.28125 -0.67188,0 -1.20704,-0.1875 -1.60547,-0.5625 -0.39453,-0.37891 -0.5918,-0.88477 -0.5918,-1.51758 0,-0.73828 0.24609,-1.29492 0.73828,-1.66992 0.49609,-0.375 1.23437,-0.5625 2.21485,-0.5625 l 1.51172,0 0,-0.10547 c -10e-6,-0.49609 -0.16407,-0.8789 -0.49219,-1.14844 -0.32423,-0.27343 -0.78126,-0.41015 -1.3711,-0.41015 -0.375,0 -0.74023,0.0449 -1.0957,0.13476 -0.35547,0.0899 -0.69727,0.22462 -1.02539,0.4043 l 0,-0.99609 c 0.39453,-0.15234 0.77734,-0.26562 1.14844,-0.33985 0.37109,-0.0781 0.73242,-0.11718 1.08398,-0.11719 0.94922,10e-6 1.6582,0.2461 2.12696,0.73829 0.46874,0.49219 0.70311,1.23828 0.70312,2.23828"
|
||||
style=""
|
||||
id="path3367" />
|
||||
<path
|
||||
d="m 292.90372,628.13324 c -0.1211,-0.0703 -0.25391,-0.12109 -0.39844,-0.15234 -0.14063,-0.0352 -0.29688,-0.0527 -0.46875,-0.0527 -0.60938,10e-6 -1.07813,0.19923 -1.40625,0.59766 -0.32422,0.39453 -0.48633,0.96289 -0.48633,1.70508 l 0,3.45703 -1.08398,0 0,-6.5625 1.08398,0 0,1.01953 c 0.22656,-0.39843 0.52148,-0.69335 0.88477,-0.88477 0.36327,-0.1953 0.80468,-0.29296 1.32422,-0.29297 0.0742,10e-6 0.15624,0.006 0.24609,0.0176 0.0898,0.008 0.18945,0.0215 0.29883,0.041 l 0.006,1.10742"
|
||||
style=""
|
||||
id="path3369" />
|
||||
<path
|
||||
d="m 296.77676,634.2973 c -0.30469,0.78125 -0.60156,1.29102 -0.89062,1.5293 -0.28907,0.23828 -0.67578,0.35742 -1.16016,0.35742 l -0.86133,0 0,-0.90234 0.63282,0 c 0.29687,0 0.52734,-0.0703 0.6914,-0.21094 0.16406,-0.14063 0.3457,-0.47266 0.54493,-0.99609 l 0.19335,-0.49219 -2.65429,-6.45703 1.14258,0 2.05078,5.13281 2.05078,-5.13281 1.14258,0 -2.88282,7.17187"
|
||||
style=""
|
||||
id="path3371" />
|
||||
<path
|
||||
d="m 305.01505,624.93988 1.76367,0 2.23242,5.95313 2.24414,-5.95313 1.76367,0 0,8.74805 -1.1543,0 0,-7.68164 -2.25585,6 -1.18946,0 -2.25586,-6 0,7.68164 -1.14843,0 0,-8.74805"
|
||||
style=""
|
||||
id="path3373" />
|
||||
<path
|
||||
d="m 317.87051,627.88129 c -0.57812,0 -1.03515,0.22656 -1.37109,0.67968 -0.33594,0.44923 -0.50391,1.06641 -0.50391,1.85157 0,0.78516 0.16602,1.4043 0.49805,1.85742 0.33594,0.44922 0.79492,0.67383 1.37695,0.67383 0.57422,0 1.0293,-0.22656 1.36524,-0.67969 0.33593,-0.45312 0.5039,-1.07031 0.5039,-1.85156 0,-0.77734 -0.16797,-1.39258 -0.5039,-1.84571 -0.33594,-0.45702 -0.79102,-0.68554 -1.36524,-0.68554 m 0,-0.91407 c 0.9375,10e-6 1.67383,0.3047 2.20899,0.91407 0.53515,0.60938 0.80273,1.45313 0.80273,2.53125 0,1.07422 -0.26758,1.91797 -0.80273,2.53125 -0.53516,0.60937 -1.27149,0.91406 -2.20899,0.91406 -0.94141,0 -1.67969,-0.30469 -2.21484,-0.91406 -0.53125,-0.61328 -0.79688,-1.45703 -0.79687,-2.53125 -10e-6,-1.07812 0.26562,-1.92187 0.79687,-2.53125 0.53515,-0.60937 1.27343,-0.91406 2.21484,-0.91407"
|
||||
style=""
|
||||
id="path3375" />
|
||||
<path
|
||||
d="m 328.11856,629.72699 0,3.96094 -1.07812,0 0,-3.92578 c -10e-6,-0.62109 -0.1211,-1.08594 -0.36329,-1.39454 -0.24219,-0.30858 -0.60547,-0.46288 -1.08984,-0.46289 -0.58203,10e-6 -1.04102,0.18556 -1.37695,0.55664 -0.33594,0.3711 -0.50391,0.87696 -0.50391,1.51758 l 0,3.70899 -1.08398,0 0,-6.5625 1.08398,0 0,1.01953 c 0.25781,-0.39453 0.56055,-0.68945 0.9082,-0.88477 0.35156,-0.1953 0.75586,-0.29296 1.2129,-0.29297 0.7539,10e-6 1.32421,0.23439 1.71093,0.70313 0.38672,0.46485 0.58007,1.15039 0.58008,2.05664"
|
||||
style=""
|
||||
id="path3377" />
|
||||
<path
|
||||
d="m 330.28067,627.12543 1.07813,0 0,6.5625 -1.07813,0 0,-6.5625 m 0,-2.55469 1.07813,0 0,1.36523 -1.07813,0 0,-1.36523"
|
||||
style=""
|
||||
id="path3379" />
|
||||
<path
|
||||
d="m 334.6752,625.26215 0,1.86328 2.2207,0 0,0.83789 -2.2207,0 0,3.5625 c 0,0.53516 0.0723,0.87891 0.2168,1.03125 0.14843,0.15234 0.44726,0.22851 0.89648,0.22851 l 1.10742,0 0,0.90235 -1.10742,0 c -0.83203,0 -1.40625,-0.1543 -1.72265,-0.46289 -0.31641,-0.3125 -0.47461,-0.87891 -0.47461,-1.69922 l 0,-3.5625 -0.79102,0 0,-0.83789 0.79102,0 0,-1.86328 1.08398,0"
|
||||
style=""
|
||||
id="path3381" />
|
||||
<path
|
||||
d="m 340.8627,627.88129 c -0.57813,0 -1.03516,0.22656 -1.37109,0.67968 -0.33594,0.44923 -0.50391,1.06641 -0.50391,1.85157 0,0.78516 0.16602,1.4043 0.49805,1.85742 0.33593,0.44922 0.79492,0.67383 1.37695,0.67383 0.57422,0 1.02929,-0.22656 1.36524,-0.67969 0.33593,-0.45312 0.5039,-1.07031 0.5039,-1.85156 0,-0.77734 -0.16797,-1.39258 -0.5039,-1.84571 -0.33595,-0.45702 -0.79102,-0.68554 -1.36524,-0.68554 m 0,-0.91407 c 0.9375,10e-6 1.67382,0.3047 2.20899,0.91407 0.53515,0.60938 0.80272,1.45313 0.80273,2.53125 -10e-6,1.07422 -0.26758,1.91797 -0.80273,2.53125 -0.53517,0.60937 -1.27149,0.91406 -2.20899,0.91406 -0.94141,0 -1.67969,-0.30469 -2.21484,-0.91406 -0.53125,-0.61328 -0.79688,-1.45703 -0.79688,-2.53125 0,-1.07812 0.26563,-1.92187 0.79688,-2.53125 0.53515,-0.60937 1.27343,-0.91406 2.21484,-0.91407"
|
||||
style=""
|
||||
id="path3383" />
|
||||
<path
|
||||
d="m 349.4584,628.13324 c -0.12109,-0.0703 -0.25391,-0.12109 -0.39843,-0.15234 -0.14063,-0.0352 -0.29688,-0.0527 -0.46875,-0.0527 -0.60938,10e-6 -1.07813,0.19923 -1.40625,0.59766 -0.32422,0.39453 -0.48633,0.96289 -0.48633,1.70508 l 0,3.45703 -1.08399,0 0,-6.5625 1.08399,0 0,1.01953 c 0.22656,-0.39843 0.52148,-0.69335 0.88476,-0.88477 0.36328,-0.1953 0.80469,-0.29296 1.32422,-0.29297 0.0742,10e-6 0.15625,0.006 0.2461,0.0176 0.0898,0.008 0.18945,0.0215 0.29883,0.041 l 0.006,1.10742"
|
||||
style=""
|
||||
id="path3385" />
|
||||
</g>
|
||||
<g
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#00b800;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
id="text3777">
|
||||
<path
|
||||
d="m 575.27002,547.52673 0,3.28711 1.48828,0 c 0.55078,10e-6 0.97656,-0.14257 1.27734,-0.42773 0.30078,-0.28515 0.45117,-0.6914 0.45118,-1.21875 -10e-6,-0.52343 -0.1504,-0.92773 -0.45118,-1.21289 -0.30078,-0.28515 -0.72656,-0.42773 -1.27734,-0.42774 l -1.48828,0 m -1.18359,-0.97265 2.67187,0 c 0.98046,10e-6 1.7207,0.22266 2.2207,0.66797 0.5039,0.44141 0.75586,1.08985 0.75586,1.94531 0,0.86328 -0.25196,1.51563 -0.75586,1.95703 -0.5,0.44141 -1.24024,0.66211 -2.2207,0.66211 l -1.48828,0 0,3.51562 -1.18359,0 0,-8.74804"
|
||||
style=""
|
||||
id="path3326" />
|
||||
<path
|
||||
d="m 584.87354,549.74744 c -0.1211,-0.0703 -0.25392,-0.12109 -0.39844,-0.15235 -0.14063,-0.0352 -0.29688,-0.0527 -0.46875,-0.0527 -0.60938,0 -1.07813,0.19922 -1.40625,0.59765 -0.32422,0.39454 -0.48633,0.9629 -0.48633,1.70508 l 0,3.45703 -1.08398,0 0,-6.5625 1.08398,0 0,1.01954 c 0.22656,-0.39844 0.52148,-0.69336 0.88477,-0.88477 0.36327,-0.19531 0.80468,-0.29296 1.32421,-0.29297 0.0742,10e-6 0.15625,0.006 0.2461,0.0176 0.0898,0.008 0.18945,0.0215 0.29883,0.041 l 0.006,1.10743"
|
||||
style=""
|
||||
id="path3328" />
|
||||
<path
|
||||
d="m 586.01611,548.73962 1.07813,0 0,6.5625 -1.07813,0 0,-6.5625 m 0,-2.55468 1.07813,0 0,1.36523 -1.07813,0 0,-1.36523"
|
||||
style=""
|
||||
id="path3330" />
|
||||
<path
|
||||
d="m 594.45361,549.99939 c 0.26953,-0.48437 0.59179,-0.84179 0.9668,-1.07227 0.37499,-0.23046 0.8164,-0.34569 1.32422,-0.3457 0.68358,10e-6 1.21093,0.24024 1.58203,0.7207 0.37108,0.47657 0.55663,1.15626 0.55664,2.03907 l 0,3.96093 -1.08398,0 0,-3.92578 c -10e-6,-0.6289 -0.11134,-1.0957 -0.33399,-1.40039 -0.22266,-0.30468 -0.56251,-0.45702 -1.01953,-0.45703 -0.5586,10e-6 -1.00001,0.18555 -1.32422,0.55664 -0.32422,0.3711 -0.48633,0.87696 -0.48633,1.51758 l 0,3.70898 -1.08398,0 0,-3.92578 c -1e-5,-0.63281 -0.11133,-1.0996 -0.33398,-1.40039 -0.22267,-0.30468 -0.56642,-0.45702 -1.03125,-0.45703 -0.55079,10e-6 -0.98829,0.18751 -1.3125,0.5625 -0.32423,0.3711 -0.48634,0.87501 -0.48633,1.51172 l 0,3.70898 -1.08399,0 0,-6.5625 1.08399,0 0,1.01954 c 0.24609,-0.40234 0.54101,-0.69922 0.88476,-0.89063 0.34375,-0.1914 0.75195,-0.2871 1.22461,-0.28711 0.47656,10e-6 0.88086,0.1211 1.21289,0.36328 0.33593,0.2422 0.58398,0.59376 0.74414,1.05469"
|
||||
style=""
|
||||
id="path3332" />
|
||||
<path
|
||||
d="m 604.02197,552.0033 c -0.87109,0 -1.47461,0.0996 -1.81054,0.29882 -0.33594,0.19923 -0.50391,0.53907 -0.50391,1.01954 0,0.38281 0.125,0.6875 0.375,0.91406 0.2539,0.22265 0.59765,0.33398 1.03125,0.33398 0.59765,0 1.07617,-0.21093 1.43555,-0.63281 0.36327,-0.42578 0.54491,-0.99023 0.54492,-1.69336 l 0,-0.24023 -1.07227,0 m 2.15039,-0.44532 0,3.74414 -1.07812,0 0,-0.99609 c -0.2461,0.39844 -0.55274,0.69336 -0.91992,0.88477 -0.36719,0.1875 -0.81641,0.28125 -1.34766,0.28125 -0.67188,0 -1.20703,-0.1875 -1.60547,-0.5625 -0.39453,-0.37891 -0.5918,-0.88477 -0.5918,-1.51758 0,-0.73828 0.2461,-1.29492 0.73829,-1.66992 0.49609,-0.375 1.23437,-0.5625 2.21484,-0.5625 l 1.51172,0 0,-0.10547 c -10e-6,-0.49609 -0.16407,-0.8789 -0.49219,-1.14844 -0.32422,-0.27343 -0.78125,-0.41015 -1.37109,-0.41016 -0.37501,10e-6 -0.74024,0.0449 -1.09571,0.13477 -0.35547,0.0898 -0.69726,0.22461 -1.02539,0.4043 l 0,-0.9961 c 0.39453,-0.15234 0.77735,-0.26562 1.14844,-0.33984 0.37109,-0.0781 0.73242,-0.11718 1.08399,-0.11719 0.94921,10e-6 1.65819,0.2461 2.12695,0.73828 0.46874,0.4922 0.70312,1.23829 0.70312,2.23828"
|
||||
style=""
|
||||
id="path3334" />
|
||||
<path
|
||||
d="m 612.20166,549.74744 c -0.1211,-0.0703 -0.25391,-0.12109 -0.39844,-0.15235 -0.14063,-0.0352 -0.29688,-0.0527 -0.46875,-0.0527 -0.60938,0 -1.07813,0.19922 -1.40625,0.59765 -0.32422,0.39454 -0.48633,0.9629 -0.48633,1.70508 l 0,3.45703 -1.08398,0 0,-6.5625 1.08398,0 0,1.01954 c 0.22656,-0.39844 0.52149,-0.69336 0.88477,-0.88477 0.36328,-0.19531 0.80468,-0.29296 1.32422,-0.29297 0.0742,10e-6 0.15624,0.006 0.24609,0.0176 0.0898,0.008 0.18945,0.0215 0.29883,0.041 l 0.006,1.10743"
|
||||
style=""
|
||||
id="path3336" />
|
||||
<path
|
||||
d="m 616.07471,555.9115 c -0.30469,0.78125 -0.60157,1.29101 -0.89063,1.5293 -0.28906,0.23827 -0.67578,0.35742 -1.16015,0.35742 l -0.86133,0 0,-0.90235 0.63281,0 c 0.29687,0 0.52734,-0.0703 0.69141,-0.21093 0.16406,-0.14063 0.3457,-0.47266 0.54492,-0.9961 l 0.19336,-0.49218 -2.6543,-6.45704 1.14258,0 2.05078,5.13282 2.05078,-5.13282 1.14258,0 -2.88281,7.17188"
|
||||
style=""
|
||||
id="path3338" />
|
||||
<path
|
||||
d="m 624.31299,546.55408 1.76367,0 2.23242,5.95312 2.24414,-5.95312 1.76367,0 0,8.74804 -1.15429,0 0,-7.68164 -2.25586,6 -1.18945,0 -2.25586,-6 0,7.68164 -1.14844,0 0,-8.74804"
|
||||
style=""
|
||||
id="path3340" />
|
||||
<path
|
||||
d="m 637.16846,549.49548 c -0.57813,10e-6 -1.03516,0.22657 -1.3711,0.67969 -0.33594,0.44922 -0.5039,1.06641 -0.5039,1.85156 0,0.78516 0.16601,1.4043 0.49804,1.85743 0.33594,0.44921 0.79492,0.67382 1.37696,0.67382 0.57421,0 1.02929,-0.22656 1.36523,-0.67968 0.33593,-0.45313 0.5039,-1.07031 0.50391,-1.85157 -10e-6,-0.77734 -0.16798,-1.39257 -0.50391,-1.8457 -0.33594,-0.45703 -0.79102,-0.68554 -1.36523,-0.68555 m 0,-0.91406 c 0.93749,10e-6 1.67382,0.30469 2.20898,0.91406 0.53515,0.60938 0.80273,1.45313 0.80274,2.53125 -10e-6,1.07422 -0.26759,1.91797 -0.80274,2.53125 -0.53516,0.60938 -1.27149,0.91407 -2.20898,0.91407 -0.94141,0 -1.67969,-0.30469 -2.21485,-0.91407 -0.53125,-0.61328 -0.79687,-1.45703 -0.79687,-2.53125 0,-1.07812 0.26562,-1.92187 0.79687,-2.53125 0.53516,-0.60937 1.27344,-0.91405 2.21485,-0.91406"
|
||||
style=""
|
||||
id="path3342" />
|
||||
<path
|
||||
d="m 647.4165,551.34119 0,3.96093 -1.07812,0 0,-3.92578 c -10e-6,-0.62109 -0.1211,-1.08593 -0.36328,-1.39453 -0.24219,-0.30859 -0.60548,-0.46288 -1.08985,-0.46289 -0.58203,10e-6 -1.04101,0.18555 -1.37695,0.55664 -0.33594,0.3711 -0.50391,0.87696 -0.50391,1.51758 l 0,3.70898 -1.08398,0 0,-6.5625 1.08398,0 0,1.01954 c 0.25781,-0.39453 0.56055,-0.68945 0.90821,-0.88477 0.35156,-0.19531 0.75585,-0.29296 1.21289,-0.29297 0.7539,10e-6 1.32421,0.23438 1.71094,0.70313 0.38671,0.46485 0.58007,1.15039 0.58007,2.05664"
|
||||
style=""
|
||||
id="path3344" />
|
||||
<path
|
||||
d="m 649.57861,548.73962 1.07813,0 0,6.5625 -1.07813,0 0,-6.5625 m 0,-2.55468 1.07813,0 0,1.36523 -1.07813,0 0,-1.36523"
|
||||
style=""
|
||||
id="path3346" />
|
||||
<path
|
||||
d="m 653.97314,546.87634 0,1.86328 2.22071,0 0,0.83789 -2.22071,0 0,3.5625 c 0,0.53516 0.0723,0.87891 0.2168,1.03125 0.14844,0.15235 0.44726,0.22852 0.89649,0.22852 l 1.10742,0 0,0.90234 -1.10742,0 c -0.83204,0 -1.40626,-0.15429 -1.72266,-0.46289 -0.31641,-0.3125 -0.47461,-0.8789 -0.47461,-1.69922 l 0,-3.5625 -0.79102,0 0,-0.83789 0.79102,0 0,-1.86328 1.08398,0"
|
||||
style=""
|
||||
id="path3348" />
|
||||
<path
|
||||
d="m 660.16064,549.49548 c -0.57812,10e-6 -1.03515,0.22657 -1.37109,0.67969 -0.33594,0.44922 -0.50391,1.06641 -0.50391,1.85156 0,0.78516 0.16602,1.4043 0.49805,1.85743 0.33594,0.44921 0.79492,0.67382 1.37695,0.67382 0.57422,0 1.0293,-0.22656 1.36524,-0.67968 0.33593,-0.45313 0.5039,-1.07031 0.50391,-1.85157 -1e-5,-0.77734 -0.16798,-1.39257 -0.50391,-1.8457 -0.33594,-0.45703 -0.79102,-0.68554 -1.36524,-0.68555 m 0,-0.91406 c 0.9375,10e-6 1.67383,0.30469 2.20899,0.91406 0.53515,0.60938 0.80273,1.45313 0.80273,2.53125 0,1.07422 -0.26758,1.91797 -0.80273,2.53125 -0.53516,0.60938 -1.27149,0.91407 -2.20899,0.91407 -0.9414,0 -1.67968,-0.30469 -2.21484,-0.91407 -0.53125,-0.61328 -0.79687,-1.45703 -0.79687,-2.53125 0,-1.07812 0.26562,-1.92187 0.79687,-2.53125 0.53516,-0.60937 1.27344,-0.91405 2.21484,-0.91406"
|
||||
style=""
|
||||
id="path3350" />
|
||||
<path
|
||||
d="m 668.75635,549.74744 c -0.1211,-0.0703 -0.25391,-0.12109 -0.39844,-0.15235 -0.14063,-0.0352 -0.29688,-0.0527 -0.46875,-0.0527 -0.60938,0 -1.07813,0.19922 -1.40625,0.59765 -0.32422,0.39454 -0.48633,0.9629 -0.48633,1.70508 l 0,3.45703 -1.08398,0 0,-6.5625 1.08398,0 0,1.01954 c 0.22656,-0.39844 0.52148,-0.69336 0.88477,-0.88477 0.36328,-0.19531 0.80468,-0.29296 1.32422,-0.29297 0.0742,10e-6 0.15624,0.006 0.24609,0.0176 0.0898,0.008 0.18945,0.0215 0.29883,0.041 l 0.006,1.10743"
|
||||
style=""
|
||||
id="path3352" />
|
||||
</g>
|
||||
<g
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
id="text3781">
|
||||
<path
|
||||
d="m 612.64136,657.77118 -3.33985,-8.74805 1.23633,0 2.77149,7.36524 2.77734,-7.36524 1.23047,0 -3.33399,8.74805 -1.34179,0"
|
||||
style=""
|
||||
id="path3401" />
|
||||
<path
|
||||
d="m 618.28394,651.20868 1.07812,0 0,6.5625 -1.07812,0 0,-6.5625 m 0,-2.55469 1.07812,0 0,1.36524 -1.07812,0 0,-1.36524"
|
||||
style=""
|
||||
id="path3403" />
|
||||
<path
|
||||
d="m 625.41479,652.21649 c -0.12109,-0.0703 -0.25391,-0.12109 -0.39843,-0.15234 -0.14063,-0.0352 -0.29688,-0.0527 -0.46875,-0.0527 -0.60938,1e-5 -1.07813,0.19923 -1.40625,0.59766 -0.32422,0.39454 -0.48633,0.96289 -0.48633,1.70508 l 0,3.45703 -1.08399,0 0,-6.5625 1.08399,0 0,1.01953 c 0.22656,-0.39843 0.52148,-0.69335 0.88476,-0.88477 0.36328,-0.1953 0.80469,-0.29296 1.32422,-0.29296 0.0742,0 0.15625,0.006 0.2461,0.0176 0.0898,0.008 0.18945,0.0215 0.29883,0.041 l 0.006,1.10742"
|
||||
style=""
|
||||
id="path3405" />
|
||||
<path
|
||||
d="m 627.62378,649.3454 0,1.86328 2.2207,0 0,0.83789 -2.2207,0 0,3.5625 c 0,0.53516 0.0723,0.87891 0.2168,1.03125 0.14843,0.15234 0.44726,0.22852 0.89648,0.22852 l 1.10742,0 0,0.90234 -1.10742,0 c -0.83203,0 -1.40625,-0.1543 -1.72266,-0.46289 -0.3164,-0.3125 -0.47461,-0.87891 -0.47461,-1.69922 l 0,-3.5625 -0.79101,0 0,-0.83789 0.79101,0 0,-1.86328 1.08399,0"
|
||||
style=""
|
||||
id="path3407" />
|
||||
<path
|
||||
d="m 631.15698,655.18134 0,-3.97266 1.07813,0 0,3.93164 c 0,0.6211 0.12109,1.08789 0.36328,1.40039 0.24218,0.3086 0.60546,0.46289 1.08984,0.46289 0.58203,0 1.04101,-0.18554 1.37696,-0.55664 0.33983,-0.37109 0.50976,-0.87695 0.50976,-1.51758 l 0,-3.7207 1.07813,0 0,6.5625 -1.07813,0 0,-1.00781 c -0.26172,0.39843 -0.56641,0.69531 -0.91406,0.89062 -0.34376,0.19141 -0.74415,0.28711 -1.20117,0.28711 -0.75391,0 -1.32618,-0.23437 -1.7168,-0.70312 -0.39063,-0.46875 -0.58594,-1.1543 -0.58594,-2.05664 m 2.71289,-4.13086 0,0"
|
||||
style=""
|
||||
id="path3409" />
|
||||
<path
|
||||
d="m 641.86792,654.47235 c -0.8711,0 -1.47461,0.0996 -1.81055,0.29883 -0.33594,0.19922 -0.50391,0.53906 -0.5039,1.01953 -10e-6,0.38281 0.12499,0.6875 0.375,0.91406 0.2539,0.22266 0.59765,0.33399 1.03125,0.33399 0.59765,0 1.07616,-0.21094 1.43554,-0.63282 0.36328,-0.42577 0.54492,-0.99023 0.54493,-1.69335 l 0,-0.24024 -1.07227,0 m 2.15039,-0.44531 0,3.74414 -1.07812,0 0,-0.99609 c -0.2461,0.39843 -0.55274,0.69336 -0.91993,0.88476 -0.36719,0.1875 -0.81641,0.28125 -1.34765,0.28125 -0.67188,0 -1.20704,-0.1875 -1.60547,-0.5625 -0.39453,-0.3789 -0.5918,-0.88476 -0.5918,-1.51758 0,-0.73828 0.24609,-1.29492 0.73828,-1.66992 0.49609,-0.37499 1.23438,-0.56249 2.21485,-0.5625 l 1.51172,0 0,-0.10547 c -10e-6,-0.49609 -0.16407,-0.8789 -0.49219,-1.14844 -0.32423,-0.27343 -0.78126,-0.41015 -1.3711,-0.41015 -0.375,0 -0.74023,0.0449 -1.0957,0.13476 -0.35547,0.0899 -0.69727,0.22462 -1.02539,0.4043 l 0,-0.99609 c 0.39453,-0.15234 0.77734,-0.26562 1.14844,-0.33985 0.37109,-0.0781 0.73242,-0.11718 1.08398,-0.11718 0.94922,0 1.6582,0.2461 2.12696,0.73828 0.46874,0.49219 0.70311,1.23828 0.70312,2.23828"
|
||||
style=""
|
||||
id="path3411" />
|
||||
<path
|
||||
d="m 646.24487,648.65399 1.07813,0 0,9.11719 -1.07813,0 0,-9.11719"
|
||||
style=""
|
||||
id="path3413" />
|
||||
<path
|
||||
d="m 658.68433,649.31024 0,1.1543 c -0.44923,-0.21484 -0.87306,-0.37499 -1.27149,-0.48047 -0.39844,-0.10546 -0.78321,-0.1582 -1.1543,-0.1582 -0.64453,0 -1.14258,0.125 -1.49414,0.375 -0.34765,0.25 -0.52148,0.60547 -0.52148,1.0664 0,0.38673 0.11523,0.6797 0.3457,0.87891 0.23438,0.19532 0.67578,0.35352 1.32422,0.47461 l 0.71485,0.14648 c 0.8828,0.16798 1.53319,0.46485 1.95117,0.89063 0.42187,0.42188 0.6328,0.98828 0.63281,1.69922 -10e-6,0.84765 -0.28516,1.49023 -0.85547,1.92773 -0.56641,0.4375 -1.39844,0.65625 -2.49609,0.65625 -0.41407,0 -0.85547,-0.0469 -1.32422,-0.14062 -0.46485,-0.0937 -0.94727,-0.23243 -1.44727,-0.41602 l 0,-1.21875 c 0.48047,0.26953 0.95117,0.47266 1.41211,0.60938 0.46094,0.13672 0.91406,0.20507 1.35938,0.20507 0.67577,0 1.19726,-0.13281 1.56445,-0.39843 0.36718,-0.26563 0.55078,-0.64453 0.55078,-1.13672 0,-0.42969 -0.13282,-0.76562 -0.39844,-1.00782 -0.26172,-0.24218 -0.69336,-0.42382 -1.29492,-0.54492 l -0.7207,-0.14062 c -0.88282,-0.17578 -1.52149,-0.45117 -1.91602,-0.82617 -0.39453,-0.375 -0.59179,-0.89648 -0.59179,-1.56446 0,-0.77343 0.27148,-1.3828 0.81445,-1.82812 0.54687,-0.44531 1.29883,-0.66796 2.25586,-0.66797 0.41015,1e-5 0.82812,0.0371 1.25391,0.11133 0.42577,0.0742 0.86132,0.18555 1.30664,0.33398"
|
||||
style=""
|
||||
id="path3415" />
|
||||
<path
|
||||
d="m 665.73315,651.46063 0,1.00781 c -0.30469,-0.16796 -0.61133,-0.29296 -0.91992,-0.375 -0.30469,-0.0859 -0.61328,-0.1289 -0.92578,-0.1289 -0.69922,0 -1.24219,0.22266 -1.62891,0.66797 -0.38672,0.44141 -0.58008,1.0625 -0.58007,1.86328 -10e-6,0.80078 0.19335,1.42383 0.58007,1.86914 0.38672,0.44141 0.92969,0.66211 1.62891,0.66211 0.3125,0 0.62109,-0.041 0.92578,-0.12305 0.30859,-0.0859 0.61523,-0.21289 0.91992,-0.38086 l 0,0.9961 c -0.30078,0.14062 -0.61328,0.24609 -0.9375,0.3164 -0.32031,0.0703 -0.66211,0.10547 -1.02539,0.10547 -0.98828,0 -1.77344,-0.31055 -2.35547,-0.93164 -0.58203,-0.62109 -0.87304,-1.45898 -0.87304,-2.51367 0,-1.07031 0.29297,-1.91211 0.8789,-2.52539 0.58985,-0.61328 1.39649,-0.91992 2.41993,-0.91992 0.33202,0 0.65624,0.0352 0.97265,0.10546 0.3164,0.0664 0.62304,0.16798 0.91992,0.30469"
|
||||
style=""
|
||||
id="path3417" />
|
||||
<path
|
||||
d="m 671.42261,652.21649 c -0.1211,-0.0703 -0.25391,-0.12109 -0.39844,-0.15234 -0.14063,-0.0352 -0.29688,-0.0527 -0.46875,-0.0527 -0.60938,1e-5 -1.07813,0.19923 -1.40625,0.59766 -0.32422,0.39454 -0.48633,0.96289 -0.48633,1.70508 l 0,3.45703 -1.08398,0 0,-6.5625 1.08398,0 0,1.01953 c 0.22656,-0.39843 0.52148,-0.69335 0.88477,-0.88477 0.36328,-0.1953 0.80468,-0.29296 1.32422,-0.29296 0.0742,0 0.15624,0.006 0.24609,0.0176 0.0898,0.008 0.18945,0.0215 0.29883,0.041 l 0.006,1.10742"
|
||||
style=""
|
||||
id="path3419" />
|
||||
<path
|
||||
d="m 677.92065,654.2204 0,0.52734 -4.95703,0 c 0.0469,0.74219 0.26953,1.3086 0.66797,1.69922 0.40234,0.38672 0.96094,0.58008 1.67578,0.58008 0.41406,0 0.81445,-0.0508 1.20117,-0.15235 0.39062,-0.10156 0.77734,-0.2539 1.16016,-0.45703 l 0,1.01953 c -0.38672,0.16407 -0.78321,0.28907 -1.18945,0.375 -0.40626,0.0859 -0.81837,0.12891 -1.23633,0.12891 -1.04688,0 -1.87696,-0.30469 -2.49023,-0.91406 -0.60938,-0.60938 -0.91407,-1.43359 -0.91407,-2.47266 0,-1.07421 0.28906,-1.92577 0.86719,-2.55469 0.58203,-0.6328 1.36523,-0.94921 2.34961,-0.94921 0.88281,0 1.58007,0.28516 2.0918,0.85546 0.51562,0.56642 0.77343,1.3379 0.77343,2.31446 m -1.07812,-0.31641 c -0.008,-0.58984 -0.17383,-1.06054 -0.49805,-1.41211 -0.32031,-0.35155 -0.7461,-0.52734 -1.27734,-0.52734 -0.60157,0 -1.08399,0.16993 -1.44727,0.50976 -0.35937,0.33985 -0.56641,0.81837 -0.62109,1.43555 l 3.84375,-0.006"
|
||||
style=""
|
||||
id="path3421" />
|
||||
<path
|
||||
d="m 685.30347,654.2204 0,0.52734 -4.95703,0 c 0.0469,0.74219 0.26952,1.3086 0.66796,1.69922 0.40235,0.38672 0.96094,0.58008 1.67579,0.58008 0.41405,0 0.81444,-0.0508 1.20117,-0.15235 0.39062,-0.10156 0.77734,-0.2539 1.16015,-0.45703 l 0,1.01953 c -0.38672,0.16407 -0.78321,0.28907 -1.18945,0.375 -0.40625,0.0859 -0.81836,0.12891 -1.23633,0.12891 -1.04688,0 -1.87695,-0.30469 -2.49023,-0.91406 -0.60938,-0.60938 -0.91407,-1.43359 -0.91406,-2.47266 -10e-6,-1.07421 0.28906,-1.92577 0.86718,-2.55469 0.58203,-0.6328 1.36523,-0.94921 2.34961,-0.94921 0.88281,0 1.58008,0.28516 2.0918,0.85546 0.51562,0.56642 0.77343,1.3379 0.77344,2.31446 m -1.07813,-0.31641 c -0.008,-0.58984 -0.17383,-1.06054 -0.49805,-1.41211 -0.32031,-0.35155 -0.74609,-0.52734 -1.27734,-0.52734 -0.60156,0 -1.08399,0.16993 -1.44726,0.50976 -0.35938,0.33985 -0.56641,0.81837 -0.6211,1.43555 l 3.84375,-0.006"
|
||||
style=""
|
||||
id="path3423" />
|
||||
<path
|
||||
d="m 692.52808,653.81024 0,3.96094 -1.07813,0 0,-3.92578 c 0,-0.62109 -0.1211,-1.08593 -0.36328,-1.39453 -0.24219,-0.30859 -0.60547,-0.46289 -1.08984,-0.46289 -0.58204,0 -1.04102,0.18555 -1.37696,0.55664 -0.33594,0.3711 -0.50391,0.87695 -0.5039,1.51757 l 0,3.70899 -1.08399,0 0,-6.5625 1.08399,0 0,1.01953 c 0.25781,-0.39452 0.56054,-0.68945 0.9082,-0.88477 0.35156,-0.1953 0.75586,-0.29296 1.21289,-0.29296 0.7539,0 1.32421,0.23438 1.71094,0.70312 0.38671,0.46485 0.58007,1.1504 0.58008,2.05664"
|
||||
style=""
|
||||
id="path3425" />
|
||||
</g>
|
||||
<rect
|
||||
style="fill:#b8b8b8;fill-opacity:1;stroke:#b8b8b8;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect5577"
|
||||
width="173.25098"
|
||||
height="141.43118"
|
||||
x="157.75581"
|
||||
y="436.97159" />
|
||||
<rect
|
||||
style="fill:#ededed;fill-opacity:1;stroke:#ededed;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect3789"
|
||||
width="168.99611"
|
||||
height="136.87178"
|
||||
x="159.87543"
|
||||
y="439.39697"
|
||||
inkscape:export-filename="/home/elmindreda/projects/glfw/glfw/docs/spaces.png"
|
||||
inkscape:export-xdpi="109.89113"
|
||||
inkscape:export-ydpi="109.89113" />
|
||||
<g
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
id="text3791">
|
||||
<path
|
||||
d="m 274.28683,558.98682 1.19532,0 1.83984,7.39453 1.83399,-7.39453 1.33007,0 1.83985,7.39453 1.83398,-7.39453 1.20117,0 -2.19726,8.74804 -1.48828,0 -1.84571,-7.59375 -1.86328,7.59375 -1.48828,0 -2.19141,-8.74804"
|
||||
style=""
|
||||
id="path3388" />
|
||||
<path
|
||||
d="m 286.62082,561.17236 1.07812,0 0,6.5625 -1.07812,0 0,-6.5625 m 0,-2.55468 1.07812,0 0,1.36523 -1.07812,0 0,-1.36523"
|
||||
style=""
|
||||
id="path3390" />
|
||||
<path
|
||||
d="m 295.40402,563.77393 0,3.96093 -1.07812,0 0,-3.92578 c -10e-6,-0.62109 -0.1211,-1.08593 -0.36328,-1.39453 -0.2422,-0.30859 -0.60548,-0.46288 -1.08985,-0.46289 -0.58203,1e-5 -1.04102,0.18555 -1.37695,0.55664 -0.33594,0.3711 -0.50391,0.87696 -0.50391,1.51758 l 0,3.70898 -1.08398,0 0,-6.5625 1.08398,0 0,1.01953 c 0.25781,-0.39452 0.56055,-0.68944 0.90821,-0.88476 0.35156,-0.19531 0.75585,-0.29296 1.21289,-0.29297 0.7539,1e-5 1.32421,0.23438 1.71093,0.70313 0.38672,0.46484 0.58008,1.15039 0.58008,2.05664"
|
||||
style=""
|
||||
id="path3392" />
|
||||
<path
|
||||
d="m 301.88449,562.16846 0,-3.55078 1.07813,0 0,9.11718 -1.07813,0 0,-0.98437 c -0.22657,0.39062 -0.51368,0.68164 -0.86133,0.87305 -0.34375,0.1875 -0.75781,0.28124 -1.24218,0.28125 -0.79298,-1e-5 -1.43946,-0.31641 -1.93946,-0.94922 -0.49609,-0.63281 -0.74414,-1.46485 -0.74414,-2.4961 0,-1.03124 0.24805,-1.86327 0.74414,-2.49609 0.5,-0.63281 1.14648,-0.94921 1.93946,-0.94922 0.48437,1e-5 0.89843,0.0957 1.24218,0.28711 0.34765,0.18751 0.63476,0.47657 0.86133,0.86719 m -3.67383,2.29101 c 0,0.79297 0.16211,1.41602 0.48633,1.86914 0.32812,0.44922 0.77734,0.67383 1.34766,0.67383 0.57031,0 1.01952,-0.22461 1.34765,-0.67383 0.32812,-0.45312 0.49219,-1.07617 0.49219,-1.86914 0,-0.79296 -0.16407,-1.41406 -0.49219,-1.86328 -0.32813,-0.45312 -0.77734,-0.67968 -1.34765,-0.67969 -0.57032,10e-6 -1.01954,0.22657 -1.34766,0.67969 -0.32422,0.44922 -0.48633,1.07032 -0.48633,1.86328"
|
||||
style=""
|
||||
id="path3394" />
|
||||
<path
|
||||
d="m 307.72629,561.92822 c -0.57813,10e-6 -1.03516,0.22657 -1.3711,0.67969 -0.33594,0.44922 -0.5039,1.06641 -0.5039,1.85156 0,0.78516 0.16601,1.4043 0.49804,1.85742 0.33594,0.44922 0.79492,0.67383 1.37696,0.67383 0.57421,0 1.02929,-0.22656 1.36523,-0.67968 0.33593,-0.45313 0.5039,-1.07031 0.50391,-1.85157 -1e-5,-0.77734 -0.16798,-1.39257 -0.50391,-1.8457 -0.33594,-0.45703 -0.79102,-0.68554 -1.36523,-0.68555 m 0,-0.91406 c 0.93749,1e-5 1.67382,0.30469 2.20898,0.91406 0.53515,0.60938 0.80273,1.45313 0.80274,2.53125 -10e-6,1.07422 -0.26759,1.91797 -0.80274,2.53125 -0.53516,0.60938 -1.27149,0.91406 -2.20898,0.91407 -0.94141,-1e-5 -1.67969,-0.30469 -2.21485,-0.91407 -0.53125,-0.61328 -0.79687,-1.45703 -0.79687,-2.53125 0,-1.07812 0.26562,-1.92187 0.79687,-2.53125 0.53516,-0.60937 1.27344,-0.91405 2.21485,-0.91406"
|
||||
style=""
|
||||
id="path3396" />
|
||||
<path
|
||||
d="m 311.8923,561.17236 1.07813,0 1.34765,5.1211 1.3418,-5.1211 1.27149,0 1.34765,5.1211 1.3418,-5.1211 1.07812,0 -1.71679,6.5625 -1.27149,0 -1.41211,-5.3789 -1.41797,5.3789 -1.27148,0 -1.7168,-6.5625"
|
||||
style=""
|
||||
id="path3398" />
|
||||
</g>
|
||||
<rect
|
||||
y="439.39581"
|
||||
x="159.87428"
|
||||
height="8.8251209"
|
||||
width="168.99841"
|
||||
id="rect3795"
|
||||
style="fill:#7b7bff;fill-opacity:1;stroke:#7b7bff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
inkscape:export-filename="/home/elmindreda/projects/glfw/glfw/docs/spaces.png"
|
||||
inkscape:export-xdpi="109.89113"
|
||||
inkscape:export-ydpi="109.89113" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
id="path3797"
|
||||
sodipodi:cx="352.54324"
|
||||
sodipodi:cy="373.03461"
|
||||
sodipodi:rx="2.5253813"
|
||||
sodipodi:ry="2.5253813"
|
||||
d="m 355.06862,373.03461 c 0,1.39473 -1.13065,2.52538 -2.52538,2.52538 -1.39473,0 -2.52538,-1.13065 -2.52538,-2.52538 0,-1.39473 1.13065,-2.52538 2.52538,-2.52538 1.39473,0 2.52538,1.13065 2.52538,2.52538 z"
|
||||
transform="matrix(0.66107369,0,0,0.66107369,123.32145,119.41326)"
|
||||
inkscape:export-filename="/home/elmindreda/projects/glfw/glfw/docs/spaces.png"
|
||||
inkscape:export-xdpi="109.89113"
|
||||
inkscape:export-ydpi="109.89113" />
|
||||
<path
|
||||
transform="matrix(0.66107369,0,0,0.66107369,-194.73594,119.44704)"
|
||||
d="m 355.06862,373.03461 c 0,1.39473 -1.13065,2.52538 -2.52538,2.52538 -1.39473,0 -2.52538,-1.13065 -2.52538,-2.52538 0,-1.39473 1.13065,-2.52538 2.52538,-2.52538 1.39473,0 2.52538,1.13065 2.52538,2.52538 z"
|
||||
sodipodi:ry="2.5253813"
|
||||
sodipodi:rx="2.5253813"
|
||||
sodipodi:cy="373.03461"
|
||||
sodipodi:cx="352.54324"
|
||||
id="path3799"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
sodipodi:type="arc"
|
||||
inkscape:export-filename="/home/elmindreda/projects/glfw/glfw/docs/spaces.png"
|
||||
inkscape:export-xdpi="109.89113"
|
||||
inkscape:export-ydpi="109.89113" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
id="path3801"
|
||||
sodipodi:cx="352.54324"
|
||||
sodipodi:cy="373.03461"
|
||||
sodipodi:rx="2.5253813"
|
||||
sodipodi:ry="2.5253813"
|
||||
d="m 355.06862,373.03461 c 0,1.39473 -1.13065,2.52538 -2.52538,2.52538 -1.39473,0 -2.52538,-1.13065 -2.52538,-2.52538 0,-1.39473 1.13065,-2.52538 2.52538,-2.52538 1.39473,0 2.52538,1.13065 2.52538,2.52538 z"
|
||||
transform="matrix(0.66107369,0,0,0.66107369,-73.218648,201.61091)"
|
||||
inkscape:export-filename="/home/elmindreda/projects/glfw/glfw/docs/spaces.png"
|
||||
inkscape:export-xdpi="109.89113"
|
||||
inkscape:export-ydpi="109.89113" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="21.213203"
|
||||
y="340.20465"
|
||||
id="text3803"
|
||||
sodipodi:linespacing="125%"
|
||||
inkscape:export-filename="/home/elmindreda/projects/glfw/glfw/docs/spaces.png"
|
||||
inkscape:export-xdpi="109.89113"
|
||||
inkscape:export-ydpi="109.89113"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3805"
|
||||
x="21.213203"
|
||||
y="340.20465" /></text>
|
||||
<g
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
id="text3807">
|
||||
<path
|
||||
d="m 71.179893,455.55557 0.996094,0 1.533203,6.16211 1.528321,-6.16211 1.108398,0 1.533203,6.16211 1.528321,-6.16211 1.000976,0 -1.831055,7.29004 -1.240234,0 -1.538086,-6.32812 -1.552734,6.32812 -1.240235,0 -1.826172,-7.29004"
|
||||
style="font-size:10px"
|
||||
id="path3164" />
|
||||
<path
|
||||
d="m 81.458214,457.37686 0.898437,0 0,5.46875 -0.898437,0 0,-5.46875 m 0,-2.1289 0.898437,0 0,1.13769 -0.898437,0 0,-1.13769"
|
||||
style="font-size:10px"
|
||||
id="path3166" />
|
||||
<path
|
||||
d="m 88.77755,459.54483 0,3.30078 -0.898438,0 0,-3.27148 c -4e-6,-0.51758 -0.100916,-0.90495 -0.302734,-1.16211 -0.201827,-0.25716 -0.504561,-0.38574 -0.908203,-0.38574 -0.485029,0 -0.867516,0.15462 -1.147461,0.46386 -0.27995,0.30925 -0.419924,0.7308 -0.419922,1.26465 l 0,3.09082 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.214842,-0.32877 0.46712,-0.57454 0.756836,-0.7373 0.292966,-0.16276 0.629879,-0.24414 1.010742,-0.24414 0.628251,0 1.103511,0.19531 1.425781,0.58593 0.322261,0.38738 0.483393,0.95867 0.483399,1.71387"
|
||||
style="font-size:10px"
|
||||
id="path3168" />
|
||||
<path
|
||||
d="m 94.17794,458.20694 0,-2.95898 0.898438,0 0,7.59765 -0.898438,0 0,-0.82031 c -0.188806,0.32552 -0.428064,0.56803 -0.717773,0.72754 -0.286462,0.15625 -0.631514,0.23437 -1.035156,0.23437 -0.66081,0 -1.199546,-0.26367 -1.616211,-0.79101 -0.413412,-0.52735 -0.620118,-1.2207 -0.620117,-2.08008 -10e-7,-0.85937 0.206705,-1.55273 0.620117,-2.08008 0.416665,-0.52734 0.955401,-0.79101 1.616211,-0.79101 0.403642,0 0.748694,0.0797 1.035156,0.23925 0.289709,0.15626 0.528967,0.39714 0.717773,0.72266 m -3.061523,1.90918 c -2e-6,0.66081 0.135089,1.18001 0.405273,1.55762 0.273436,0.37435 0.647784,0.56152 1.123047,0.56152 0.475257,0 0.849606,-0.18717 1.123047,-0.56152 0.273433,-0.37761 0.410152,-0.89681 0.410156,-1.55762 -4e-6,-0.6608 -0.136723,-1.17838 -0.410156,-1.55273 -0.273441,-0.3776 -0.64779,-0.56641 -1.123047,-0.56641 -0.475263,0 -0.849611,0.18881 -1.123047,0.56641 -0.270184,0.37435 -0.405275,0.89193 -0.405273,1.55273"
|
||||
style="font-size:10px"
|
||||
id="path3170" />
|
||||
<path
|
||||
d="m 99.046104,458.00674 c -0.481773,1e-5 -0.862632,0.18881 -1.142578,0.56641 -0.279949,0.37435 -0.419923,0.88868 -0.419922,1.54297 -10e-7,0.6543 0.138345,1.17025 0.415039,1.54785 0.279946,0.37435 0.662433,0.56153 1.147461,0.56152 0.478513,1e-5 0.857744,-0.1888 1.137696,-0.5664 0.27994,-0.3776 0.41992,-0.89193 0.41992,-1.54297 0,-0.64778 -0.13998,-1.16048 -0.41992,-1.53809 -0.279952,-0.38085 -0.659183,-0.57128 -1.137696,-0.57129 m 0,-0.76171 c 0.781247,0 1.394856,0.25391 1.840816,0.76171 0.44596,0.50782 0.66894,1.21095 0.66895,2.10938 -1e-5,0.89518 -0.22299,1.59831 -0.66895,2.10937 -0.44596,0.50782 -1.059569,0.76172 -1.840816,0.76172 -0.784507,0 -1.399741,-0.2539 -1.845703,-0.76172 -0.442709,-0.51106 -0.664063,-1.21419 -0.664062,-2.10937 -10e-7,-0.89843 0.221353,-1.60156 0.664062,-2.10938 0.445962,-0.5078 1.061196,-0.76171 1.845703,-0.76171"
|
||||
style="font-size:10px"
|
||||
id="path3172" />
|
||||
<path
|
||||
d="m 102.51778,457.37686 0.89844,0 1.12305,4.26758 1.11816,-4.26758 1.05957,0 1.12305,4.26758 1.11816,-4.26758 0.89844,0 -1.43066,5.46875 -1.05957,0 -1.17676,-4.48242 -1.18164,4.48242 -1.05957,0 -1.43067,-5.46875"
|
||||
style="font-size:10px"
|
||||
id="path3174" />
|
||||
<path
|
||||
d="m 115.27657,462.0253 0,2.90039 -0.90332,0 0,-7.54883 0.90332,0 0,0.83008 c 0.1888,-0.32552 0.42643,-0.5664 0.71289,-0.72266 0.28971,-0.1595 0.63477,-0.23925 1.03516,-0.23925 0.66406,0 1.20279,0.26367 1.61621,0.79101 0.41666,0.52735 0.625,1.22071 0.625,2.08008 0,0.85938 -0.20834,1.55273 -0.625,2.08008 -0.41342,0.52734 -0.95215,0.79101 -1.61621,0.79101 -0.40039,0 -0.74545,-0.0781 -1.03516,-0.23437 -0.28646,-0.15951 -0.52409,-0.40202 -0.71289,-0.72754 m 3.05664,-1.90918 c 0,-0.6608 -0.13672,-1.17838 -0.41015,-1.55273 -0.27019,-0.3776 -0.64291,-0.56641 -1.11817,-0.56641 -0.47526,0 -0.84961,0.18881 -1.12304,0.56641 -0.27019,0.37435 -0.40528,0.89193 -0.40528,1.55273 0,0.66081 0.13509,1.18001 0.40528,1.55762 0.27343,0.37435 0.64778,0.56152 1.12304,0.56152 0.47526,0 0.84798,-0.18717 1.11817,-0.56152 0.27343,-0.37761 0.41015,-0.89681 0.41015,-1.55762"
|
||||
style="font-size:10px"
|
||||
id="path3176" />
|
||||
<path
|
||||
d="m 122.87423,458.00674 c -0.48177,1e-5 -0.86263,0.18881 -1.14258,0.56641 -0.27995,0.37435 -0.41992,0.88868 -0.41992,1.54297 0,0.6543 0.13834,1.17025 0.41504,1.54785 0.27994,0.37435 0.66243,0.56153 1.14746,0.56152 0.47851,1e-5 0.85774,-0.1888 1.13769,-0.5664 0.27995,-0.3776 0.41992,-0.89193 0.41993,-1.54297 -1e-5,-0.64778 -0.13998,-1.16048 -0.41993,-1.53809 -0.27995,-0.38085 -0.65918,-0.57128 -1.13769,-0.57129 m 0,-0.76171 c 0.78125,0 1.39485,0.25391 1.84082,0.76171 0.44596,0.50782 0.66894,1.21095 0.66895,2.10938 -1e-5,0.89518 -0.22299,1.59831 -0.66895,2.10937 -0.44597,0.50782 -1.05957,0.76172 -1.84082,0.76172 -0.78451,0 -1.39974,-0.2539 -1.8457,-0.76172 -0.44271,-0.51106 -0.66407,-1.21419 -0.66407,-2.10937 0,-0.89843 0.22136,-1.60156 0.66407,-2.10938 0.44596,-0.5078 1.06119,-0.76171 1.8457,-0.76171"
|
||||
style="font-size:10px"
|
||||
id="path3178" />
|
||||
<path
|
||||
d="m 130.3547,457.53799 0,0.84961 c -0.25391,-0.1302 -0.51758,-0.22786 -0.79102,-0.29296 -0.27344,-0.0651 -0.55664,-0.0977 -0.84961,-0.0977 -0.44596,0 -0.78125,0.0684 -1.00586,0.20508 -0.22135,0.13672 -0.33203,0.3418 -0.33203,0.61523 0,0.20834 0.0797,0.37273 0.23926,0.49317 0.1595,0.11719 0.48014,0.22949 0.96191,0.33691 l 0.30762,0.0684 c 0.63802,0.13672 1.09049,0.33041 1.35742,0.58105 0.27018,0.2474 0.40527,0.59408 0.40528,1.04004 -1e-5,0.50782 -0.20183,0.90983 -0.60547,1.20606 -0.4004,0.29622 -0.95215,0.44433 -1.65528,0.44433 -0.29297,0 -0.59896,-0.0293 -0.91796,-0.0879 -0.31576,-0.0553 -0.64942,-0.13997 -1.00098,-0.2539 l 0,-0.92774 c 0.33203,0.17253 0.65918,0.30274 0.98144,0.39063 0.32227,0.0846 0.64128,0.12695 0.95704,0.12695 0.42317,0 0.74869,-0.0716 0.97656,-0.21484 0.22786,-0.14649 0.34179,-0.35157 0.3418,-0.61524 -1e-5,-0.24414 -0.083,-0.43131 -0.24903,-0.56152 -0.16276,-0.13021 -0.52246,-0.25553 -1.0791,-0.37598 l -0.3125,-0.0732 c -0.55664,-0.11719 -0.95866,-0.29622 -1.20605,-0.53711 -0.2474,-0.24414 -0.3711,-0.5778 -0.3711,-1.00098 0,-0.51431 0.18229,-0.91145 0.54688,-1.1914 0.36458,-0.27994 0.88216,-0.41992 1.55273,-0.41992 0.33203,0 0.64453,0.0244 0.9375,0.0732 0.29297,0.0488 0.56315,0.12207 0.81055,0.21972"
|
||||
style="font-size:10px"
|
||||
id="path3180" />
|
||||
<path
|
||||
d="m 132.08321,457.37686 0.89844,0 0,5.46875 -0.89844,0 0,-5.46875 m 0,-2.1289 0.89844,0 0,1.13769 -0.89844,0 0,-1.13769"
|
||||
style="font-size:10px"
|
||||
id="path3182" />
|
||||
<path
|
||||
d="m 135.74532,455.82413 0,1.55273 1.85059,0 0,0.69824 -1.85059,0 0,2.96875 c 0,0.44597 0.0602,0.73243 0.18067,0.85938 0.12369,0.12695 0.37272,0.19043 0.74707,0.19043 l 0.92285,0 0,0.75195 -0.92285,0 c -0.69336,0 -1.17188,-0.12858 -1.43555,-0.38574 -0.26367,-0.26042 -0.39551,-0.73242 -0.39551,-1.41602 l 0,-2.96875 -0.65918,0 0,-0.69824 0.65918,0 0,-1.55273 0.90332,0"
|
||||
style="font-size:10px"
|
||||
id="path3184" />
|
||||
<path
|
||||
d="m 138.78243,457.37686 0.89844,0 0,5.46875 -0.89844,0 0,-5.46875 m 0,-2.1289 0.89844,0 0,1.13769 -0.89844,0 0,-1.13769"
|
||||
style="font-size:10px"
|
||||
id="path3186" />
|
||||
<path
|
||||
d="m 143.67501,458.00674 c -0.48177,1e-5 -0.86263,0.18881 -1.14258,0.56641 -0.27995,0.37435 -0.41992,0.88868 -0.41992,1.54297 0,0.6543 0.13835,1.17025 0.41504,1.54785 0.27995,0.37435 0.66243,0.56153 1.14746,0.56152 0.47851,1e-5 0.85774,-0.1888 1.1377,-0.5664 0.27994,-0.3776 0.41991,-0.89193 0.41992,-1.54297 -1e-5,-0.64778 -0.13998,-1.16048 -0.41992,-1.53809 -0.27996,-0.38085 -0.65919,-0.57128 -1.1377,-0.57129 m 0,-0.76171 c 0.78125,0 1.39485,0.25391 1.84082,0.76171 0.44596,0.50782 0.66894,1.21095 0.66895,2.10938 -1e-5,0.89518 -0.22299,1.59831 -0.66895,2.10937 -0.44597,0.50782 -1.05957,0.76172 -1.84082,0.76172 -0.78451,0 -1.39974,-0.2539 -1.8457,-0.76172 -0.44271,-0.51106 -0.66407,-1.21419 -0.66406,-2.10937 -10e-6,-0.89843 0.22135,-1.60156 0.66406,-2.10938 0.44596,-0.5078 1.06119,-0.76171 1.8457,-0.76171"
|
||||
style="font-size:10px"
|
||||
id="path3188" />
|
||||
<path
|
||||
d="m 152.21505,459.54483 0,3.30078 -0.89844,0 0,-3.27148 c 0,-0.51758 -0.10091,-0.90495 -0.30273,-1.16211 -0.20183,-0.25716 -0.50456,-0.38574 -0.90821,-0.38574 -0.48502,0 -0.86751,0.15462 -1.14746,0.46386 -0.27995,0.30925 -0.41992,0.7308 -0.41992,1.26465 l 0,3.09082 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.21484,-0.32877 0.46712,-0.57454 0.75684,-0.7373 0.29296,-0.16276 0.62988,-0.24414 1.01074,-0.24414 0.62825,0 1.10351,0.19531 1.42578,0.58593 0.32226,0.38738 0.48339,0.95867 0.4834,1.71387"
|
||||
style="font-size:10px"
|
||||
id="path3190" />
|
||||
</g>
|
||||
<g
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
id="text3817">
|
||||
<path
|
||||
d="m 49.798271,374.06503 0,0.96192 c -0.374354,-0.17903 -0.727544,-0.3125 -1.05957,-0.40039 -0.332035,-0.0879 -0.652673,-0.13183 -0.961914,-0.13184 -0.537112,1e-5 -0.952151,0.10417 -1.245117,0.3125 -0.289716,0.20834 -0.434572,0.50456 -0.434571,0.88867 -10e-7,0.32227 0.09603,0.56641 0.288086,0.73242 0.195311,0.16277 0.563149,0.2946 1.103516,0.39551 l 0.595703,0.12207 c 0.735673,0.13998 1.277664,0.38738 1.625977,0.74219 0.351556,0.35157 0.527338,0.82357 0.527343,1.41602 -5e-6,0.70638 -0.237635,1.24186 -0.71289,1.60644 -0.47201,0.36458 -1.165369,0.54688 -2.080078,0.54688 -0.345055,0 -0.712893,-0.0391 -1.103516,-0.11719 -0.387371,-0.0781 -0.789389,-0.19369 -1.206055,-0.34668 l 0,-1.01563 c 0.40039,0.22461 0.792642,0.39388 1.176758,0.50782 0.384112,0.11393 0.761716,0.1709 1.132813,0.17089 0.563147,10e-6 0.997717,-0.11067 1.30371,-0.33203 0.305985,-0.22135 0.45898,-0.5371 0.458985,-0.94726 -5e-6,-0.35807 -0.110682,-0.63802 -0.332031,-0.83985 -0.218104,-0.20182 -0.577804,-0.35318 -1.079102,-0.4541 l -0.600586,-0.11719 c -0.735679,-0.14648 -1.267905,-0.37597 -1.59668,-0.68847 -0.328776,-0.3125 -0.493164,-0.74707 -0.493164,-1.30371 0,-0.64453 0.226236,-1.15234 0.678711,-1.52344 0.455728,-0.37109 1.082355,-0.55663 1.879883,-0.55664 0.341793,10e-6 0.6901,0.0309 1.044922,0.0928 0.354813,0.0619 0.717768,0.15463 1.088867,0.27832"
|
||||
style="font-size:10px"
|
||||
id="path3193" />
|
||||
<path
|
||||
d="m 56.414482,378.15683 0,0.43945 -4.130859,0 c 0.03906,0.61849 0.224607,1.0905 0.55664,1.41602 0.335284,0.32226 0.800779,0.4834 1.396485,0.4834 0.345048,0 0.678707,-0.0423 1.000976,-0.12696 0.325516,-0.0846 0.647782,-0.21158 0.966797,-0.38086 l 0,0.84961 c -0.322271,0.13672 -0.652674,0.24089 -0.991211,0.3125 -0.338546,0.0716 -0.68197,0.10743 -1.030273,0.10743 -0.872399,0 -1.56413,-0.25391 -2.075196,-0.76172 -0.507813,-0.50781 -0.761719,-1.19466 -0.761718,-2.06055 -10e-7,-0.89518 0.240884,-1.60481 0.722656,-2.12891 0.485024,-0.52733 1.137693,-0.79101 1.958008,-0.79101 0.735673,0 1.316727,0.23763 1.743164,0.71289 0.429682,0.47201 0.644525,1.11491 0.644531,1.92871 m -0.898437,-0.26367 c -0.0065,-0.49153 -0.144862,-0.88379 -0.415039,-1.17676 -0.266932,-0.29296 -0.621749,-0.43945 -1.064454,-0.43945 -0.501304,0 -0.903322,0.1416 -1.206054,0.4248 -0.299481,0.28321 -0.472007,0.68197 -0.517578,1.19629 l 3.203125,-0.005"
|
||||
style="font-size:10px"
|
||||
id="path3195" />
|
||||
<path
|
||||
d="m 61.824638,375.85703 0,0.83984 c -0.253911,-0.13997 -0.509444,-0.24414 -0.766601,-0.3125 -0.25391,-0.0716 -0.511072,-0.10742 -0.771485,-0.10742 -0.582685,0 -1.035158,0.18555 -1.357421,0.55664 -0.322268,0.36784 -0.4834,0.88542 -0.483399,1.55273 -10e-7,0.66732 0.161131,1.18653 0.483399,1.55762 0.322263,0.36784 0.774736,0.55176 1.357421,0.55176 0.260413,0 0.517575,-0.0342 0.771485,-0.10254 0.257157,-0.0716 0.51269,-0.17741 0.766601,-0.31738 l 0,0.83007 c -0.250655,0.11719 -0.511072,0.20508 -0.78125,0.26368 -0.266931,0.0586 -0.551761,0.0879 -0.854492,0.0879 -0.82357,0 -1.477866,-0.25879 -1.96289,-0.77637 -0.485027,-0.51758 -0.72754,-1.21582 -0.72754,-2.09473 0,-0.89192 0.24414,-1.59342 0.732422,-2.10449 0.491535,-0.51106 1.163735,-0.7666 2.016602,-0.7666 0.276689,0 0.546871,0.0293 0.810547,0.0879 0.263667,0.0553 0.519201,0.13998 0.766601,0.25391"
|
||||
style="font-size:10px"
|
||||
id="path3197" />
|
||||
<path
|
||||
d="m 65.516045,376.27695 c -0.481774,0 -0.862633,0.1888 -1.142579,0.5664 -0.279949,0.37436 -0.419923,0.88868 -0.419921,1.54297 -2e-6,0.6543 0.138344,1.17025 0.415039,1.54785 0.279945,0.37435 0.662432,0.56153 1.147461,0.56153 0.478512,0 0.857743,-0.1888 1.137695,-0.56641 0.279943,-0.3776 0.419917,-0.89192 0.419922,-1.54297 -5e-6,-0.64778 -0.139979,-1.16048 -0.419922,-1.53808 -0.279952,-0.38086 -0.659183,-0.57129 -1.137695,-0.57129 m 0,-0.76172 c 0.781246,0 1.394852,0.25391 1.84082,0.76172 0.445958,0.50781 0.66894,1.21094 0.668945,2.10937 -5e-6,0.89519 -0.222987,1.59831 -0.668945,2.10938 -0.445968,0.50781 -1.059574,0.76172 -1.84082,0.76172 -0.784508,0 -1.399742,-0.25391 -1.845704,-0.76172 -0.442709,-0.51107 -0.664063,-1.21419 -0.664062,-2.10938 -10e-7,-0.89843 0.221353,-1.60156 0.664062,-2.10937 0.445962,-0.50781 1.061196,-0.76172 1.845704,-0.76172"
|
||||
style="font-size:10px"
|
||||
id="path3199" />
|
||||
<path
|
||||
d="m 74.056084,377.81503 0,3.30078 -0.898438,0 0,-3.27148 c -4e-6,-0.51757 -0.100916,-0.90494 -0.302734,-1.16211 -0.201827,-0.25716 -0.504561,-0.38574 -0.908203,-0.38574 -0.485029,0 -0.867516,0.15463 -1.147461,0.46387 -0.27995,0.30924 -0.419924,0.73079 -0.419922,1.26464 l 0,3.09082 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.214842,-0.32877 0.46712,-0.57454 0.756836,-0.7373 0.292966,-0.16276 0.629879,-0.24414 1.010742,-0.24414 0.628251,0 1.103511,0.19532 1.425781,0.58594 0.322261,0.38737 0.483393,0.95866 0.483399,1.71386"
|
||||
style="font-size:10px"
|
||||
id="path3201" />
|
||||
<path
|
||||
d="m 79.456474,376.47714 0,-2.95898 0.898438,0 0,7.59765 -0.898438,0 0,-0.82031 c -0.188806,0.32552 -0.428064,0.56804 -0.717773,0.72754 -0.286462,0.15625 -0.631514,0.23438 -1.035156,0.23438 -0.66081,0 -1.199546,-0.26368 -1.616211,-0.79102 -0.413413,-0.52734 -0.620118,-1.2207 -0.620118,-2.08008 0,-0.85937 0.206705,-1.55273 0.620118,-2.08008 0.416665,-0.52733 0.955401,-0.79101 1.616211,-0.79101 0.403642,0 0.748694,0.0798 1.035156,0.23926 0.289709,0.15625 0.528967,0.39714 0.717773,0.72265 m -3.061523,1.90918 c -2e-6,0.66081 0.135089,1.18002 0.405273,1.55762 0.273436,0.37435 0.647784,0.56152 1.123047,0.56152 0.475257,0 0.849606,-0.18717 1.123047,-0.56152 0.273433,-0.3776 0.410152,-0.89681 0.410156,-1.55762 -4e-6,-0.6608 -0.136723,-1.17838 -0.410156,-1.55273 -0.273441,-0.3776 -0.64779,-0.5664 -1.123047,-0.56641 -0.475263,1e-5 -0.849611,0.18881 -1.123047,0.56641 -0.270184,0.37435 -0.405275,0.89193 -0.405273,1.55273"
|
||||
style="font-size:10px"
|
||||
id="path3203" />
|
||||
<path
|
||||
d="m 84.690849,378.36679 c -0.725914,0 -1.228843,0.083 -1.508789,0.24902 -0.279949,0.16602 -0.419923,0.44923 -0.419922,0.84961 -10e-7,0.31902 0.104165,0.57292 0.3125,0.76172 0.211587,0.18555 0.498045,0.27832 0.859375,0.27832 0.498044,0 0.896807,-0.17578 1.196289,-0.52734 0.302731,-0.35482 0.454098,-0.82519 0.454102,-1.41113 l 0,-0.2002 -0.893555,0 m 1.791992,-0.37109 0,3.12011 -0.898437,0 0,-0.83007 c -0.205082,0.33203 -0.460616,0.5778 -0.766602,0.7373 -0.305992,0.15625 -0.680341,0.23438 -1.123046,0.23438 -0.559898,0 -1.005861,-0.15625 -1.337891,-0.46875 -0.328777,-0.31576 -0.493165,-0.73731 -0.493164,-1.26465 -1e-6,-0.61523 0.205077,-1.0791 0.615234,-1.3916 0.41341,-0.3125 1.028644,-0.46875 1.845703,-0.46875 l 1.259766,0 0,-0.0879 c -4e-6,-0.41341 -0.136723,-0.73242 -0.410156,-0.95704 -0.270186,-0.22786 -0.651045,-0.34179 -1.142578,-0.34179 -0.312503,0 -0.616865,0.0374 -0.913086,0.1123 -0.296226,0.0749 -0.581056,0.18718 -0.854493,0.33692 l 0,-0.83008 c 0.328775,-0.12695 0.647785,-0.22135 0.957032,-0.28321 0.309242,-0.0651 0.610349,-0.0977 0.90332,-0.0977 0.791012,0 1.381832,0.20508 1.772461,0.61523 0.39062,0.41016 0.585932,1.03191 0.585937,1.86524"
|
||||
style="font-size:10px"
|
||||
id="path3205" />
|
||||
<path
|
||||
d="m 91.507256,376.48691 c -0.100916,-0.0586 -0.211593,-0.10091 -0.332032,-0.12696 -0.117191,-0.0293 -0.247399,-0.0439 -0.390625,-0.0439 -0.507815,0 -0.89844,0.16602 -1.171875,0.49805 -0.270184,0.32878 -0.405275,0.80241 -0.405273,1.42089 l 0,2.88086 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.1888,-0.33202 0.434568,-0.57779 0.737305,-0.7373 0.302731,-0.16276 0.670569,-0.24414 1.103515,-0.24414 0.06185,0 0.130205,0.005 0.205078,0.0147 0.07487,0.007 0.157874,0.0179 0.249024,0.0342 l 0.0049,0.92285"
|
||||
style="font-size:10px"
|
||||
id="path3207" />
|
||||
<path
|
||||
d="m 94.734795,381.62363 c -0.25391,0.65104 -0.501305,1.07584 -0.742188,1.27441 -0.240888,0.19857 -0.563153,0.29785 -0.966797,0.29785 l -0.717773,0 0,-0.75195 0.527344,0 c 0.247394,0 0.439451,-0.0586 0.576171,-0.17578 0.136717,-0.11719 0.288084,-0.39388 0.454102,-0.83008 l 0.161133,-0.41016 -2.211914,-5.38086 0.952148,0 1.708985,4.27735 1.708984,-4.27735 0.952148,0 -2.402343,5.97657"
|
||||
style="font-size:10px"
|
||||
id="path3209" />
|
||||
<path
|
||||
d="m 105.81878,376.69687 c 0.2246,-0.40364 0.49316,-0.70149 0.80566,-0.89356 0.3125,-0.19205 0.68033,-0.28808 1.10352,-0.28808 0.56965,0 1.00911,0.2002 1.31836,0.60058 0.30923,0.39714 0.46386,0.96355 0.46387,1.69922 l 0,3.30078 -0.90333,0 0,-3.27148 c 0,-0.52408 -0.0928,-0.91308 -0.27832,-1.16699 -0.18555,-0.2539 -0.46875,-0.38086 -0.8496,-0.38086 -0.46551,0 -0.83334,0.15463 -1.10352,0.46387 -0.27019,0.30924 -0.40528,0.73079 -0.40527,1.26464 l 0,3.09082 -0.90332,0 0,-3.27148 c -10e-6,-0.52734 -0.0928,-0.91634 -0.27832,-1.16699 -0.18556,-0.2539 -0.47201,-0.38086 -0.85938,-0.38086 -0.45899,0 -0.82357,0.15625 -1.09375,0.46875 -0.27018,0.30925 -0.40527,0.72917 -0.40527,1.25976 l 0,3.09082 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.20507,-0.33528 0.45084,-0.58267 0.7373,-0.74218 0.28646,-0.1595 0.62663,-0.23926 1.02051,-0.23926 0.39713,0 0.73404,0.10092 1.01074,0.30273 0.27994,0.20183 0.48665,0.4948 0.62012,0.87891"
|
||||
style="font-size:10px"
|
||||
id="path3211" />
|
||||
<path
|
||||
d="m 113.4262,376.27695 c -0.48177,0 -0.86263,0.1888 -1.14258,0.5664 -0.27995,0.37436 -0.41992,0.88868 -0.41992,1.54297 0,0.6543 0.13835,1.17025 0.41504,1.54785 0.27995,0.37435 0.66243,0.56153 1.14746,0.56153 0.47851,0 0.85774,-0.1888 1.1377,-0.56641 0.27994,-0.3776 0.41991,-0.89192 0.41992,-1.54297 -10e-6,-0.64778 -0.13998,-1.16048 -0.41992,-1.53808 -0.27996,-0.38086 -0.65919,-0.57129 -1.1377,-0.57129 m 0,-0.76172 c 0.78125,0 1.39485,0.25391 1.84082,0.76172 0.44596,0.50781 0.66894,1.21094 0.66895,2.10937 -1e-5,0.89519 -0.22299,1.59831 -0.66895,2.10938 -0.44597,0.50781 -1.05957,0.76172 -1.84082,0.76172 -0.78451,0 -1.39974,-0.25391 -1.8457,-0.76172 -0.44271,-0.51107 -0.66407,-1.21419 -0.66406,-2.10938 -10e-6,-0.89843 0.22135,-1.60156 0.66406,-2.10937 0.44596,-0.50781 1.06119,-0.76172 1.8457,-0.76172"
|
||||
style="font-size:10px"
|
||||
id="path3213" />
|
||||
<path
|
||||
d="m 121.96624,377.81503 0,3.30078 -0.89844,0 0,-3.27148 c 0,-0.51757 -0.10091,-0.90494 -0.30273,-1.16211 -0.20183,-0.25716 -0.50456,-0.38574 -0.90821,-0.38574 -0.48502,0 -0.86751,0.15463 -1.14746,0.46387 -0.27995,0.30924 -0.41992,0.73079 -0.41992,1.26464 l 0,3.09082 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.21484,-0.32877 0.46712,-0.57454 0.75684,-0.7373 0.29296,-0.16276 0.62988,-0.24414 1.01074,-0.24414 0.62825,0 1.10351,0.19532 1.42578,0.58594 0.32226,0.38737 0.48339,0.95866 0.4834,1.71386"
|
||||
style="font-size:10px"
|
||||
id="path3215" />
|
||||
<path
|
||||
d="m 123.768,375.64706 0.89844,0 0,5.46875 -0.89844,0 0,-5.46875 m 0,-2.1289 0.89844,0 0,1.13769 -0.89844,0 0,-1.13769"
|
||||
style="font-size:10px"
|
||||
id="path3217" />
|
||||
<path
|
||||
d="m 127.43011,374.09433 0,1.55273 1.85058,0 0,0.69825 -1.85058,0 0,2.96875 c 0,0.44596 0.0602,0.73242 0.18066,0.85937 0.1237,0.12696 0.37272,0.19043 0.74707,0.19043 l 0.92285,0 0,0.75195 -0.92285,0 c -0.69336,0 -1.17188,-0.12858 -1.43555,-0.38574 -0.26367,-0.26041 -0.3955,-0.73242 -0.3955,-1.41601 l 0,-2.96875 -0.65918,0 0,-0.69825 0.65918,0 0,-1.55273 0.90332,0"
|
||||
style="font-size:10px"
|
||||
id="path3219" />
|
||||
<path
|
||||
d="m 132.58636,376.27695 c -0.48178,0 -0.86264,0.1888 -1.14258,0.5664 -0.27995,0.37436 -0.41992,0.88868 -0.41992,1.54297 0,0.6543 0.13834,1.17025 0.41504,1.54785 0.27994,0.37435 0.66243,0.56153 1.14746,0.56153 0.47851,0 0.85774,-0.1888 1.13769,-0.56641 0.27995,-0.3776 0.41992,-0.89192 0.41992,-1.54297 0,-0.64778 -0.13997,-1.16048 -0.41992,-1.53808 -0.27995,-0.38086 -0.65918,-0.57129 -1.13769,-0.57129 m 0,-0.76172 c 0.78124,0 1.39485,0.25391 1.84082,0.76172 0.44596,0.50781 0.66894,1.21094 0.66894,2.10937 0,0.89519 -0.22298,1.59831 -0.66894,2.10938 -0.44597,0.50781 -1.05958,0.76172 -1.84082,0.76172 -0.78451,0 -1.39974,-0.25391 -1.84571,-0.76172 -0.44271,-0.51107 -0.66406,-1.21419 -0.66406,-2.10938 0,-0.89843 0.22135,-1.60156 0.66406,-2.10937 0.44597,-0.50781 1.0612,-0.76172 1.84571,-0.76172"
|
||||
style="font-size:10px"
|
||||
id="path3221" />
|
||||
<path
|
||||
d="m 139.74944,376.48691 c -0.10091,-0.0586 -0.21159,-0.10091 -0.33203,-0.12696 -0.11719,-0.0293 -0.2474,-0.0439 -0.39062,-0.0439 -0.50782,0 -0.89844,0.16602 -1.17188,0.49805 -0.27018,0.32878 -0.40527,0.80241 -0.40527,1.42089 l 0,2.88086 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.1888,-0.33202 0.43457,-0.57779 0.7373,-0.7373 0.30273,-0.16276 0.67057,-0.24414 1.10352,-0.24414 0.0618,0 0.1302,0.005 0.20508,0.0147 0.0749,0.007 0.15787,0.0179 0.24902,0.0342 l 0.005,0.92285"
|
||||
style="font-size:10px"
|
||||
id="path3223" />
|
||||
<path
|
||||
d="m 144.75433,380.2955 0,2.90039 -0.90332,0 0,-7.54883 0.90332,0 0,0.83008 c 0.1888,-0.32551 0.42643,-0.5664 0.71289,-0.72265 0.28971,-0.1595 0.63476,-0.23926 1.03515,-0.23926 0.66406,0 1.2028,0.26368 1.61621,0.79101 0.41666,0.52735 0.625,1.22071 0.625,2.08008 0,0.85938 -0.20834,1.55274 -0.625,2.08008 -0.41341,0.52734 -0.95215,0.79102 -1.61621,0.79102 -0.40039,0 -0.74544,-0.0781 -1.03515,-0.23438 -0.28646,-0.1595 -0.52409,-0.40202 -0.71289,-0.72754 m 3.05664,-1.90918 c -1e-5,-0.6608 -0.13673,-1.17838 -0.41016,-1.55273 -0.27019,-0.3776 -0.64291,-0.5664 -1.11816,-0.56641 -0.47527,1e-5 -0.84962,0.18881 -1.12305,0.56641 -0.27018,0.37435 -0.40528,0.89193 -0.40527,1.55273 -1e-5,0.66081 0.13509,1.18002 0.40527,1.55762 0.27343,0.37435 0.64778,0.56152 1.12305,0.56152 0.47525,0 0.84797,-0.18717 1.11816,-0.56152 0.27343,-0.3776 0.41015,-0.89681 0.41016,-1.55762"
|
||||
style="font-size:10px"
|
||||
id="path3225" />
|
||||
<path
|
||||
d="m 152.35198,376.27695 c -0.48177,0 -0.86263,0.1888 -1.14258,0.5664 -0.27995,0.37436 -0.41992,0.88868 -0.41992,1.54297 0,0.6543 0.13835,1.17025 0.41504,1.54785 0.27995,0.37435 0.66243,0.56153 1.14746,0.56153 0.47851,0 0.85775,-0.1888 1.1377,-0.56641 0.27994,-0.3776 0.41991,-0.89192 0.41992,-1.54297 -1e-5,-0.64778 -0.13998,-1.16048 -0.41992,-1.53808 -0.27995,-0.38086 -0.65919,-0.57129 -1.1377,-0.57129 m 0,-0.76172 c 0.78125,0 1.39485,0.25391 1.84082,0.76172 0.44596,0.50781 0.66894,1.21094 0.66895,2.10937 -1e-5,0.89519 -0.22299,1.59831 -0.66895,2.10938 -0.44597,0.50781 -1.05957,0.76172 -1.84082,0.76172 -0.78451,0 -1.39974,-0.25391 -1.8457,-0.76172 -0.44271,-0.51107 -0.66406,-1.21419 -0.66406,-2.10938 0,-0.89843 0.22135,-1.60156 0.66406,-2.10937 0.44596,-0.50781 1.06119,-0.76172 1.8457,-0.76172"
|
||||
style="font-size:10px"
|
||||
id="path3227" />
|
||||
<path
|
||||
d="m 159.83245,375.8082 0,0.84961 c -0.25391,-0.13021 -0.51758,-0.22786 -0.79101,-0.29297 -0.27345,-0.0651 -0.55665,-0.0976 -0.84961,-0.0977 -0.44597,1e-5 -0.78126,0.0684 -1.00586,0.20508 -0.22136,0.13672 -0.33204,0.3418 -0.33203,0.61523 -1e-5,0.20834 0.0798,0.37273 0.23925,0.49317 0.15951,0.11719 0.48014,0.22949 0.96192,0.33691 l 0.30761,0.0684 c 0.63802,0.13672 1.0905,0.33041 1.35743,0.58106 0.27017,0.24739 0.40526,0.59407 0.40527,1.04004 -1e-5,0.50781 -0.20183,0.90983 -0.60547,1.20605 -0.40039,0.29622 -0.95215,0.44434 -1.65527,0.44434 -0.29297,0 -0.59896,-0.0293 -0.91797,-0.0879 -0.31576,-0.0553 -0.64942,-0.13998 -1.00098,-0.25391 l 0,-0.92774 c 0.33203,0.17253 0.65918,0.30274 0.98145,0.39063 0.32226,0.0846 0.64127,0.12695 0.95703,0.12695 0.42317,0 0.74869,-0.0716 0.97656,-0.21484 0.22786,-0.14648 0.34179,-0.35156 0.3418,-0.61524 -1e-5,-0.24413 -0.083,-0.43131 -0.24903,-0.56152 -0.16276,-0.13021 -0.52246,-0.25553 -1.0791,-0.37598 l -0.3125,-0.0732 c -0.55664,-0.11718 -0.95866,-0.29622 -1.20605,-0.53711 -0.2474,-0.24413 -0.3711,-0.57779 -0.3711,-1.00097 0,-0.51432 0.1823,-0.91146 0.54688,-1.19141 0.36458,-0.27994 0.88216,-0.41992 1.55273,-0.41992 0.33203,0 0.64453,0.0244 0.9375,0.0732 0.29297,0.0488 0.56315,0.12208 0.81055,0.21973"
|
||||
style="font-size:10px"
|
||||
id="path3229" />
|
||||
<path
|
||||
d="m 161.56097,375.64706 0.89843,0 0,5.46875 -0.89843,0 0,-5.46875 m 0,-2.1289 0.89843,0 0,1.13769 -0.89843,0 0,-1.13769"
|
||||
style="font-size:10px"
|
||||
id="path3231" />
|
||||
<path
|
||||
d="m 165.22308,374.09433 0,1.55273 1.85058,0 0,0.69825 -1.85058,0 0,2.96875 c -1e-5,0.44596 0.0602,0.73242 0.18066,0.85937 0.1237,0.12696 0.37272,0.19043 0.74707,0.19043 l 0.92285,0 0,0.75195 -0.92285,0 c -0.69336,0 -1.17188,-0.12858 -1.43555,-0.38574 -0.26367,-0.26041 -0.39551,-0.73242 -0.3955,-1.41601 l 0,-2.96875 -0.65918,0 0,-0.69825 0.65918,0 0,-1.55273 0.90332,0"
|
||||
style="font-size:10px"
|
||||
id="path3233" />
|
||||
<path
|
||||
d="m 168.26019,375.64706 0.89843,0 0,5.46875 -0.89843,0 0,-5.46875 m 0,-2.1289 0.89843,0 0,1.13769 -0.89843,0 0,-1.13769"
|
||||
style="font-size:10px"
|
||||
id="path3235" />
|
||||
<path
|
||||
d="m 173.15276,376.27695 c -0.48177,0 -0.86263,0.1888 -1.14257,0.5664 -0.27995,0.37436 -0.41993,0.88868 -0.41993,1.54297 0,0.6543 0.13835,1.17025 0.41504,1.54785 0.27995,0.37435 0.66243,0.56153 1.14746,0.56153 0.47852,0 0.85775,-0.1888 1.1377,-0.56641 0.27994,-0.3776 0.41992,-0.89192 0.41992,-1.54297 0,-0.64778 -0.13998,-1.16048 -0.41992,-1.53808 -0.27995,-0.38086 -0.65918,-0.57129 -1.1377,-0.57129 m 0,-0.76172 c 0.78125,0 1.39486,0.25391 1.84082,0.76172 0.44596,0.50781 0.66894,1.21094 0.66895,2.10937 -1e-5,0.89519 -0.22299,1.59831 -0.66895,2.10938 -0.44596,0.50781 -1.05957,0.76172 -1.84082,0.76172 -0.7845,0 -1.39974,-0.25391 -1.8457,-0.76172 -0.44271,-0.51107 -0.66406,-1.21419 -0.66406,-2.10938 0,-0.89843 0.22135,-1.60156 0.66406,-2.10937 0.44596,-0.50781 1.0612,-0.76172 1.8457,-0.76172"
|
||||
style="font-size:10px"
|
||||
id="path3237" />
|
||||
<path
|
||||
d="m 181.6928,377.81503 0,3.30078 -0.89844,0 0,-3.27148 c 0,-0.51757 -0.10091,-0.90494 -0.30273,-1.16211 -0.20183,-0.25716 -0.50456,-0.38574 -0.9082,-0.38574 -0.48503,0 -0.86752,0.15463 -1.14746,0.46387 -0.27995,0.30924 -0.41993,0.73079 -0.41993,1.26464 l 0,3.09082 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.21485,-0.32877 0.46712,-0.57454 0.75684,-0.7373 0.29297,-0.16276 0.62988,-0.24414 1.01074,-0.24414 0.62825,0 1.10351,0.19532 1.42578,0.58594 0.32226,0.38737 0.4834,0.95866 0.4834,1.71386"
|
||||
style="font-size:10px"
|
||||
id="path3239" />
|
||||
</g>
|
||||
<g
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
id="text3826">
|
||||
<path
|
||||
d="m 172.22728,456.1171 0,1.04004 c -0.33204,-0.30924 -0.68686,-0.54036 -1.06445,-0.69336 -0.37436,-0.15299 -0.77312,-0.22949 -1.19629,-0.2295 -0.83334,10e-6 -1.47136,0.25554 -1.91407,0.76661 -0.44271,0.50781 -0.66406,1.24349 -0.66406,2.20703 0,0.96029 0.22135,1.69596 0.66406,2.20703 0.44271,0.50781 1.08073,0.76172 1.91407,0.76172 0.42317,0 0.82193,-0.0765 1.19629,-0.2295 0.37759,-0.15299 0.73241,-0.38411 1.06445,-0.69336 l 0,1.03028 c -0.34506,0.23437 -0.71127,0.41015 -1.09863,0.52734 -0.38412,0.11719 -0.79102,0.17578 -1.22071,0.17578 -1.10351,0 -1.97265,-0.33691 -2.60742,-1.01074 -0.63476,-0.67708 -0.95215,-1.59993 -0.95215,-2.76855 0,-1.17187 0.31739,-2.09472 0.95215,-2.76856 0.63477,-0.67707 1.50391,-1.01562 2.60742,-1.01562 0.4362,0 0.84635,0.0586 1.23047,0.17578 0.38737,0.11394 0.75032,0.28646 1.08887,0.51758"
|
||||
style="font-size:10px"
|
||||
id="path3108" />
|
||||
<path
|
||||
d="m 173.72142,455.24796 0.89844,0 0,7.59765 -0.89844,0 0,-7.59765"
|
||||
style="font-size:10px"
|
||||
id="path3110" />
|
||||
<path
|
||||
d="m 176.49486,457.37686 0.89844,0 0,5.46875 -0.89844,0 0,-5.46875 m 0,-2.1289 0.89844,0 0,1.13769 -0.89844,0 0,-1.13769"
|
||||
style="font-size:10px"
|
||||
id="path3112" />
|
||||
<path
|
||||
d="m 183.94603,459.88663 0,0.43945 -4.13086,0 c 0.0391,0.61849 0.22461,1.0905 0.55664,1.41602 0.33528,0.32226 0.80078,0.4834 1.39649,0.48339 0.34504,1e-5 0.6787,-0.0423 1.00097,-0.12695 0.32552,-0.0846 0.64778,-0.21159 0.9668,-0.38086 l 0,0.84961 c -0.32227,0.13672 -0.65268,0.24089 -0.99121,0.3125 -0.33855,0.0716 -0.68197,0.10742 -1.03028,0.10742 -0.87239,0 -1.56413,-0.2539 -2.07519,-0.76172 -0.50781,-0.50781 -0.76172,-1.19466 -0.76172,-2.06054 0,-0.89518 0.24088,-1.60482 0.72266,-2.12891 0.48502,-0.52734 1.13769,-0.79101 1.958,-0.79101 0.73568,0 1.31673,0.23763 1.74317,0.71289 0.42968,0.47201 0.64452,1.11491 0.64453,1.92871 m -0.89844,-0.26367 c -0.007,-0.49154 -0.14486,-0.88379 -0.41504,-1.17676 -0.26693,-0.29297 -0.62175,-0.43945 -1.06445,-0.43946 -0.5013,1e-5 -0.90332,0.14161 -1.20605,0.42481 -0.29949,0.28321 -0.47201,0.68197 -0.51758,1.19629 l 3.20312,-0.005"
|
||||
style="font-size:10px"
|
||||
id="path3114" />
|
||||
<path
|
||||
d="m 189.96654,459.54483 0,3.30078 -0.89844,0 0,-3.27148 c 0,-0.51758 -0.10092,-0.90495 -0.30273,-1.16211 -0.20183,-0.25716 -0.50457,-0.38574 -0.90821,-0.38574 -0.48503,0 -0.86751,0.15462 -1.14746,0.46386 -0.27995,0.30925 -0.41992,0.7308 -0.41992,1.26465 l 0,3.09082 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.21484,-0.32877 0.46712,-0.57454 0.75684,-0.7373 0.29296,-0.16276 0.62988,-0.24414 1.01074,-0.24414 0.62825,0 1.10351,0.19531 1.42578,0.58593 0.32226,0.38738 0.48339,0.95867 0.4834,1.71387"
|
||||
style="font-size:10px"
|
||||
id="path3116" />
|
||||
<path
|
||||
d="m 192.65697,455.82413 0,1.55273 1.85058,0 0,0.69824 -1.85058,0 0,2.96875 c 0,0.44597 0.0602,0.73243 0.18066,0.85938 0.1237,0.12695 0.37272,0.19043 0.74707,0.19043 l 0.92285,0 0,0.75195 -0.92285,0 c -0.69336,0 -1.17188,-0.12858 -1.43555,-0.38574 -0.26367,-0.26042 -0.3955,-0.73242 -0.3955,-1.41602 l 0,-2.96875 -0.65918,0 0,-0.69824 0.65918,0 0,-1.55273 0.90332,0"
|
||||
style="font-size:10px"
|
||||
id="path3118" />
|
||||
<path
|
||||
d="m 201.36302,460.09659 c -0.72591,0 -1.22884,0.083 -1.50879,0.24902 -0.27995,0.16602 -0.41992,0.44922 -0.41992,0.84961 0,0.31901 0.10417,0.57292 0.3125,0.76172 0.21159,0.18555 0.49805,0.27832 0.85938,0.27832 0.49804,0 0.8968,-0.17578 1.19628,-0.52734 0.30274,-0.35482 0.4541,-0.8252 0.45411,-1.41114 l 0,-0.20019 -0.89356,0 m 1.79199,-0.3711 0,3.12012 -0.89843,0 0,-0.83008 c -0.20509,0.33204 -0.46062,0.5778 -0.76661,0.73731 -0.30599,0.15625 -0.68034,0.23437 -1.12304,0.23437 -0.5599,0 -1.00586,-0.15625 -1.33789,-0.46875 -0.32878,-0.31575 -0.49317,-0.7373 -0.49317,-1.26465 0,-0.61523 0.20508,-1.07909 0.61524,-1.3916 0.41341,-0.31249 1.02864,-0.46874 1.8457,-0.46875 l 1.25977,0 0,-0.0879 c -1e-5,-0.4134 -0.13673,-0.73242 -0.41016,-0.95703 -0.27019,-0.22786 -0.65104,-0.34179 -1.14258,-0.3418 -0.3125,1e-5 -0.61686,0.0374 -0.91308,0.11231 -0.29623,0.0749 -0.58106,0.18718 -0.8545,0.33691 l 0,-0.83007 c 0.32878,-0.12695 0.64779,-0.22135 0.95704,-0.28321 0.30924,-0.0651 0.61034,-0.0976 0.90332,-0.0976 0.79101,0 1.38183,0.20508 1.77246,0.61523 0.39062,0.41016 0.58593,1.03191 0.58593,1.86523"
|
||||
style="font-size:10px"
|
||||
id="path3120" />
|
||||
<path
|
||||
d="m 208.17943,458.21671 c -0.10092,-0.0586 -0.21159,-0.10091 -0.33203,-0.12696 -0.11719,-0.0293 -0.2474,-0.0439 -0.39063,-0.0439 -0.50781,0 -0.89844,0.16602 -1.17187,0.49804 -0.27019,0.32878 -0.40528,0.80242 -0.40528,1.4209 l 0,2.88086 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.1888,-0.33203 0.43457,-0.57779 0.73731,-0.7373 0.30273,-0.16276 0.67057,-0.24414 1.10351,-0.24414 0.0618,0 0.13021,0.005 0.20508,0.0146 0.0749,0.007 0.15788,0.0179 0.24903,0.0342 l 0.005,0.92286"
|
||||
style="font-size:10px"
|
||||
id="path3122" />
|
||||
<path
|
||||
d="m 213.59447,459.88663 0,0.43945 -4.13086,0 c 0.0391,0.61849 0.22461,1.0905 0.55664,1.41602 0.33528,0.32226 0.80078,0.4834 1.39648,0.48339 0.34505,1e-5 0.67871,-0.0423 1.00098,-0.12695 0.32552,-0.0846 0.64778,-0.21159 0.9668,-0.38086 l 0,0.84961 c -0.32227,0.13672 -0.65268,0.24089 -0.99121,0.3125 -0.33855,0.0716 -0.68197,0.10742 -1.03028,0.10742 -0.8724,0 -1.56413,-0.2539 -2.07519,-0.76172 -0.50782,-0.50781 -0.76172,-1.19466 -0.76172,-2.06054 0,-0.89518 0.24088,-1.60482 0.72265,-2.12891 0.48503,-0.52734 1.1377,-0.79101 1.95801,-0.79101 0.73567,0 1.31673,0.23763 1.74317,0.71289 0.42968,0.47201 0.64452,1.11491 0.64453,1.92871 m -0.89844,-0.26367 c -0.007,-0.49154 -0.14486,-0.88379 -0.41504,-1.17676 -0.26693,-0.29297 -0.62175,-0.43945 -1.06445,-0.43946 -0.50131,1e-5 -0.90333,0.14161 -1.20606,0.42481 -0.29948,0.28321 -0.472,0.68197 -0.51758,1.19629 l 3.20313,-0.005"
|
||||
style="font-size:10px"
|
||||
id="path3124" />
|
||||
<path
|
||||
d="m 217.55443,460.09659 c -0.72592,0 -1.22885,0.083 -1.50879,0.24902 -0.27995,0.16602 -0.41992,0.44922 -0.41992,0.84961 0,0.31901 0.10416,0.57292 0.3125,0.76172 0.21158,0.18555 0.49804,0.27832 0.85937,0.27832 0.49805,0 0.89681,-0.17578 1.19629,-0.52734 0.30273,-0.35482 0.4541,-0.8252 0.4541,-1.41114 l 0,-0.20019 -0.89355,0 m 1.79199,-0.3711 0,3.12012 -0.89844,0 0,-0.83008 c -0.20508,0.33204 -0.46061,0.5778 -0.7666,0.73731 -0.30599,0.15625 -0.68034,0.23437 -1.12305,0.23437 -0.55989,0 -1.00586,-0.15625 -1.33789,-0.46875 -0.32877,-0.31575 -0.49316,-0.7373 -0.49316,-1.26465 0,-0.61523 0.20508,-1.07909 0.61523,-1.3916 0.41341,-0.31249 1.02865,-0.46874 1.84571,-0.46875 l 1.25976,0 0,-0.0879 c 0,-0.4134 -0.13672,-0.73242 -0.41015,-0.95703 -0.27019,-0.22786 -0.65105,-0.34179 -1.14258,-0.3418 -0.3125,1e-5 -0.61687,0.0374 -0.91309,0.11231 -0.29622,0.0749 -0.58105,0.18718 -0.85449,0.33691 l 0,-0.83007 c 0.32877,-0.12695 0.64779,-0.22135 0.95703,-0.28321 0.30924,-0.0651 0.61035,-0.0976 0.90332,-0.0976 0.79101,0 1.38183,0.20508 1.77246,0.61523 0.39062,0.41016 0.58594,1.03191 0.58594,1.86523"
|
||||
style="font-size:10px"
|
||||
id="path3126" />
|
||||
<path
|
||||
d="m 226.50462,458.00674 c -0.48177,1e-5 -0.86263,0.18881 -1.14257,0.56641 -0.27995,0.37435 -0.41993,0.88868 -0.41993,1.54297 0,0.6543 0.13835,1.17025 0.41504,1.54785 0.27995,0.37435 0.66243,0.56153 1.14746,0.56152 0.47852,1e-5 0.85775,-0.1888 1.1377,-0.5664 0.27994,-0.3776 0.41992,-0.89193 0.41992,-1.54297 0,-0.64778 -0.13998,-1.16048 -0.41992,-1.53809 -0.27995,-0.38085 -0.65918,-0.57128 -1.1377,-0.57129 m 0,-0.76171 c 0.78125,0 1.39486,0.25391 1.84082,0.76171 0.44596,0.50782 0.66894,1.21095 0.66895,2.10938 -1e-5,0.89518 -0.22299,1.59831 -0.66895,2.10937 -0.44596,0.50782 -1.05957,0.76172 -1.84082,0.76172 -0.7845,0 -1.39974,-0.2539 -1.8457,-0.76172 -0.44271,-0.51106 -0.66406,-1.21419 -0.66406,-2.10937 0,-0.89843 0.22135,-1.60156 0.66406,-2.10938 0.44596,-0.5078 1.0612,-0.76171 1.8457,-0.76171"
|
||||
style="font-size:10px"
|
||||
id="path3128" />
|
||||
<path
|
||||
d="m 233.66771,458.21671 c -0.10092,-0.0586 -0.21159,-0.10091 -0.33203,-0.12696 -0.11719,-0.0293 -0.2474,-0.0439 -0.39063,-0.0439 -0.50781,0 -0.89844,0.16602 -1.17187,0.49804 -0.27019,0.32878 -0.40528,0.80242 -0.40528,1.4209 l 0,2.88086 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.1888,-0.33203 0.43457,-0.57779 0.73731,-0.7373 0.30273,-0.16276 0.67057,-0.24414 1.10351,-0.24414 0.0618,0 0.13021,0.005 0.20508,0.0146 0.0749,0.007 0.15788,0.0179 0.24903,0.0342 l 0.005,0.92286"
|
||||
style="font-size:10px"
|
||||
id="path3130" />
|
||||
<path
|
||||
d="m 234.61986,457.37686 0.89844,0 0,5.46875 -0.89844,0 0,-5.46875 m 0,-2.1289 0.89844,0 0,1.13769 -0.89844,0 0,-1.13769"
|
||||
style="font-size:10px"
|
||||
id="path3132" />
|
||||
<path
|
||||
d="m 240.99193,460.04776 c -1e-5,-0.65104 -0.1351,-1.15559 -0.40528,-1.51367 -0.26693,-0.35807 -0.6429,-0.53711 -1.12793,-0.53711 -0.48177,0 -0.85774,0.17904 -1.12792,0.53711 -0.26693,0.35808 -0.4004,0.86263 -0.4004,1.51367 0,0.64779 0.13347,1.15072 0.4004,1.50879 0.27018,0.35807 0.64615,0.53711 1.12792,0.53711 0.48503,0 0.861,-0.17904 1.12793,-0.53711 0.27018,-0.35807 0.40527,-0.861 0.40528,-1.50879 m 0.89844,2.11914 c -1e-5,0.93099 -0.20672,1.62272 -0.62012,2.0752 -0.41342,0.45572 -1.04655,0.68359 -1.89942,0.68359 -0.31575,0 -0.6136,-0.0244 -0.89355,-0.0732 -0.27995,-0.0456 -0.55176,-0.11719 -0.81543,-0.21485 l 0,-0.87402 c 0.26367,0.14323 0.52409,0.24902 0.78125,0.31738 0.25716,0.0684 0.5192,0.10254 0.78613,0.10254 0.58919,0 1.03027,-0.15462 1.32324,-0.46386 0.29297,-0.306 0.43945,-0.76986 0.43946,-1.39161 l 0,-0.44433 c -0.18555,0.32226 -0.42318,0.56315 -0.71289,0.72265 -0.28972,0.15951 -0.6364,0.23926 -1.04004,0.23926 -0.67058,0 -1.21094,-0.25553 -1.6211,-0.7666 -0.41015,-0.51107 -0.61523,-1.18815 -0.61523,-2.03125 0,-0.84635 0.20508,-1.52506 0.61523,-2.03613 0.41016,-0.51107 0.95052,-0.7666 1.6211,-0.7666 0.40364,0 0.75032,0.0797 1.04004,0.23925 0.28971,0.15951 0.52734,0.4004 0.71289,0.72266 l 0,-0.83008 0.89844,0 0,4.79004"
|
||||
style="font-size:10px"
|
||||
id="path3134" />
|
||||
<path
|
||||
d="m 243.74095,457.37686 0.89844,0 0,5.46875 -0.89844,0 0,-5.46875 m 0,-2.1289 0.89844,0 0,1.13769 -0.89844,0 0,-1.13769"
|
||||
style="font-size:10px"
|
||||
id="path3136" />
|
||||
<path
|
||||
d="m 251.06029,459.54483 0,3.30078 -0.89844,0 0,-3.27148 c 0,-0.51758 -0.10092,-0.90495 -0.30273,-1.16211 -0.20183,-0.25716 -0.50457,-0.38574 -0.90821,-0.38574 -0.48503,0 -0.86751,0.15462 -1.14746,0.46386 -0.27995,0.30925 -0.41992,0.7308 -0.41992,1.26465 l 0,3.09082 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.21484,-0.32877 0.46712,-0.57454 0.75684,-0.7373 0.29296,-0.16276 0.62988,-0.24414 1.01074,-0.24414 0.62825,0 1.10351,0.19531 1.42578,0.58593 0.32226,0.38738 0.48339,0.95867 0.4834,1.71387"
|
||||
style="font-size:10px"
|
||||
id="path3138" />
|
||||
</g>
|
||||
<g
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
id="text3017">
|
||||
<path
|
||||
d="m 367.17007,356.71783 -2.7832,-7.29003 1.03027,0 2.30958,6.13769 2.31445,-6.13769 1.02539,0 -2.77832,7.29003 -1.11817,0"
|
||||
style="font-size:10px"
|
||||
id="path3242" />
|
||||
<path
|
||||
d="m 371.87222,351.24908 0.89844,0 0,5.46875 -0.89844,0 0,-5.46875 m 0,-2.1289 0.89844,0 0,1.13769 -0.89844,0 0,-1.13769"
|
||||
style="font-size:10px"
|
||||
id="path3244" />
|
||||
<path
|
||||
d="m 377.81461,352.08893 c -0.10092,-0.0586 -0.2116,-0.10091 -0.33204,-0.12695 -0.11719,-0.0293 -0.24739,-0.0439 -0.39062,-0.0439 -0.50782,0 -0.89844,0.16602 -1.17188,0.49805 -0.27018,0.32878 -0.40527,0.80241 -0.40527,1.4209 l 0,2.88085 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.1888,-0.33202 0.43457,-0.57779 0.73731,-0.7373 0.30273,-0.16276 0.67057,-0.24414 1.10351,-0.24414 0.0618,0 0.13021,0.005 0.20508,0.0146 0.0749,0.007 0.15787,0.0179 0.24902,0.0342 l 0.005,0.92285"
|
||||
style="font-size:10px"
|
||||
id="path3246" />
|
||||
<path
|
||||
d="m 379.65543,349.69635 0,1.55273 1.85058,0 0,0.69825 -1.85058,0 0,2.96875 c -1e-5,0.44596 0.0602,0.73242 0.18066,0.85937 0.1237,0.12696 0.37272,0.19043 0.74707,0.19043 l 0.92285,0 0,0.75195 -0.92285,0 c -0.69336,0 -1.17188,-0.12858 -1.43555,-0.38574 -0.26367,-0.26041 -0.39551,-0.73242 -0.3955,-1.41601 l 0,-2.96875 -0.65918,0 0,-0.69825 0.65918,0 0,-1.55273 0.90332,0"
|
||||
style="font-size:10px"
|
||||
id="path3248" />
|
||||
<path
|
||||
d="m 382.59976,354.55963 0,-3.31055 0.89844,0 0,3.27637 c 0,0.51758 0.10091,0.90658 0.30273,1.16699 0.20182,0.25717 0.50456,0.38575 0.90821,0.38575 0.48502,0 0.86751,-0.15463 1.14746,-0.46387 0.2832,-0.30924 0.4248,-0.73079 0.4248,-1.26465 l 0,-3.10059 0.89844,0 0,5.46875 -0.89844,0 0,-0.83984 c -0.2181,0.33203 -0.47201,0.57943 -0.76172,0.74219 -0.28646,0.1595 -0.62012,0.23926 -1.00097,0.23926 -0.62826,0 -1.10515,-0.19532 -1.43067,-0.58594 -0.32552,-0.39063 -0.48828,-0.96191 -0.48828,-1.71387 m 2.26074,-3.44238 0,0"
|
||||
style="font-size:10px"
|
||||
id="path3250" />
|
||||
<path
|
||||
d="m 391.52554,353.96881 c -0.72591,0 -1.22884,0.083 -1.50879,0.24902 -0.27995,0.16602 -0.41992,0.44923 -0.41992,0.84961 0,0.31902 0.10417,0.57292 0.3125,0.76172 0.21159,0.18555 0.49805,0.27832 0.85938,0.27832 0.49804,0 0.8968,-0.17578 1.19629,-0.52734 0.30273,-0.35482 0.45409,-0.82519 0.4541,-1.41113 l 0,-0.2002 -0.89356,0 m 1.792,-0.37109 0,3.12011 -0.89844,0 0,-0.83007 c -0.20508,0.33203 -0.46062,0.5778 -0.7666,0.7373 -0.306,0.15625 -0.68035,0.23438 -1.12305,0.23438 -0.5599,0 -1.00586,-0.15625 -1.33789,-0.46875 -0.32878,-0.31576 -0.49317,-0.73731 -0.49317,-1.26465 0,-0.61523 0.20508,-1.0791 0.61524,-1.3916 0.41341,-0.3125 1.02864,-0.46875 1.8457,-0.46875 l 1.25977,0 0,-0.0879 c -1e-5,-0.41341 -0.13673,-0.73242 -0.41016,-0.95704 -0.27018,-0.22786 -0.65104,-0.34179 -1.14258,-0.34179 -0.3125,0 -0.61686,0.0374 -0.91308,0.1123 -0.29623,0.0749 -0.58106,0.18718 -0.85449,0.33692 l 0,-0.83008 c 0.32877,-0.12695 0.64778,-0.22135 0.95703,-0.28321 0.30924,-0.0651 0.61035,-0.0976 0.90332,-0.0976 0.79101,0 1.38183,0.20508 1.77246,0.61523 0.39062,0.41016 0.58593,1.03191 0.58594,1.86524"
|
||||
style="font-size:10px"
|
||||
id="path3252" />
|
||||
<path
|
||||
d="m 395.173,349.12018 0.89844,0 0,7.59765 -0.89844,0 0,-7.59765"
|
||||
style="font-size:10px"
|
||||
id="path3254" />
|
||||
<path
|
||||
d="m 404.61636,351.41022 0,0.84961 c -0.25391,-0.13021 -0.51758,-0.22786 -0.79101,-0.29297 -0.27344,-0.0651 -0.55665,-0.0976 -0.84961,-0.0977 -0.44597,1e-5 -0.78125,0.0684 -1.00586,0.20508 -0.22136,0.13672 -0.33203,0.3418 -0.33203,0.61523 0,0.20834 0.0797,0.37273 0.23926,0.49317 0.1595,0.11719 0.48014,0.22949 0.96191,0.33691 l 0.30762,0.0684 c 0.63801,0.13672 1.09049,0.33041 1.35742,0.58106 0.27018,0.24739 0.40527,0.59407 0.40527,1.04004 0,0.50781 -0.20183,0.90983 -0.60547,1.20605 -0.40039,0.29622 -0.95215,0.44434 -1.65527,0.44434 -0.29297,0 -0.59896,-0.0293 -0.91797,-0.0879 -0.31576,-0.0553 -0.64941,-0.13998 -1.00098,-0.25391 l 0,-0.92774 c 0.33204,0.17253 0.65918,0.30274 0.98145,0.39063 0.32226,0.0846 0.64127,0.12695 0.95703,0.12695 0.42318,0 0.7487,-0.0716 0.97656,-0.21484 0.22786,-0.14648 0.3418,-0.35156 0.3418,-0.61524 0,-0.24413 -0.083,-0.43131 -0.24902,-0.56152 -0.16277,-0.1302 -0.52247,-0.25553 -1.0791,-0.37598 l -0.3125,-0.0732 c -0.55665,-0.11718 -0.95866,-0.29622 -1.20606,-0.53711 -0.2474,-0.24413 -0.37109,-0.57779 -0.37109,-1.00097 0,-0.51432 0.18229,-0.91146 0.54687,-1.19141 0.36458,-0.27994 0.88216,-0.41992 1.55274,-0.41992 0.33202,0 0.64452,0.0244 0.9375,0.0732 0.29296,0.0488 0.56314,0.12208 0.81054,0.21973"
|
||||
style="font-size:10px"
|
||||
id="path3256" />
|
||||
<path
|
||||
d="m 410.28043,351.45905 0,0.83984 c -0.25391,-0.13997 -0.50945,-0.24414 -0.76661,-0.3125 -0.25391,-0.0716 -0.51107,-0.10742 -0.77148,-0.10742 -0.58268,0 -1.03516,0.18555 -1.35742,0.55664 -0.32227,0.36784 -0.4834,0.88542 -0.4834,1.55273 0,0.66732 0.16113,1.18653 0.4834,1.55762 0.32226,0.36784 0.77474,0.55176 1.35742,0.55176 0.26041,0 0.51757,-0.0342 0.77148,-0.10254 0.25716,-0.0716 0.5127,-0.17741 0.76661,-0.31738 l 0,0.83007 c -0.25066,0.11719 -0.51108,0.20508 -0.78125,0.26368 -0.26693,0.0586 -0.55177,0.0879 -0.8545,0.0879 -0.82357,0 -1.47786,-0.25879 -1.96289,-0.77637 -0.48502,-0.51758 -0.72754,-1.21582 -0.72754,-2.09473 0,-0.89192 0.24414,-1.59342 0.73243,-2.10449 0.49153,-0.51106 1.16373,-0.7666 2.0166,-0.7666 0.27669,0 0.54687,0.0293 0.81054,0.0879 0.26367,0.0553 0.51921,0.13998 0.76661,0.25391"
|
||||
style="font-size:10px"
|
||||
id="path3258" />
|
||||
<path
|
||||
d="m 415.02164,352.08893 c -0.10092,-0.0586 -0.2116,-0.10091 -0.33203,-0.12695 -0.1172,-0.0293 -0.2474,-0.0439 -0.39063,-0.0439 -0.50781,0 -0.89844,0.16602 -1.17187,0.49805 -0.27019,0.32878 -0.40528,0.80241 -0.40528,1.4209 l 0,2.88085 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.1888,-0.33202 0.43457,-0.57779 0.73731,-0.7373 0.30273,-0.16276 0.67057,-0.24414 1.10351,-0.24414 0.0618,0 0.13021,0.005 0.20508,0.0146 0.0749,0.007 0.15787,0.0179 0.24902,0.0342 l 0.005,0.92285"
|
||||
style="font-size:10px"
|
||||
id="path3260" />
|
||||
<path
|
||||
d="m 420.43668,353.75885 0,0.43945 -4.13086,0 c 0.0391,0.61849 0.2246,1.0905 0.55664,1.41602 0.33528,0.32227 0.80078,0.4834 1.39648,0.4834 0.34505,0 0.67871,-0.0423 1.00098,-0.12696 0.32551,-0.0846 0.64778,-0.21158 0.9668,-0.38086 l 0,0.84961 c -0.32228,0.13672 -0.65268,0.24089 -0.99122,0.3125 -0.33854,0.0716 -0.68197,0.10743 -1.03027,0.10743 -0.8724,0 -1.56413,-0.25391 -2.07519,-0.76172 -0.50782,-0.50781 -0.76172,-1.19466 -0.76172,-2.06055 0,-0.89518 0.24088,-1.60481 0.72265,-2.12891 0.48503,-0.52733 1.1377,-0.79101 1.95801,-0.79101 0.73567,0 1.31673,0.23763 1.74316,0.71289 0.42969,0.47201 0.64453,1.11491 0.64454,1.92871 m -0.89844,-0.26367 c -0.007,-0.49153 -0.14486,-0.88379 -0.41504,-1.17676 -0.26693,-0.29296 -0.62175,-0.43945 -1.06445,-0.43945 -0.50131,0 -0.90333,0.1416 -1.20606,0.4248 -0.29948,0.28321 -0.47201,0.68197 -0.51758,1.19629 l 3.20313,-0.005"
|
||||
style="font-size:10px"
|
||||
id="path3262" />
|
||||
<path
|
||||
d="m 426.58902,353.75885 0,0.43945 -4.13086,0 c 0.0391,0.61849 0.22461,1.0905 0.55664,1.41602 0.33529,0.32227 0.80078,0.4834 1.39649,0.4834 0.34504,0 0.6787,-0.0423 1.00097,-0.12696 0.32552,-0.0846 0.64778,-0.21158 0.9668,-0.38086 l 0,0.84961 c -0.32227,0.13672 -0.65268,0.24089 -0.99121,0.3125 -0.33855,0.0716 -0.68197,0.10743 -1.03028,0.10743 -0.87239,0 -1.56412,-0.25391 -2.07519,-0.76172 -0.50781,-0.50781 -0.76172,-1.19466 -0.76172,-2.06055 0,-0.89518 0.24089,-1.60481 0.72266,-2.12891 0.48502,-0.52733 1.13769,-0.79101 1.958,-0.79101 0.73568,0 1.31673,0.23763 1.74317,0.71289 0.42968,0.47201 0.64452,1.11491 0.64453,1.92871 m -0.89844,-0.26367 c -0.007,-0.49153 -0.14486,-0.88379 -0.41504,-1.17676 -0.26693,-0.29296 -0.62175,-0.43945 -1.06445,-0.43945 -0.5013,0 -0.90332,0.1416 -1.20605,0.4248 -0.29949,0.28321 -0.47201,0.68197 -0.51758,1.19629 l 3.20312,-0.005"
|
||||
style="font-size:10px"
|
||||
id="path3264" />
|
||||
<path
|
||||
d="m 432.60953,353.41705 0,3.30078 -0.89844,0 0,-3.27148 c 0,-0.51757 -0.10092,-0.90494 -0.30273,-1.16211 -0.20183,-0.25716 -0.50457,-0.38574 -0.90821,-0.38574 -0.48503,0 -0.86751,0.15463 -1.14746,0.46387 -0.27995,0.30924 -0.41992,0.73079 -0.41992,1.26464 l 0,3.09082 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.21484,-0.32877 0.46712,-0.57454 0.75684,-0.7373 0.29296,-0.16276 0.62988,-0.24414 1.01074,-0.24414 0.62825,0 1.10351,0.19532 1.42578,0.58594 0.32226,0.38737 0.48339,0.95866 0.4834,1.71386"
|
||||
style="font-size:10px"
|
||||
id="path3266" />
|
||||
<path
|
||||
d="m 439.71402,351.87897 c -0.48177,0 -0.86263,0.1888 -1.14258,0.5664 -0.27995,0.37436 -0.41992,0.88868 -0.41992,1.54297 0,0.6543 0.13834,1.17025 0.41504,1.54785 0.27994,0.37435 0.66243,0.56153 1.14746,0.56153 0.47851,0 0.85774,-0.1888 1.1377,-0.56641 0.27994,-0.3776 0.41991,-0.89192 0.41992,-1.54297 -10e-6,-0.64778 -0.13998,-1.16048 -0.41992,-1.53808 -0.27996,-0.38086 -0.65919,-0.57129 -1.1377,-0.57129 m 0,-0.76172 c 0.78125,0 1.39485,0.25391 1.84082,0.76172 0.44596,0.50781 0.66894,1.21094 0.66895,2.10937 -1e-5,0.89519 -0.22299,1.59831 -0.66895,2.10938 -0.44597,0.50781 -1.05957,0.76172 -1.84082,0.76172 -0.78451,0 -1.39974,-0.25391 -1.8457,-0.76172 -0.44271,-0.51107 -0.66407,-1.21419 -0.66407,-2.10938 0,-0.89843 0.22136,-1.60156 0.66407,-2.10937 0.44596,-0.50781 1.06119,-0.76172 1.8457,-0.76172"
|
||||
style="font-size:10px"
|
||||
id="path3268" />
|
||||
<path
|
||||
d="m 446.87711,352.08893 c -0.10092,-0.0586 -0.2116,-0.10091 -0.33204,-0.12695 -0.11719,-0.0293 -0.24739,-0.0439 -0.39062,-0.0439 -0.50782,0 -0.89844,0.16602 -1.17188,0.49805 -0.27018,0.32878 -0.40527,0.80241 -0.40527,1.4209 l 0,2.88085 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.1888,-0.33202 0.43457,-0.57779 0.73731,-0.7373 0.30273,-0.16276 0.67057,-0.24414 1.10351,-0.24414 0.0618,0 0.13021,0.005 0.20508,0.0146 0.0749,0.007 0.15787,0.0179 0.24902,0.0342 l 0.005,0.92285"
|
||||
style="font-size:10px"
|
||||
id="path3270" />
|
||||
<path
|
||||
d="m 447.82925,351.24908 0.89844,0 0,5.46875 -0.89844,0 0,-5.46875 m 0,-2.1289 0.89844,0 0,1.13769 -0.89844,0 0,-1.13769"
|
||||
style="font-size:10px"
|
||||
id="path3272" />
|
||||
<path
|
||||
d="m 454.20132,353.91998 c 0,-0.65104 -0.13509,-1.15559 -0.40527,-1.51367 -0.26693,-0.35807 -0.64291,-0.5371 -1.12793,-0.53711 -0.48177,1e-5 -0.85775,0.17904 -1.12793,0.53711 -0.26693,0.35808 -0.40039,0.86263 -0.40039,1.51367 0,0.64779 0.13346,1.15072 0.40039,1.50879 0.27018,0.35808 0.64616,0.53711 1.12793,0.53711 0.48502,0 0.861,-0.17903 1.12793,-0.53711 0.27018,-0.35807 0.40527,-0.861 0.40527,-1.50879 m 0.89844,2.11914 c 0,0.93099 -0.20671,1.62272 -0.62012,2.0752 -0.41341,0.45573 -1.04655,0.68359 -1.89941,0.68359 -0.31576,0 -0.61361,-0.0244 -0.89355,-0.0732 -0.27995,-0.0456 -0.55176,-0.11719 -0.81543,-0.21484 l 0,-0.87403 c 0.26367,0.14323 0.52408,0.24903 0.78125,0.31739 0.25716,0.0684 0.5192,0.10253 0.78613,0.10254 0.58919,-10e-6 1.03027,-0.15463 1.32324,-0.46387 0.29297,-0.30599 0.43945,-0.76986 0.43945,-1.3916 l 0,-0.44434 c -0.18555,0.32227 -0.42318,0.56315 -0.71289,0.72266 -0.28971,0.1595 -0.63639,0.23925 -1.04004,0.23925 -0.67057,0 -1.21093,-0.25553 -1.62109,-0.7666 -0.41016,-0.51106 -0.61523,-1.18815 -0.61523,-2.03125 0,-0.84635 0.20507,-1.52506 0.61523,-2.03613 0.41016,-0.51106 0.95052,-0.7666 1.62109,-0.7666 0.40365,0 0.75033,0.0798 1.04004,0.23926 0.28971,0.15951 0.52734,0.40039 0.71289,0.72265 l 0,-0.83008 0.89844,0 0,4.79004"
|
||||
style="font-size:10px"
|
||||
id="path3274" />
|
||||
<path
|
||||
d="m 456.95035,351.24908 0.89844,0 0,5.46875 -0.89844,0 0,-5.46875 m 0,-2.1289 0.89844,0 0,1.13769 -0.89844,0 0,-1.13769"
|
||||
style="font-size:10px"
|
||||
id="path3276" />
|
||||
<path
|
||||
d="m 464.26968,353.41705 0,3.30078 -0.89843,0 0,-3.27148 c -10e-6,-0.51757 -0.10092,-0.90494 -0.30274,-1.16211 -0.20183,-0.25716 -0.50456,-0.38574 -0.9082,-0.38574 -0.48503,0 -0.86752,0.15463 -1.14746,0.46387 -0.27995,0.30924 -0.41993,0.73079 -0.41992,1.26464 l 0,3.09082 -0.90332,0 0,-5.46875 0.90332,0 0,0.84961 c 0.21484,-0.32877 0.46712,-0.57454 0.75683,-0.7373 0.29297,-0.16276 0.62988,-0.24414 1.01074,-0.24414 0.62826,0 1.10352,0.19532 1.42579,0.58594 0.32226,0.38737 0.48339,0.95866 0.48339,1.71386"
|
||||
style="font-size:10px"
|
||||
id="path3278" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 343.73692,26.224389 0.01,294.941191"
|
||||
id="path3861"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc"
|
||||
transform="translate(12.627039,339.86462)" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4307"
|
||||
d="m 356.48533,366.00457 336.31202,-0.0196"
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4309"
|
||||
d="m 159.89916,447.6257 -0.0625,145.00422"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
||||
d="m 160.03997,448.23877 184.95568,-0.0159"
|
||||
id="path4493"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<g
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
id="text4495">
|
||||
<path
|
||||
d="m 228.57881,442.02737 0.49805,0 0.7666,3.08106 0.76416,-3.08106 0.5542,0 0.7666,3.08106 0.76416,-3.08106 0.50049,0 -0.91553,3.64502 -0.62012,0 -0.76904,-3.16406 -0.77637,3.16406 -0.62011,0 -0.91309,-3.64502"
|
||||
style="font-size:5px"
|
||||
id="path3141" />
|
||||
<path
|
||||
d="m 233.71797,442.93802 0.44922,0 0,2.73437 -0.44922,0 0,-2.73437 m 0,-1.06445 0.44922,0 0,0.56884 -0.44922,0 0,-0.56884"
|
||||
style="font-size:5px"
|
||||
id="path3143" />
|
||||
<path
|
||||
d="m 237.37764,444.022 0,1.65039 -0.44922,0 0,-1.63574 c 0,-0.25879 -0.0505,-0.45247 -0.15137,-0.58105 -0.10091,-0.12858 -0.25228,-0.19287 -0.4541,-0.19287 -0.24251,0 -0.43376,0.0773 -0.57373,0.23193 -0.13997,0.15462 -0.20996,0.3654 -0.20996,0.63232 l 0,1.54541 -0.45166,0 0,-2.73437 0.45166,0 0,0.4248 c 0.10742,-0.16438 0.23356,-0.28727 0.37842,-0.36865 0.14648,-0.0814 0.31494,-0.12207 0.50537,-0.12207 0.31413,0 0.55176,0.0977 0.71289,0.29297 0.16113,0.19369 0.2417,0.47933 0.2417,0.85693"
|
||||
style="font-size:5px"
|
||||
id="path3145" />
|
||||
<path
|
||||
d="m 240.07784,443.35306 0,-1.47949 0.44921,0 0,3.79882 -0.44921,0 0,-0.41015 c -0.0944,0.16276 -0.21404,0.28401 -0.35889,0.36377 -0.14323,0.0781 -0.31576,0.11718 -0.51758,0.11718 -0.3304,0 -0.59977,-0.13183 -0.80811,-0.3955 -0.2067,-0.26367 -0.31005,-0.61035 -0.31005,-1.04004 0,-0.42969 0.10335,-0.77637 0.31005,-1.04004 0.20834,-0.26367 0.47771,-0.39551 0.80811,-0.39551 0.20182,0 0.37435,0.0399 0.51758,0.11963 0.14485,0.0781 0.26448,0.19857 0.35889,0.36133 m -1.53077,0.95459 c 0,0.3304 0.0676,0.59 0.20264,0.77881 0.13672,0.18717 0.32389,0.28076 0.56152,0.28076 0.23763,0 0.42481,-0.0936 0.56153,-0.28076 0.13671,-0.18881 0.20507,-0.44841 0.20508,-0.77881 -1e-5,-0.3304 -0.0684,-0.58919 -0.20508,-0.77637 -0.13672,-0.1888 -0.3239,-0.2832 -0.56153,-0.2832 -0.23763,0 -0.4248,0.0944 -0.56152,0.2832 -0.13509,0.18718 -0.20264,0.44597 -0.20264,0.77637"
|
||||
style="font-size:5px"
|
||||
id="path3147" />
|
||||
<path
|
||||
d="m 242.51192,443.25296 c -0.24089,0 -0.43132,0.0944 -0.57129,0.2832 -0.13998,0.18718 -0.20996,0.44434 -0.20996,0.77149 0,0.32715 0.0692,0.58512 0.20752,0.77392 0.13997,0.18718 0.33121,0.28077 0.57373,0.28077 0.23925,0 0.42887,-0.0944 0.56884,-0.28321 0.13998,-0.1888 0.20996,-0.44596 0.20997,-0.77148 -1e-5,-0.32389 -0.07,-0.58024 -0.20997,-0.76905 -0.13997,-0.19042 -0.32959,-0.28564 -0.56884,-0.28564 m 0,-0.38086 c 0.39062,0 0.69742,0.12696 0.92041,0.38086 0.22298,0.25391 0.33447,0.60547 0.33447,1.05469 0,0.44759 -0.11149,0.79915 -0.33447,1.05469 -0.22299,0.2539 -0.52979,0.38085 -0.92041,0.38085 -0.39226,0 -0.69987,-0.12695 -0.92285,-0.38085 -0.22136,-0.25554 -0.33204,-0.6071 -0.33204,-1.05469 0,-0.44922 0.11068,-0.80078 0.33204,-1.05469 0.22298,-0.2539 0.53059,-0.38086 0.92285,-0.38086"
|
||||
style="font-size:5px"
|
||||
id="path3149" />
|
||||
<path
|
||||
d="m 244.24776,442.93802 0.44922,0 0.56152,2.13379 0.55908,-2.13379 0.52979,0 0.56152,2.13379 0.55908,-2.13379 0.44922,0 -0.71533,2.73437 -0.52979,0 -0.58838,-2.24121 -0.59082,2.24121 -0.52978,0 -0.71533,-2.73437"
|
||||
style="font-size:5px"
|
||||
id="path3151" />
|
||||
<path
|
||||
d="m 249.70674,442.02737 3.0835,0 0,0.41504 -1.29395,0 0,3.22998 -0.4956,0 0,-3.22998 -1.29395,0 0,-0.41504"
|
||||
style="font-size:5px"
|
||||
id="path3153" />
|
||||
<path
|
||||
d="m 253.09297,442.93802 0.44922,0 0,2.73437 -0.44922,0 0,-2.73437 m 0,-1.06445 0.44922,0 0,0.56884 -0.44922,0 0,-0.56884"
|
||||
style="font-size:5px"
|
||||
id="path3155" />
|
||||
<path
|
||||
d="m 254.92403,442.16165 0,0.77637 0.92529,0 0,0.34912 -0.92529,0 0,1.48437 c 0,0.22299 0.0301,0.36622 0.0903,0.42969 0.0618,0.0635 0.18636,0.0952 0.37353,0.0952 l 0.46143,0 0,0.37597 -0.46143,0 c -0.34668,0 -0.58593,-0.0643 -0.71777,-0.19287 -0.13184,-0.13021 -0.19775,-0.36621 -0.19775,-0.70801 l 0,-1.48437 -0.32959,0 0,-0.34912 0.32959,0 0,-0.77637 0.45166,0"
|
||||
style="font-size:5px"
|
||||
id="path3157" />
|
||||
<path
|
||||
d="m 256.44258,441.87357 0.44922,0 0,3.79882 -0.44922,0 0,-3.79882"
|
||||
style="font-size:5px"
|
||||
id="path3159" />
|
||||
<path
|
||||
d="m 260.16817,444.1929 0,0.21973 -2.06543,0 c 0.0195,0.30924 0.1123,0.54525 0.27832,0.70801 0.16764,0.16113 0.40039,0.2417 0.69824,0.2417 0.17252,0 0.33935,-0.0212 0.50049,-0.0635 0.16276,-0.0423 0.32389,-0.1058 0.4834,-0.19043 l 0,0.4248 c -0.16114,0.0684 -0.32634,0.12045 -0.49561,0.15625 -0.16927,0.0358 -0.34098,0.0537 -0.51514,0.0537 -0.43619,0 -0.78206,-0.12695 -1.03759,-0.38085 -0.25391,-0.25391 -0.38086,-0.59733 -0.38086,-1.03028 0,-0.44759 0.12044,-0.8024 0.36133,-1.06445 0.24251,-0.26367 0.56884,-0.39551 0.979,-0.39551 0.36784,0 0.65836,0.11882 0.87158,0.35645 0.21484,0.236 0.32226,0.55745 0.32227,0.96435 m -0.44922,-0.13183 c -0.003,-0.24577 -0.0724,-0.4419 -0.20752,-0.58838 -0.13347,-0.14649 -0.31088,-0.21973 -0.53223,-0.21973 -0.25065,0 -0.45166,0.0708 -0.60303,0.2124 -0.14974,0.14161 -0.236,0.34099 -0.25878,0.59815 l 1.60156,-0.002"
|
||||
style="font-size:5px"
|
||||
id="path3161" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 109 KiB |
|
@ -0,0 +1,232 @@
|
|||
/*!
|
||||
|
||||
@page vulkan_guide Vulkan guide
|
||||
|
||||
@tableofcontents
|
||||
|
||||
This guide is intended to fill the gaps between the [Vulkan
|
||||
documentation](https://www.khronos.org/vulkan/) and the rest of the GLFW
|
||||
documentation and is not a replacement for either. It assumes some familiarity
|
||||
with Vulkan concepts like loaders, devices, queues and surfaces and leaves it to
|
||||
the Vulkan documentation to explain the details of Vulkan functions.
|
||||
|
||||
To develop for Vulkan you should install an SDK for your platform, for example
|
||||
the [LunarG Vulkan SDK](https://vulkan.lunarg.com/) for Windows and Linux or
|
||||
[MoltenVK](https://moltengl.com/moltenvk/) for macOS. Apart from headers and
|
||||
link libraries, they should also provide the validation layers necessary for
|
||||
development.
|
||||
|
||||
The GLFW library does not need the Vulkan SDK to enable support for Vulkan.
|
||||
However, any Vulkan-specific test and example programs are built only if the
|
||||
CMake files find a Vulkan SDK.
|
||||
|
||||
For details on a specific function in this category, see the @ref vulkan. There
|
||||
are also guides for the other areas of the GLFW API.
|
||||
|
||||
- @ref intro_guide
|
||||
- @ref window_guide
|
||||
- @ref context_guide
|
||||
- @ref monitor_guide
|
||||
- @ref input_guide
|
||||
|
||||
|
||||
@section vulkan_loader Linking against the Vulkan loader
|
||||
|
||||
By default, GLFW will look for the Vulkan loader on demand at runtime via its
|
||||
standard name (`vulkan-1.dll` on Windows, `libvulkan.so.1` on Linux and other
|
||||
Unix-like systems). This means that GLFW does not need to be linked against the
|
||||
loader. However, it also means that if you are using the static library form of
|
||||
the Vulkan loader GLFW will either fail to find it or (worse) use the wrong one.
|
||||
|
||||
The @ref GLFW_VULKAN_STATIC CMake option makes GLFW link directly against the
|
||||
static form. Not linking against the Vulkan loader will then be a compile-time
|
||||
error.
|
||||
|
||||
@macos MoltenVK only provides the static library form of the Vulkan loader, but
|
||||
GLFW is able to find it without @ref GLFW_VULKAN_STATIC as long as it is linked
|
||||
into any of the binaries already loaded into the process. As it is a static
|
||||
library, you must also link against its dependencies: the `Cocoa`, `Metal` and
|
||||
`QuartzCore` frameworks and the `libc++` library.
|
||||
|
||||
|
||||
@section vulkan_include Including the Vulkan and GLFW header files
|
||||
|
||||
To include the Vulkan header, define @ref GLFW_INCLUDE_VULKAN before including
|
||||
the GLFW header.
|
||||
|
||||
@code
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
If you instead want to include the Vulkan header from a custom location or use
|
||||
your own custom Vulkan header then do this before the GLFW header.
|
||||
|
||||
@code
|
||||
#include <path/to/vulkan.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
Unless a Vulkan header is included, either by the GLFW header or above it, any
|
||||
GLFW functions that take or return Vulkan types will not be declared.
|
||||
|
||||
The `VK_USE_PLATFORM_*_KHR` macros do not need to be defined for the Vulkan part
|
||||
of GLFW to work. Define them only if you are using these extensions directly.
|
||||
|
||||
|
||||
@section vulkan_support Querying for Vulkan support
|
||||
|
||||
If you are linking directly against the Vulkan loader then you can skip this
|
||||
section. The canonical desktop loader library exports all Vulkan core and
|
||||
Khronos extension functions, allowing them to be called directly.
|
||||
|
||||
If you are loading the Vulkan loader dynamically instead of linking directly
|
||||
against it, you can check for the availability of a loader and ICD with @ref
|
||||
glfwVulkanSupported.
|
||||
|
||||
@code
|
||||
if (glfwVulkanSupported())
|
||||
{
|
||||
// Vulkan is available, at least for compute
|
||||
}
|
||||
@endcode
|
||||
|
||||
This function returns `GLFW_TRUE` if the Vulkan loader and any minimally
|
||||
functional ICD was found.
|
||||
|
||||
If if one or both were not found, calling any other Vulkan related GLFW function
|
||||
will generate a @ref GLFW_API_UNAVAILABLE error.
|
||||
|
||||
|
||||
@subsection vulkan_proc Querying Vulkan function pointers
|
||||
|
||||
To load any Vulkan core or extension function from the found loader, call @ref
|
||||
glfwGetInstanceProcAddress. To load functions needed for instance creation,
|
||||
pass `NULL` as the instance.
|
||||
|
||||
@code
|
||||
PFN_vkCreateInstance pfnCreateInstance = (PFN_vkCreateInstance)
|
||||
glfwGetInstanceProcAddress(NULL, "vkCreateInstance");
|
||||
@endcode
|
||||
|
||||
Once you have created an instance, you can load from it all other Vulkan core
|
||||
functions and functions from any instance extensions you enabled.
|
||||
|
||||
@code
|
||||
PFN_vkCreateDevice pfnCreateDevice = (PFN_vkCreateDevice)
|
||||
glfwGetInstanceProcAddress(instance, "vkCreateDevice");
|
||||
@endcode
|
||||
|
||||
This function in turn calls `vkGetInstanceProcAddr`. If that fails, the
|
||||
function falls back to a platform-specific query of the Vulkan loader (i.e.
|
||||
`dlsym` or `GetProcAddress`). If that also fails, the function returns `NULL`.
|
||||
For more information about `vkGetInstanceProcAddr`, see the Vulkan
|
||||
documentation.
|
||||
|
||||
Vulkan also provides `vkGetDeviceProcAddr` for loading device-specific versions
|
||||
of Vulkan function. This function can be retrieved from an instance with @ref
|
||||
glfwGetInstanceProcAddress.
|
||||
|
||||
@code
|
||||
PFN_vkGetDeviceProcAddr pfnGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)
|
||||
glfwGetInstanceProcAddress(instance, "vkGetDeviceProcAddr");
|
||||
@endcode
|
||||
|
||||
Device-specific functions may execute a little bit faster, due to not having to
|
||||
dispatch internally based on the device passed to them. For more information
|
||||
about `vkGetDeviceProcAddr`, see the Vulkan documentation.
|
||||
|
||||
|
||||
@section vulkan_ext Querying required Vulkan extensions
|
||||
|
||||
To do anything useful with Vulkan you need to create an instance. If you want
|
||||
to use Vulkan to render to a window, you must enable the instance extensions
|
||||
GLFW requires to create Vulkan surfaces.
|
||||
|
||||
To query the instance extensions required, call @ref
|
||||
glfwGetRequiredInstanceExtensions.
|
||||
|
||||
@code
|
||||
uint32_t count;
|
||||
const char** extensions = glfwGetRequiredInstanceExtensions(&count);
|
||||
@endcode
|
||||
|
||||
These extensions must all be enabled when creating instances that are going to
|
||||
be passed to @ref glfwGetPhysicalDevicePresentationSupport and @ref
|
||||
glfwCreateWindowSurface. The set of extensions will vary depending on platform
|
||||
and may also vary depending on graphics drivers and other factors.
|
||||
|
||||
If it fails it will return `NULL` and GLFW will not be able to create Vulkan
|
||||
window surfaces. You can still use Vulkan for off-screen rendering and compute
|
||||
work.
|
||||
|
||||
The returned array will always contain `VK_KHR_surface`, so if you don't
|
||||
require any additional extensions you can pass this list directly to the
|
||||
`VkInstanceCreateInfo` struct.
|
||||
|
||||
@code
|
||||
VkInstanceCreateInfo ici;
|
||||
|
||||
memset(&ici, 0, sizeof(ici));
|
||||
ici.enabledExtensionCount = count;
|
||||
ici.ppEnabledExtensionNames = extensions;
|
||||
...
|
||||
@endcode
|
||||
|
||||
Additional extensions may be required by future versions of GLFW. You should
|
||||
check whether any extensions you wish to enable are already in the returned
|
||||
array, as it is an error to specify an extension more than once in the
|
||||
`VkInstanceCreateInfo` struct.
|
||||
|
||||
|
||||
@section vulkan_present Querying for Vulkan presentation support
|
||||
|
||||
Not every queue family of every Vulkan device can present images to surfaces.
|
||||
To check whether a specific queue family of a physical device supports image
|
||||
presentation without first having to create a window and surface, call @ref
|
||||
glfwGetPhysicalDevicePresentationSupport.
|
||||
|
||||
@code
|
||||
if (glfwGetPhysicalDevicePresentationSupport(instance, physical_device, queue_family_index))
|
||||
{
|
||||
// Queue family supports image presentation
|
||||
}
|
||||
@endcode
|
||||
|
||||
The `VK_KHR_surface` extension additionally provides the
|
||||
`vkGetPhysicalDeviceSurfaceSupportKHR` function, which performs the same test on
|
||||
an existing Vulkan surface.
|
||||
|
||||
|
||||
@section vulkan_window Creating the window
|
||||
|
||||
Unless you will be using OpenGL or OpenGL ES with the same window as Vulkan,
|
||||
there is no need to create a context. You can disable context creation with the
|
||||
[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint.
|
||||
|
||||
@code
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(640, 480, "Window Title", NULL, NULL);
|
||||
@endcode
|
||||
|
||||
See @ref context_less for more information.
|
||||
|
||||
|
||||
@section vulkan_surface Creating a Vulkan window surface
|
||||
|
||||
You can create a Vulkan surface (as defined by the `VK_KHR_surface` extension)
|
||||
for a GLFW window with @ref glfwCreateWindowSurface.
|
||||
|
||||
@code
|
||||
VkSurfaceKHR surface;
|
||||
VkResult err = glfwCreateWindowSurface(instance, window, NULL, &surface);
|
||||
if (err)
|
||||
{
|
||||
// Window surface creation failed
|
||||
}
|
||||
@endcode
|
||||
|
||||
It is your responsibility to destroy the surface. GLFW does not destroy it for
|
||||
you. Call `vkDestroySurfaceKHR` function from the same extension to destroy it.
|
||||
|
||||
*/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,75 @@
|
|||
|
||||
link_libraries(glfw)
|
||||
|
||||
include_directories(${glfw_INCLUDE_DIRS} "${GLFW_SOURCE_DIR}/deps")
|
||||
|
||||
if (MATH_LIBRARY)
|
||||
link_libraries("${MATH_LIBRARY}")
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
if (GLFW_USE_OSMESA)
|
||||
add_definitions(-DUSE_NATIVE_OSMESA)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
set(ICON glfw.rc)
|
||||
elseif (APPLE)
|
||||
set(ICON glfw.icns)
|
||||
set_source_files_properties(glfw.icns PROPERTIES
|
||||
MACOSX_PACKAGE_LOCATION "Resources")
|
||||
endif()
|
||||
|
||||
set(GLAD "${GLFW_SOURCE_DIR}/deps/glad/glad.h"
|
||||
"${GLFW_SOURCE_DIR}/deps/glad.c")
|
||||
set(GETOPT "${GLFW_SOURCE_DIR}/deps/getopt.h"
|
||||
"${GLFW_SOURCE_DIR}/deps/getopt.c")
|
||||
set(TINYCTHREAD "${GLFW_SOURCE_DIR}/deps/tinycthread.h"
|
||||
"${GLFW_SOURCE_DIR}/deps/tinycthread.c")
|
||||
|
||||
add_executable(boing WIN32 MACOSX_BUNDLE boing.c ${ICON} ${GLAD})
|
||||
add_executable(gears WIN32 MACOSX_BUNDLE gears.c ${ICON} ${GLAD})
|
||||
add_executable(heightmap WIN32 MACOSX_BUNDLE heightmap.c ${ICON} ${GLAD})
|
||||
add_executable(offscreen offscreen.c ${ICON} ${GLAD})
|
||||
add_executable(particles WIN32 MACOSX_BUNDLE particles.c ${ICON} ${TINYCTHREAD} ${GETOPT} ${GLAD})
|
||||
add_executable(simple WIN32 MACOSX_BUNDLE simple.c ${ICON} ${GLAD})
|
||||
add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c ${ICON} ${GLAD})
|
||||
add_executable(wave WIN32 MACOSX_BUNDLE wave.c ${ICON} ${GLAD})
|
||||
|
||||
target_link_libraries(particles "${CMAKE_THREAD_LIBS_INIT}")
|
||||
if (RT_LIBRARY)
|
||||
target_link_libraries(particles "${RT_LIBRARY}")
|
||||
endif()
|
||||
|
||||
set(WINDOWS_BINARIES boing gears heightmap particles simple splitview wave)
|
||||
set(CONSOLE_BINARIES offscreen)
|
||||
|
||||
set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
|
||||
FOLDER "GLFW3/Examples")
|
||||
|
||||
if (MSVC)
|
||||
# Tell MSVC to use main instead of WinMain for Windows subsystem executables
|
||||
set_target_properties(${WINDOWS_BINARIES} PROPERTIES
|
||||
LINK_FLAGS "/ENTRY:mainCRTStartup")
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
set_target_properties(boing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Boing")
|
||||
set_target_properties(gears PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gears")
|
||||
set_target_properties(heightmap PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Heightmap")
|
||||
set_target_properties(particles PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Particles")
|
||||
set_target_properties(simple PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Simple")
|
||||
set_target_properties(splitview PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "SplitView")
|
||||
set_target_properties(wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave")
|
||||
|
||||
set_target_properties(${WINDOWS_BINARIES} PROPERTIES
|
||||
RESOURCE glfw.icns
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}
|
||||
MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION_FULL}
|
||||
MACOSX_BUNDLE_ICON_FILE glfw.icns
|
||||
MACOSX_BUNDLE_INFO_PLIST "${GLFW_SOURCE_DIR}/CMake/MacOSXBundleInfo.plist.in")
|
||||
endif()
|
||||
|
|
@ -0,0 +1,678 @@
|
|||
/*****************************************************************************
|
||||
* Title: GLBoing
|
||||
* Desc: Tribute to Amiga Boing.
|
||||
* Author: Jim Brooks <gfx@jimbrooks.org>
|
||||
* Original Amiga authors were R.J. Mical and Dale Luck.
|
||||
* GLFW conversion by Marcus Geelnard
|
||||
* Notes: - 360' = 2*PI [radian]
|
||||
*
|
||||
* - Distances between objects are created by doing a relative
|
||||
* Z translations.
|
||||
*
|
||||
* - Although OpenGL enticingly supports alpha-blending,
|
||||
* the shadow of the original Boing didn't affect the color
|
||||
* of the grid.
|
||||
*
|
||||
* - [Marcus] Changed timing scheme from interval driven to frame-
|
||||
* time based animation steps (which results in much smoother
|
||||
* movement)
|
||||
*
|
||||
* History of Amiga Boing:
|
||||
*
|
||||
* Boing was demonstrated on the prototype Amiga (codenamed "Lorraine") in
|
||||
* 1985. According to legend, it was written ad-hoc in one night by
|
||||
* R. J. Mical and Dale Luck. Because the bouncing ball animation was so fast
|
||||
* and smooth, attendees did not believe the Amiga prototype was really doing
|
||||
* the rendering. Suspecting a trick, they began looking around the booth for
|
||||
* a hidden computer or VCR.
|
||||
*****************************************************************************/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Make MS math.h define M_PI
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <linmath.h>
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Various declarations and macros
|
||||
*****************************************************************************/
|
||||
|
||||
/* Prototypes */
|
||||
void init( void );
|
||||
void display( void );
|
||||
void reshape( GLFWwindow* window, int w, int h );
|
||||
void key_callback( GLFWwindow* window, int key, int scancode, int action, int mods );
|
||||
void mouse_button_callback( GLFWwindow* window, int button, int action, int mods );
|
||||
void cursor_position_callback( GLFWwindow* window, double x, double y );
|
||||
void DrawBoingBall( void );
|
||||
void BounceBall( double dt );
|
||||
void DrawBoingBallBand( GLfloat long_lo, GLfloat long_hi );
|
||||
void DrawGrid( void );
|
||||
|
||||
#define RADIUS 70.f
|
||||
#define STEP_LONGITUDE 22.5f /* 22.5 makes 8 bands like original Boing */
|
||||
#define STEP_LATITUDE 22.5f
|
||||
|
||||
#define DIST_BALL (RADIUS * 2.f + RADIUS * 0.1f)
|
||||
|
||||
#define VIEW_SCENE_DIST (DIST_BALL * 3.f + 200.f)/* distance from viewer to middle of boing area */
|
||||
#define GRID_SIZE (RADIUS * 4.5f) /* length (width) of grid */
|
||||
#define BOUNCE_HEIGHT (RADIUS * 2.1f)
|
||||
#define BOUNCE_WIDTH (RADIUS * 2.1f)
|
||||
|
||||
#define SHADOW_OFFSET_X -20.f
|
||||
#define SHADOW_OFFSET_Y 10.f
|
||||
#define SHADOW_OFFSET_Z 0.f
|
||||
|
||||
#define WALL_L_OFFSET 0.f
|
||||
#define WALL_R_OFFSET 5.f
|
||||
|
||||
/* Animation speed (50.0 mimics the original GLUT demo speed) */
|
||||
#define ANIMATION_SPEED 50.f
|
||||
|
||||
/* Maximum allowed delta time per physics iteration */
|
||||
#define MAX_DELTA_T 0.02f
|
||||
|
||||
/* Draw ball, or its shadow */
|
||||
typedef enum { DRAW_BALL, DRAW_BALL_SHADOW } DRAW_BALL_ENUM;
|
||||
|
||||
/* Vertex type */
|
||||
typedef struct {float x; float y; float z;} vertex_t;
|
||||
|
||||
/* Global vars */
|
||||
int windowed_xpos, windowed_ypos, windowed_width, windowed_height;
|
||||
int width, height;
|
||||
GLfloat deg_rot_y = 0.f;
|
||||
GLfloat deg_rot_y_inc = 2.f;
|
||||
int override_pos = GLFW_FALSE;
|
||||
GLfloat cursor_x = 0.f;
|
||||
GLfloat cursor_y = 0.f;
|
||||
GLfloat ball_x = -RADIUS;
|
||||
GLfloat ball_y = -RADIUS;
|
||||
GLfloat ball_x_inc = 1.f;
|
||||
GLfloat ball_y_inc = 2.f;
|
||||
DRAW_BALL_ENUM drawBallHow;
|
||||
double t;
|
||||
double t_old = 0.f;
|
||||
double dt;
|
||||
|
||||
/* Random number generator */
|
||||
#ifndef RAND_MAX
|
||||
#define RAND_MAX 4095
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Truncate a degree.
|
||||
*****************************************************************************/
|
||||
GLfloat TruncateDeg( GLfloat deg )
|
||||
{
|
||||
if ( deg >= 360.f )
|
||||
return (deg - 360.f);
|
||||
else
|
||||
return deg;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Convert a degree (360-based) into a radian.
|
||||
* 360' = 2 * PI
|
||||
*****************************************************************************/
|
||||
double deg2rad( double deg )
|
||||
{
|
||||
return deg / 360 * (2 * M_PI);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* 360' sin().
|
||||
*****************************************************************************/
|
||||
double sin_deg( double deg )
|
||||
{
|
||||
return sin( deg2rad( deg ) );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* 360' cos().
|
||||
*****************************************************************************/
|
||||
double cos_deg( double deg )
|
||||
{
|
||||
return cos( deg2rad( deg ) );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Compute a cross product (for a normal vector).
|
||||
*
|
||||
* c = a x b
|
||||
*****************************************************************************/
|
||||
void CrossProduct( vertex_t a, vertex_t b, vertex_t c, vertex_t *n )
|
||||
{
|
||||
GLfloat u1, u2, u3;
|
||||
GLfloat v1, v2, v3;
|
||||
|
||||
u1 = b.x - a.x;
|
||||
u2 = b.y - a.y;
|
||||
u3 = b.y - a.z;
|
||||
|
||||
v1 = c.x - a.x;
|
||||
v2 = c.y - a.y;
|
||||
v3 = c.z - a.z;
|
||||
|
||||
n->x = u2 * v3 - v2 * v3;
|
||||
n->y = u3 * v1 - v3 * u1;
|
||||
n->z = u1 * v2 - v1 * u2;
|
||||
}
|
||||
|
||||
|
||||
#define BOING_DEBUG 0
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* init()
|
||||
*****************************************************************************/
|
||||
void init( void )
|
||||
{
|
||||
/*
|
||||
* Clear background.
|
||||
*/
|
||||
glClearColor( 0.55f, 0.55f, 0.55f, 0.f );
|
||||
|
||||
glShadeModel( GL_FLAT );
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* display()
|
||||
*****************************************************************************/
|
||||
void display(void)
|
||||
{
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
glPushMatrix();
|
||||
|
||||
drawBallHow = DRAW_BALL_SHADOW;
|
||||
DrawBoingBall();
|
||||
|
||||
DrawGrid();
|
||||
|
||||
drawBallHow = DRAW_BALL;
|
||||
DrawBoingBall();
|
||||
|
||||
glPopMatrix();
|
||||
glFlush();
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* reshape()
|
||||
*****************************************************************************/
|
||||
void reshape( GLFWwindow* window, int w, int h )
|
||||
{
|
||||
mat4x4 projection, view;
|
||||
|
||||
glViewport( 0, 0, (GLsizei)w, (GLsizei)h );
|
||||
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
mat4x4_perspective( projection,
|
||||
2.f * (float) atan2( RADIUS, 200.f ),
|
||||
(float)w / (float)h,
|
||||
1.f, VIEW_SCENE_DIST );
|
||||
glLoadMatrixf((const GLfloat*) projection);
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
{
|
||||
vec3 eye = { 0.f, 0.f, VIEW_SCENE_DIST };
|
||||
vec3 center = { 0.f, 0.f, 0.f };
|
||||
vec3 up = { 0.f, -1.f, 0.f };
|
||||
mat4x4_look_at( view, eye, center, up );
|
||||
}
|
||||
glLoadMatrixf((const GLfloat*) view);
|
||||
}
|
||||
|
||||
void key_callback( GLFWwindow* window, int key, int scancode, int action, int mods )
|
||||
{
|
||||
if (action != GLFW_PRESS)
|
||||
return;
|
||||
|
||||
if (key == GLFW_KEY_ESCAPE && mods == 0)
|
||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||
if ((key == GLFW_KEY_ENTER && mods == GLFW_MOD_ALT) ||
|
||||
(key == GLFW_KEY_F11 && mods == GLFW_MOD_ALT))
|
||||
{
|
||||
if (glfwGetWindowMonitor(window))
|
||||
{
|
||||
glfwSetWindowMonitor(window, NULL,
|
||||
windowed_xpos, windowed_ypos,
|
||||
windowed_width, windowed_height, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
||||
if (monitor)
|
||||
{
|
||||
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
||||
glfwGetWindowPos(window, &windowed_xpos, &windowed_ypos);
|
||||
glfwGetWindowSize(window, &windowed_width, &windowed_height);
|
||||
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void set_ball_pos ( GLfloat x, GLfloat y )
|
||||
{
|
||||
ball_x = (width / 2) - x;
|
||||
ball_y = y - (height / 2);
|
||||
}
|
||||
|
||||
void mouse_button_callback( GLFWwindow* window, int button, int action, int mods )
|
||||
{
|
||||
if (button != GLFW_MOUSE_BUTTON_LEFT)
|
||||
return;
|
||||
|
||||
if (action == GLFW_PRESS)
|
||||
{
|
||||
override_pos = GLFW_TRUE;
|
||||
set_ball_pos(cursor_x, cursor_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
override_pos = GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void cursor_position_callback( GLFWwindow* window, double x, double y )
|
||||
{
|
||||
cursor_x = (float) x;
|
||||
cursor_y = (float) y;
|
||||
|
||||
if ( override_pos )
|
||||
set_ball_pos(cursor_x, cursor_y);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Draw the Boing ball.
|
||||
*
|
||||
* The Boing ball is sphere in which each facet is a rectangle.
|
||||
* Facet colors alternate between red and white.
|
||||
* The ball is built by stacking latitudinal circles. Each circle is composed
|
||||
* of a widely-separated set of points, so that each facet is noticably large.
|
||||
*****************************************************************************/
|
||||
void DrawBoingBall( void )
|
||||
{
|
||||
GLfloat lon_deg; /* degree of longitude */
|
||||
double dt_total, dt2;
|
||||
|
||||
glPushMatrix();
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
|
||||
/*
|
||||
* Another relative Z translation to separate objects.
|
||||
*/
|
||||
glTranslatef( 0.0, 0.0, DIST_BALL );
|
||||
|
||||
/* Update ball position and rotation (iterate if necessary) */
|
||||
dt_total = dt;
|
||||
while( dt_total > 0.0 )
|
||||
{
|
||||
dt2 = dt_total > MAX_DELTA_T ? MAX_DELTA_T : dt_total;
|
||||
dt_total -= dt2;
|
||||
BounceBall( dt2 );
|
||||
deg_rot_y = TruncateDeg( deg_rot_y + deg_rot_y_inc*((float)dt2*ANIMATION_SPEED) );
|
||||
}
|
||||
|
||||
/* Set ball position */
|
||||
glTranslatef( ball_x, ball_y, 0.0 );
|
||||
|
||||
/*
|
||||
* Offset the shadow.
|
||||
*/
|
||||
if ( drawBallHow == DRAW_BALL_SHADOW )
|
||||
{
|
||||
glTranslatef( SHADOW_OFFSET_X,
|
||||
SHADOW_OFFSET_Y,
|
||||
SHADOW_OFFSET_Z );
|
||||
}
|
||||
|
||||
/*
|
||||
* Tilt the ball.
|
||||
*/
|
||||
glRotatef( -20.0, 0.0, 0.0, 1.0 );
|
||||
|
||||
/*
|
||||
* Continually rotate ball around Y axis.
|
||||
*/
|
||||
glRotatef( deg_rot_y, 0.0, 1.0, 0.0 );
|
||||
|
||||
/*
|
||||
* Set OpenGL state for Boing ball.
|
||||
*/
|
||||
glCullFace( GL_FRONT );
|
||||
glEnable( GL_CULL_FACE );
|
||||
glEnable( GL_NORMALIZE );
|
||||
|
||||
/*
|
||||
* Build a faceted latitude slice of the Boing ball,
|
||||
* stepping same-sized vertical bands of the sphere.
|
||||
*/
|
||||
for ( lon_deg = 0;
|
||||
lon_deg < 180;
|
||||
lon_deg += STEP_LONGITUDE )
|
||||
{
|
||||
/*
|
||||
* Draw a latitude circle at this longitude.
|
||||
*/
|
||||
DrawBoingBallBand( lon_deg,
|
||||
lon_deg + STEP_LONGITUDE );
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Bounce the ball.
|
||||
*****************************************************************************/
|
||||
void BounceBall( double delta_t )
|
||||
{
|
||||
GLfloat sign;
|
||||
GLfloat deg;
|
||||
|
||||
if ( override_pos )
|
||||
return;
|
||||
|
||||
/* Bounce on walls */
|
||||
if ( ball_x > (BOUNCE_WIDTH/2 + WALL_R_OFFSET ) )
|
||||
{
|
||||
ball_x_inc = -0.5f - 0.75f * (GLfloat)rand() / (GLfloat)RAND_MAX;
|
||||
deg_rot_y_inc = -deg_rot_y_inc;
|
||||
}
|
||||
if ( ball_x < -(BOUNCE_HEIGHT/2 + WALL_L_OFFSET) )
|
||||
{
|
||||
ball_x_inc = 0.5f + 0.75f * (GLfloat)rand() / (GLfloat)RAND_MAX;
|
||||
deg_rot_y_inc = -deg_rot_y_inc;
|
||||
}
|
||||
|
||||
/* Bounce on floor / roof */
|
||||
if ( ball_y > BOUNCE_HEIGHT/2 )
|
||||
{
|
||||
ball_y_inc = -0.75f - 1.f * (GLfloat)rand() / (GLfloat)RAND_MAX;
|
||||
}
|
||||
if ( ball_y < -BOUNCE_HEIGHT/2*0.85 )
|
||||
{
|
||||
ball_y_inc = 0.75f + 1.f * (GLfloat)rand() / (GLfloat)RAND_MAX;
|
||||
}
|
||||
|
||||
/* Update ball position */
|
||||
ball_x += ball_x_inc * ((float)delta_t*ANIMATION_SPEED);
|
||||
ball_y += ball_y_inc * ((float)delta_t*ANIMATION_SPEED);
|
||||
|
||||
/*
|
||||
* Simulate the effects of gravity on Y movement.
|
||||
*/
|
||||
if ( ball_y_inc < 0 ) sign = -1.0; else sign = 1.0;
|
||||
|
||||
deg = (ball_y + BOUNCE_HEIGHT/2) * 90 / BOUNCE_HEIGHT;
|
||||
if ( deg > 80 ) deg = 80;
|
||||
if ( deg < 10 ) deg = 10;
|
||||
|
||||
ball_y_inc = sign * 4.f * (float) sin_deg( deg );
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Draw a faceted latitude band of the Boing ball.
|
||||
*
|
||||
* Parms: long_lo, long_hi
|
||||
* Low and high longitudes of slice, resp.
|
||||
*****************************************************************************/
|
||||
void DrawBoingBallBand( GLfloat long_lo,
|
||||
GLfloat long_hi )
|
||||
{
|
||||
vertex_t vert_ne; /* "ne" means south-east, so on */
|
||||
vertex_t vert_nw;
|
||||
vertex_t vert_sw;
|
||||
vertex_t vert_se;
|
||||
vertex_t vert_norm;
|
||||
GLfloat lat_deg;
|
||||
static int colorToggle = 0;
|
||||
|
||||
/*
|
||||
* Iterate thru the points of a latitude circle.
|
||||
* A latitude circle is a 2D set of X,Z points.
|
||||
*/
|
||||
for ( lat_deg = 0;
|
||||
lat_deg <= (360 - STEP_LATITUDE);
|
||||
lat_deg += STEP_LATITUDE )
|
||||
{
|
||||
/*
|
||||
* Color this polygon with red or white.
|
||||
*/
|
||||
if ( colorToggle )
|
||||
glColor3f( 0.8f, 0.1f, 0.1f );
|
||||
else
|
||||
glColor3f( 0.95f, 0.95f, 0.95f );
|
||||
#if 0
|
||||
if ( lat_deg >= 180 )
|
||||
if ( colorToggle )
|
||||
glColor3f( 0.1f, 0.8f, 0.1f );
|
||||
else
|
||||
glColor3f( 0.5f, 0.5f, 0.95f );
|
||||
#endif
|
||||
colorToggle = ! colorToggle;
|
||||
|
||||
/*
|
||||
* Change color if drawing shadow.
|
||||
*/
|
||||
if ( drawBallHow == DRAW_BALL_SHADOW )
|
||||
glColor3f( 0.35f, 0.35f, 0.35f );
|
||||
|
||||
/*
|
||||
* Assign each Y.
|
||||
*/
|
||||
vert_ne.y = vert_nw.y = (float) cos_deg(long_hi) * RADIUS;
|
||||
vert_sw.y = vert_se.y = (float) cos_deg(long_lo) * RADIUS;
|
||||
|
||||
/*
|
||||
* Assign each X,Z with sin,cos values scaled by latitude radius indexed by longitude.
|
||||
* Eg, long=0 and long=180 are at the poles, so zero scale is sin(longitude),
|
||||
* while long=90 (sin(90)=1) is at equator.
|
||||
*/
|
||||
vert_ne.x = (float) cos_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
|
||||
vert_se.x = (float) cos_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo ));
|
||||
vert_nw.x = (float) cos_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
|
||||
vert_sw.x = (float) cos_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo ));
|
||||
|
||||
vert_ne.z = (float) sin_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
|
||||
vert_se.z = (float) sin_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo ));
|
||||
vert_nw.z = (float) sin_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
|
||||
vert_sw.z = (float) sin_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo ));
|
||||
|
||||
/*
|
||||
* Draw the facet.
|
||||
*/
|
||||
glBegin( GL_POLYGON );
|
||||
|
||||
CrossProduct( vert_ne, vert_nw, vert_sw, &vert_norm );
|
||||
glNormal3f( vert_norm.x, vert_norm.y, vert_norm.z );
|
||||
|
||||
glVertex3f( vert_ne.x, vert_ne.y, vert_ne.z );
|
||||
glVertex3f( vert_nw.x, vert_nw.y, vert_nw.z );
|
||||
glVertex3f( vert_sw.x, vert_sw.y, vert_sw.z );
|
||||
glVertex3f( vert_se.x, vert_se.y, vert_se.z );
|
||||
|
||||
glEnd();
|
||||
|
||||
#if BOING_DEBUG
|
||||
printf( "----------------------------------------------------------- \n" );
|
||||
printf( "lat = %f long_lo = %f long_hi = %f \n", lat_deg, long_lo, long_hi );
|
||||
printf( "vert_ne x = %.8f y = %.8f z = %.8f \n", vert_ne.x, vert_ne.y, vert_ne.z );
|
||||
printf( "vert_nw x = %.8f y = %.8f z = %.8f \n", vert_nw.x, vert_nw.y, vert_nw.z );
|
||||
printf( "vert_se x = %.8f y = %.8f z = %.8f \n", vert_se.x, vert_se.y, vert_se.z );
|
||||
printf( "vert_sw x = %.8f y = %.8f z = %.8f \n", vert_sw.x, vert_sw.y, vert_sw.z );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Toggle color so that next band will opposite red/white colors than this one.
|
||||
*/
|
||||
colorToggle = ! colorToggle;
|
||||
|
||||
/*
|
||||
* This circular band is done.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Draw the purple grid of lines, behind the Boing ball.
|
||||
* When the Workbench is dropped to the bottom, Boing shows 12 rows.
|
||||
*****************************************************************************/
|
||||
void DrawGrid( void )
|
||||
{
|
||||
int row, col;
|
||||
const int rowTotal = 12; /* must be divisible by 2 */
|
||||
const int colTotal = rowTotal; /* must be same as rowTotal */
|
||||
const GLfloat widthLine = 2.0; /* should be divisible by 2 */
|
||||
const GLfloat sizeCell = GRID_SIZE / rowTotal;
|
||||
const GLfloat z_offset = -40.0;
|
||||
GLfloat xl, xr;
|
||||
GLfloat yt, yb;
|
||||
|
||||
glPushMatrix();
|
||||
glDisable( GL_CULL_FACE );
|
||||
|
||||
/*
|
||||
* Another relative Z translation to separate objects.
|
||||
*/
|
||||
glTranslatef( 0.0, 0.0, DIST_BALL );
|
||||
|
||||
/*
|
||||
* Draw vertical lines (as skinny 3D rectangles).
|
||||
*/
|
||||
for ( col = 0; col <= colTotal; col++ )
|
||||
{
|
||||
/*
|
||||
* Compute co-ords of line.
|
||||
*/
|
||||
xl = -GRID_SIZE / 2 + col * sizeCell;
|
||||
xr = xl + widthLine;
|
||||
|
||||
yt = GRID_SIZE / 2;
|
||||
yb = -GRID_SIZE / 2 - widthLine;
|
||||
|
||||
glBegin( GL_POLYGON );
|
||||
|
||||
glColor3f( 0.6f, 0.1f, 0.6f ); /* purple */
|
||||
|
||||
glVertex3f( xr, yt, z_offset ); /* NE */
|
||||
glVertex3f( xl, yt, z_offset ); /* NW */
|
||||
glVertex3f( xl, yb, z_offset ); /* SW */
|
||||
glVertex3f( xr, yb, z_offset ); /* SE */
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw horizontal lines (as skinny 3D rectangles).
|
||||
*/
|
||||
for ( row = 0; row <= rowTotal; row++ )
|
||||
{
|
||||
/*
|
||||
* Compute co-ords of line.
|
||||
*/
|
||||
yt = GRID_SIZE / 2 - row * sizeCell;
|
||||
yb = yt - widthLine;
|
||||
|
||||
xl = -GRID_SIZE / 2;
|
||||
xr = GRID_SIZE / 2 + widthLine;
|
||||
|
||||
glBegin( GL_POLYGON );
|
||||
|
||||
glColor3f( 0.6f, 0.1f, 0.6f ); /* purple */
|
||||
|
||||
glVertex3f( xr, yt, z_offset ); /* NE */
|
||||
glVertex3f( xl, yt, z_offset ); /* NW */
|
||||
glVertex3f( xl, yb, z_offset ); /* SW */
|
||||
glVertex3f( xr, yb, z_offset ); /* SE */
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*
|
||||
* main()
|
||||
*======================================================================*/
|
||||
|
||||
int main( void )
|
||||
{
|
||||
GLFWwindow* window;
|
||||
|
||||
/* Init GLFW */
|
||||
if( !glfwInit() )
|
||||
exit( EXIT_FAILURE );
|
||||
|
||||
window = glfwCreateWindow( 400, 400, "Boing (classic Amiga demo)", NULL, NULL );
|
||||
if (!window)
|
||||
{
|
||||
glfwTerminate();
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
glfwSetWindowAspectRatio(window, 1, 1);
|
||||
|
||||
glfwSetFramebufferSizeCallback(window, reshape);
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetMouseButtonCallback(window, mouse_button_callback);
|
||||
glfwSetCursorPosCallback(window, cursor_position_callback);
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
|
||||
glfwSwapInterval( 1 );
|
||||
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
reshape(window, width, height);
|
||||
|
||||
glfwSetTime( 0.0 );
|
||||
|
||||
init();
|
||||
|
||||
/* Main loop */
|
||||
for (;;)
|
||||
{
|
||||
/* Timing */
|
||||
t = glfwGetTime();
|
||||
dt = t - t_old;
|
||||
t_old = t;
|
||||
|
||||
/* Draw one frame */
|
||||
display();
|
||||
|
||||
/* Swap buffers */
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
|
||||
/* Check if we are still running */
|
||||
if (glfwWindowShouldClose(window))
|
||||
break;
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
exit( EXIT_SUCCESS );
|
||||
}
|
||||
|
|
@ -0,0 +1,357 @@
|
|||
/*
|
||||
* 3-D gear wheels. This program is in the public domain.
|
||||
*
|
||||
* Command line options:
|
||||
* -info print GL implementation information
|
||||
* -exit automatically exit after 30 seconds
|
||||
*
|
||||
*
|
||||
* Brian Paul
|
||||
*
|
||||
*
|
||||
* Marcus Geelnard:
|
||||
* - Conversion to GLFW
|
||||
* - Time based rendering (frame rate independent)
|
||||
* - Slightly modified camera that should work better for stereo viewing
|
||||
*
|
||||
*
|
||||
* Camilla Löwy:
|
||||
* - Removed FPS counter (this is not a benchmark)
|
||||
* - Added a few comments
|
||||
* - Enabled vsync
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Make MS math.h define M_PI
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
/**
|
||||
|
||||
Draw a gear wheel. You'll probably want to call this function when
|
||||
building a display list since we do a lot of trig here.
|
||||
|
||||
Input: inner_radius - radius of hole at center
|
||||
outer_radius - radius at center of teeth
|
||||
width - width of gear teeth - number of teeth
|
||||
tooth_depth - depth of tooth
|
||||
|
||||
**/
|
||||
|
||||
static void
|
||||
gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
|
||||
GLint teeth, GLfloat tooth_depth)
|
||||
{
|
||||
GLint i;
|
||||
GLfloat r0, r1, r2;
|
||||
GLfloat angle, da;
|
||||
GLfloat u, v, len;
|
||||
|
||||
r0 = inner_radius;
|
||||
r1 = outer_radius - tooth_depth / 2.f;
|
||||
r2 = outer_radius + tooth_depth / 2.f;
|
||||
|
||||
da = 2.f * (float) M_PI / teeth / 4.f;
|
||||
|
||||
glShadeModel(GL_FLAT);
|
||||
|
||||
glNormal3f(0.f, 0.f, 1.f);
|
||||
|
||||
/* draw front face */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (i = 0; i <= teeth; i++) {
|
||||
angle = i * 2.f * (float) M_PI / teeth;
|
||||
glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), width * 0.5f);
|
||||
glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), width * 0.5f);
|
||||
if (i < teeth) {
|
||||
glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), width * 0.5f);
|
||||
glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), width * 0.5f);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* draw front sides of teeth */
|
||||
glBegin(GL_QUADS);
|
||||
da = 2.f * (float) M_PI / teeth / 4.f;
|
||||
for (i = 0; i < teeth; i++) {
|
||||
angle = i * 2.f * (float) M_PI / teeth;
|
||||
|
||||
glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), width * 0.5f);
|
||||
glVertex3f(r2 * (float) cos(angle + da), r2 * (float) sin(angle + da), width * 0.5f);
|
||||
glVertex3f(r2 * (float) cos(angle + 2 * da), r2 * (float) sin(angle + 2 * da), width * 0.5f);
|
||||
glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), width * 0.5f);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glNormal3f(0.0, 0.0, -1.0);
|
||||
|
||||
/* draw back face */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (i = 0; i <= teeth; i++) {
|
||||
angle = i * 2.f * (float) M_PI / teeth;
|
||||
glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), -width * 0.5f);
|
||||
glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), -width * 0.5f);
|
||||
if (i < teeth) {
|
||||
glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), -width * 0.5f);
|
||||
glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), -width * 0.5f);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* draw back sides of teeth */
|
||||
glBegin(GL_QUADS);
|
||||
da = 2.f * (float) M_PI / teeth / 4.f;
|
||||
for (i = 0; i < teeth; i++) {
|
||||
angle = i * 2.f * (float) M_PI / teeth;
|
||||
|
||||
glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), -width * 0.5f);
|
||||
glVertex3f(r2 * (float) cos(angle + 2 * da), r2 * (float) sin(angle + 2 * da), -width * 0.5f);
|
||||
glVertex3f(r2 * (float) cos(angle + da), r2 * (float) sin(angle + da), -width * 0.5f);
|
||||
glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), -width * 0.5f);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* draw outward faces of teeth */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (i = 0; i < teeth; i++) {
|
||||
angle = i * 2.f * (float) M_PI / teeth;
|
||||
|
||||
glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), width * 0.5f);
|
||||
glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), -width * 0.5f);
|
||||
u = r2 * (float) cos(angle + da) - r1 * (float) cos(angle);
|
||||
v = r2 * (float) sin(angle + da) - r1 * (float) sin(angle);
|
||||
len = (float) sqrt(u * u + v * v);
|
||||
u /= len;
|
||||
v /= len;
|
||||
glNormal3f(v, -u, 0.0);
|
||||
glVertex3f(r2 * (float) cos(angle + da), r2 * (float) sin(angle + da), width * 0.5f);
|
||||
glVertex3f(r2 * (float) cos(angle + da), r2 * (float) sin(angle + da), -width * 0.5f);
|
||||
glNormal3f((float) cos(angle), (float) sin(angle), 0.f);
|
||||
glVertex3f(r2 * (float) cos(angle + 2 * da), r2 * (float) sin(angle + 2 * da), width * 0.5f);
|
||||
glVertex3f(r2 * (float) cos(angle + 2 * da), r2 * (float) sin(angle + 2 * da), -width * 0.5f);
|
||||
u = r1 * (float) cos(angle + 3 * da) - r2 * (float) cos(angle + 2 * da);
|
||||
v = r1 * (float) sin(angle + 3 * da) - r2 * (float) sin(angle + 2 * da);
|
||||
glNormal3f(v, -u, 0.f);
|
||||
glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), width * 0.5f);
|
||||
glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), -width * 0.5f);
|
||||
glNormal3f((float) cos(angle), (float) sin(angle), 0.f);
|
||||
}
|
||||
|
||||
glVertex3f(r1 * (float) cos(0), r1 * (float) sin(0), width * 0.5f);
|
||||
glVertex3f(r1 * (float) cos(0), r1 * (float) sin(0), -width * 0.5f);
|
||||
|
||||
glEnd();
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
/* draw inside radius cylinder */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (i = 0; i <= teeth; i++) {
|
||||
angle = i * 2.f * (float) M_PI / teeth;
|
||||
glNormal3f(-(float) cos(angle), -(float) sin(angle), 0.f);
|
||||
glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), -width * 0.5f);
|
||||
glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), width * 0.5f);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
}
|
||||
|
||||
|
||||
static GLfloat view_rotx = 20.f, view_roty = 30.f, view_rotz = 0.f;
|
||||
static GLint gear1, gear2, gear3;
|
||||
static GLfloat angle = 0.f;
|
||||
|
||||
/* OpenGL draw function & timing */
|
||||
static void draw(void)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(view_rotx, 1.0, 0.0, 0.0);
|
||||
glRotatef(view_roty, 0.0, 1.0, 0.0);
|
||||
glRotatef(view_rotz, 0.0, 0.0, 1.0);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(-3.0, -2.0, 0.0);
|
||||
glRotatef(angle, 0.0, 0.0, 1.0);
|
||||
glCallList(gear1);
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(3.1f, -2.f, 0.f);
|
||||
glRotatef(-2.f * angle - 9.f, 0.f, 0.f, 1.f);
|
||||
glCallList(gear2);
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(-3.1f, 4.2f, 0.f);
|
||||
glRotatef(-2.f * angle - 25.f, 0.f, 0.f, 1.f);
|
||||
glCallList(gear3);
|
||||
glPopMatrix();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
/* update animation parameters */
|
||||
static void animate(void)
|
||||
{
|
||||
angle = 100.f * (float) glfwGetTime();
|
||||
}
|
||||
|
||||
|
||||
/* change view angle, exit upon ESC */
|
||||
void key( GLFWwindow* window, int k, int s, int action, int mods )
|
||||
{
|
||||
if( action != GLFW_PRESS ) return;
|
||||
|
||||
switch (k) {
|
||||
case GLFW_KEY_Z:
|
||||
if( mods & GLFW_MOD_SHIFT )
|
||||
view_rotz -= 5.0;
|
||||
else
|
||||
view_rotz += 5.0;
|
||||
break;
|
||||
case GLFW_KEY_ESCAPE:
|
||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||
break;
|
||||
case GLFW_KEY_UP:
|
||||
view_rotx += 5.0;
|
||||
break;
|
||||
case GLFW_KEY_DOWN:
|
||||
view_rotx -= 5.0;
|
||||
break;
|
||||
case GLFW_KEY_LEFT:
|
||||
view_roty += 5.0;
|
||||
break;
|
||||
case GLFW_KEY_RIGHT:
|
||||
view_roty -= 5.0;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* new window size */
|
||||
void reshape( GLFWwindow* window, int width, int height )
|
||||
{
|
||||
GLfloat h = (GLfloat) height / (GLfloat) width;
|
||||
GLfloat xmax, znear, zfar;
|
||||
|
||||
znear = 5.0f;
|
||||
zfar = 30.0f;
|
||||
xmax = znear * 0.5f;
|
||||
|
||||
glViewport( 0, 0, (GLint) width, (GLint) height );
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
glFrustum( -xmax, xmax, -xmax*h, xmax*h, znear, zfar );
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
glTranslatef( 0.0, 0.0, -20.0 );
|
||||
}
|
||||
|
||||
|
||||
/* program & OpenGL initialization */
|
||||
static void init(void)
|
||||
{
|
||||
static GLfloat pos[4] = {5.f, 5.f, 10.f, 0.f};
|
||||
static GLfloat red[4] = {0.8f, 0.1f, 0.f, 1.f};
|
||||
static GLfloat green[4] = {0.f, 0.8f, 0.2f, 1.f};
|
||||
static GLfloat blue[4] = {0.2f, 0.2f, 1.f, 1.f};
|
||||
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, pos);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
/* make the gears */
|
||||
gear1 = glGenLists(1);
|
||||
glNewList(gear1, GL_COMPILE);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
|
||||
gear(1.f, 4.f, 1.f, 20, 0.7f);
|
||||
glEndList();
|
||||
|
||||
gear2 = glGenLists(1);
|
||||
glNewList(gear2, GL_COMPILE);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
|
||||
gear(0.5f, 2.f, 2.f, 10, 0.7f);
|
||||
glEndList();
|
||||
|
||||
gear3 = glGenLists(1);
|
||||
glNewList(gear3, GL_COMPILE);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
|
||||
gear(1.3f, 2.f, 0.5f, 10, 0.7f);
|
||||
glEndList();
|
||||
|
||||
glEnable(GL_NORMALIZE);
|
||||
}
|
||||
|
||||
|
||||
/* program entry */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
GLFWwindow* window;
|
||||
int width, height;
|
||||
|
||||
if( !glfwInit() )
|
||||
{
|
||||
fprintf( stderr, "Failed to initialize GLFW\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_DEPTH_BITS, 16);
|
||||
|
||||
window = glfwCreateWindow( 300, 300, "Gears", NULL, NULL );
|
||||
if (!window)
|
||||
{
|
||||
fprintf( stderr, "Failed to open GLFW window\n" );
|
||||
glfwTerminate();
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
// Set callback functions
|
||||
glfwSetFramebufferSizeCallback(window, reshape);
|
||||
glfwSetKeyCallback(window, key);
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
|
||||
glfwSwapInterval( 1 );
|
||||
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
reshape(window, width, height);
|
||||
|
||||
// Parse command-line options
|
||||
init();
|
||||
|
||||
// Main loop
|
||||
while( !glfwWindowShouldClose(window) )
|
||||
{
|
||||
// Draw gears
|
||||
draw();
|
||||
|
||||
// Update animation
|
||||
animate();
|
||||
|
||||
// Swap buffers
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
// Terminate GLFW
|
||||
glfwTerminate();
|
||||
|
||||
// Exit program
|
||||
exit( EXIT_SUCCESS );
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
|
@ -0,0 +1,3 @@
|
|||
|
||||
GLFW_ICON ICON "glfw.ico"
|
||||
|
|
@ -0,0 +1,511 @@
|
|||
//========================================================================
|
||||
// Heightmap example program using OpenGL 3 core profile
|
||||
// Copyright (c) 2010 Olivier Delannoy
|
||||
//
|
||||
// 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
/* Map height updates */
|
||||
#define MAX_CIRCLE_SIZE (5.0f)
|
||||
#define MAX_DISPLACEMENT (1.0f)
|
||||
#define DISPLACEMENT_SIGN_LIMIT (0.3f)
|
||||
#define MAX_ITER (200)
|
||||
#define NUM_ITER_AT_A_TIME (1)
|
||||
|
||||
/* Map general information */
|
||||
#define MAP_SIZE (10.0f)
|
||||
#define MAP_NUM_VERTICES (80)
|
||||
#define MAP_NUM_TOTAL_VERTICES (MAP_NUM_VERTICES*MAP_NUM_VERTICES)
|
||||
#define MAP_NUM_LINES (3* (MAP_NUM_VERTICES - 1) * (MAP_NUM_VERTICES - 1) + \
|
||||
2 * (MAP_NUM_VERTICES - 1))
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Default shader programs
|
||||
*********************************************************************/
|
||||
|
||||
static const char* vertex_shader_text =
|
||||
"#version 150\n"
|
||||
"uniform mat4 project;\n"
|
||||
"uniform mat4 modelview;\n"
|
||||
"in float x;\n"
|
||||
"in float y;\n"
|
||||
"in float z;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = project * modelview * vec4(x, y, z, 1.0);\n"
|
||||
"}\n";
|
||||
|
||||
static const char* fragment_shader_text =
|
||||
"#version 150\n"
|
||||
"out vec4 color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" color = vec4(0.2, 1.0, 0.2, 1.0); \n"
|
||||
"}\n";
|
||||
|
||||
/**********************************************************************
|
||||
* Values for shader uniforms
|
||||
*********************************************************************/
|
||||
|
||||
/* Frustum configuration */
|
||||
static GLfloat view_angle = 45.0f;
|
||||
static GLfloat aspect_ratio = 4.0f/3.0f;
|
||||
static GLfloat z_near = 1.0f;
|
||||
static GLfloat z_far = 100.f;
|
||||
|
||||
/* Projection matrix */
|
||||
static GLfloat projection_matrix[16] = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
};
|
||||
|
||||
/* Model view matrix */
|
||||
static GLfloat modelview_matrix[16] = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
};
|
||||
|
||||
/**********************************************************************
|
||||
* Heightmap vertex and index data
|
||||
*********************************************************************/
|
||||
|
||||
static GLfloat map_vertices[3][MAP_NUM_TOTAL_VERTICES];
|
||||
static GLuint map_line_indices[2*MAP_NUM_LINES];
|
||||
|
||||
/* Store uniform location for the shaders
|
||||
* Those values are setup as part of the process of creating
|
||||
* the shader program. They should not be used before creating
|
||||
* the program.
|
||||
*/
|
||||
static GLuint mesh;
|
||||
static GLuint mesh_vbo[4];
|
||||
|
||||
/**********************************************************************
|
||||
* OpenGL helper functions
|
||||
*********************************************************************/
|
||||
|
||||
/* Creates a shader object of the specified type using the specified text
|
||||
*/
|
||||
static GLuint make_shader(GLenum type, const char* text)
|
||||
{
|
||||
GLuint shader;
|
||||
GLint shader_ok;
|
||||
GLsizei log_length;
|
||||
char info_log[8192];
|
||||
|
||||
shader = glCreateShader(type);
|
||||
if (shader != 0)
|
||||
{
|
||||
glShaderSource(shader, 1, (const GLchar**)&text, NULL);
|
||||
glCompileShader(shader);
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &shader_ok);
|
||||
if (shader_ok != GL_TRUE)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Failed to compile %s shader\n", (type == GL_FRAGMENT_SHADER) ? "fragment" : "vertex" );
|
||||
glGetShaderInfoLog(shader, 8192, &log_length,info_log);
|
||||
fprintf(stderr, "ERROR: \n%s\n\n", info_log);
|
||||
glDeleteShader(shader);
|
||||
shader = 0;
|
||||
}
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
/* Creates a program object using the specified vertex and fragment text
|
||||
*/
|
||||
static GLuint make_shader_program(const char* vs_text, const char* fs_text)
|
||||
{
|
||||
GLuint program = 0u;
|
||||
GLint program_ok;
|
||||
GLuint vertex_shader = 0u;
|
||||
GLuint fragment_shader = 0u;
|
||||
GLsizei log_length;
|
||||
char info_log[8192];
|
||||
|
||||
vertex_shader = make_shader(GL_VERTEX_SHADER, vs_text);
|
||||
if (vertex_shader != 0u)
|
||||
{
|
||||
fragment_shader = make_shader(GL_FRAGMENT_SHADER, fs_text);
|
||||
if (fragment_shader != 0u)
|
||||
{
|
||||
/* make the program that connect the two shader and link it */
|
||||
program = glCreateProgram();
|
||||
if (program != 0u)
|
||||
{
|
||||
/* attach both shader and link */
|
||||
glAttachShader(program, vertex_shader);
|
||||
glAttachShader(program, fragment_shader);
|
||||
glLinkProgram(program);
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &program_ok);
|
||||
|
||||
if (program_ok != GL_TRUE)
|
||||
{
|
||||
fprintf(stderr, "ERROR, failed to link shader program\n");
|
||||
glGetProgramInfoLog(program, 8192, &log_length, info_log);
|
||||
fprintf(stderr, "ERROR: \n%s\n\n", info_log);
|
||||
glDeleteProgram(program);
|
||||
glDeleteShader(fragment_shader);
|
||||
glDeleteShader(vertex_shader);
|
||||
program = 0u;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "ERROR: Unable to load fragment shader\n");
|
||||
glDeleteShader(vertex_shader);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "ERROR: Unable to load vertex shader\n");
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Geometry creation functions
|
||||
*********************************************************************/
|
||||
|
||||
/* Generate vertices and indices for the heightmap
|
||||
*/
|
||||
static void init_map(void)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int k;
|
||||
GLfloat step = MAP_SIZE / (MAP_NUM_VERTICES - 1);
|
||||
GLfloat x = 0.0f;
|
||||
GLfloat z = 0.0f;
|
||||
/* Create a flat grid */
|
||||
k = 0;
|
||||
for (i = 0 ; i < MAP_NUM_VERTICES ; ++i)
|
||||
{
|
||||
for (j = 0 ; j < MAP_NUM_VERTICES ; ++j)
|
||||
{
|
||||
map_vertices[0][k] = x;
|
||||
map_vertices[1][k] = 0.0f;
|
||||
map_vertices[2][k] = z;
|
||||
z += step;
|
||||
++k;
|
||||
}
|
||||
x += step;
|
||||
z = 0.0f;
|
||||
}
|
||||
#if DEBUG_ENABLED
|
||||
for (i = 0 ; i < MAP_NUM_TOTAL_VERTICES ; ++i)
|
||||
{
|
||||
printf ("Vertice %d (%f, %f, %f)\n",
|
||||
i, map_vertices[0][i], map_vertices[1][i], map_vertices[2][i]);
|
||||
|
||||
}
|
||||
#endif
|
||||
/* create indices */
|
||||
/* line fan based on i
|
||||
* i+1
|
||||
* | / i + n + 1
|
||||
* | /
|
||||
* |/
|
||||
* i --- i + n
|
||||
*/
|
||||
|
||||
/* close the top of the square */
|
||||
k = 0;
|
||||
for (i = 0 ; i < MAP_NUM_VERTICES -1 ; ++i)
|
||||
{
|
||||
map_line_indices[k++] = (i + 1) * MAP_NUM_VERTICES -1;
|
||||
map_line_indices[k++] = (i + 2) * MAP_NUM_VERTICES -1;
|
||||
}
|
||||
/* close the right of the square */
|
||||
for (i = 0 ; i < MAP_NUM_VERTICES -1 ; ++i)
|
||||
{
|
||||
map_line_indices[k++] = (MAP_NUM_VERTICES - 1) * MAP_NUM_VERTICES + i;
|
||||
map_line_indices[k++] = (MAP_NUM_VERTICES - 1) * MAP_NUM_VERTICES + i + 1;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < (MAP_NUM_VERTICES - 1) ; ++i)
|
||||
{
|
||||
for (j = 0 ; j < (MAP_NUM_VERTICES - 1) ; ++j)
|
||||
{
|
||||
int ref = i * (MAP_NUM_VERTICES) + j;
|
||||
map_line_indices[k++] = ref;
|
||||
map_line_indices[k++] = ref + 1;
|
||||
|
||||
map_line_indices[k++] = ref;
|
||||
map_line_indices[k++] = ref + MAP_NUM_VERTICES;
|
||||
|
||||
map_line_indices[k++] = ref;
|
||||
map_line_indices[k++] = ref + MAP_NUM_VERTICES + 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
for (k = 0 ; k < 2 * MAP_NUM_LINES ; k += 2)
|
||||
{
|
||||
int beg, end;
|
||||
beg = map_line_indices[k];
|
||||
end = map_line_indices[k+1];
|
||||
printf ("Line %d: %d -> %d (%f, %f, %f) -> (%f, %f, %f)\n",
|
||||
k / 2, beg, end,
|
||||
map_vertices[0][beg], map_vertices[1][beg], map_vertices[2][beg],
|
||||
map_vertices[0][end], map_vertices[1][end], map_vertices[2][end]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void generate_heightmap__circle(float* center_x, float* center_y,
|
||||
float* size, float* displacement)
|
||||
{
|
||||
float sign;
|
||||
/* random value for element in between [0-1.0] */
|
||||
*center_x = (MAP_SIZE * rand()) / (1.0f * RAND_MAX);
|
||||
*center_y = (MAP_SIZE * rand()) / (1.0f * RAND_MAX);
|
||||
*size = (MAX_CIRCLE_SIZE * rand()) / (1.0f * RAND_MAX);
|
||||
sign = (1.0f * rand()) / (1.0f * RAND_MAX);
|
||||
sign = (sign < DISPLACEMENT_SIGN_LIMIT) ? -1.0f : 1.0f;
|
||||
*displacement = (sign * (MAX_DISPLACEMENT * rand())) / (1.0f * RAND_MAX);
|
||||
}
|
||||
|
||||
/* Run the specified number of iterations of the generation process for the
|
||||
* heightmap
|
||||
*/
|
||||
static void update_map(int num_iter)
|
||||
{
|
||||
assert(num_iter > 0);
|
||||
while(num_iter)
|
||||
{
|
||||
/* center of the circle */
|
||||
float center_x;
|
||||
float center_z;
|
||||
float circle_size;
|
||||
float disp;
|
||||
size_t ii;
|
||||
generate_heightmap__circle(¢er_x, ¢er_z, &circle_size, &disp);
|
||||
disp = disp / 2.0f;
|
||||
for (ii = 0u ; ii < MAP_NUM_TOTAL_VERTICES ; ++ii)
|
||||
{
|
||||
GLfloat dx = center_x - map_vertices[0][ii];
|
||||
GLfloat dz = center_z - map_vertices[2][ii];
|
||||
GLfloat pd = (2.0f * (float) sqrt((dx * dx) + (dz * dz))) / circle_size;
|
||||
if (fabs(pd) <= 1.0f)
|
||||
{
|
||||
/* tx,tz is within the circle */
|
||||
GLfloat new_height = disp + (float) (cos(pd*3.14f)*disp);
|
||||
map_vertices[1][ii] += new_height;
|
||||
}
|
||||
}
|
||||
--num_iter;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* OpenGL helper functions
|
||||
*********************************************************************/
|
||||
|
||||
/* Create VBO, IBO and VAO objects for the heightmap geometry and bind them to
|
||||
* the specified program object
|
||||
*/
|
||||
static void make_mesh(GLuint program)
|
||||
{
|
||||
GLuint attrloc;
|
||||
|
||||
glGenVertexArrays(1, &mesh);
|
||||
glGenBuffers(4, mesh_vbo);
|
||||
glBindVertexArray(mesh);
|
||||
/* Prepare the data for drawing through a buffer inidices */
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh_vbo[3]);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)* MAP_NUM_LINES * 2, map_line_indices, GL_STATIC_DRAW);
|
||||
|
||||
/* Prepare the attributes for rendering */
|
||||
attrloc = glGetAttribLocation(program, "x");
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh_vbo[0]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * MAP_NUM_TOTAL_VERTICES, &map_vertices[0][0], GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(attrloc);
|
||||
glVertexAttribPointer(attrloc, 1, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
|
||||
attrloc = glGetAttribLocation(program, "z");
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh_vbo[2]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * MAP_NUM_TOTAL_VERTICES, &map_vertices[2][0], GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(attrloc);
|
||||
glVertexAttribPointer(attrloc, 1, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
|
||||
attrloc = glGetAttribLocation(program, "y");
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh_vbo[1]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * MAP_NUM_TOTAL_VERTICES, &map_vertices[1][0], GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(attrloc);
|
||||
glVertexAttribPointer(attrloc, 1, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
}
|
||||
|
||||
/* Update VBO vertices from source data
|
||||
*/
|
||||
static void update_mesh(void)
|
||||
{
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * MAP_NUM_TOTAL_VERTICES, &map_vertices[1][0]);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* GLFW callback functions
|
||||
*********************************************************************/
|
||||
|
||||
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
{
|
||||
switch(key)
|
||||
{
|
||||
case GLFW_KEY_ESCAPE:
|
||||
/* Exit program on Escape */
|
||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void error_callback(int error, const char* description)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", description);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
GLFWwindow* window;
|
||||
int iter;
|
||||
double dt;
|
||||
double last_update_time;
|
||||
int frame;
|
||||
float f;
|
||||
GLint uloc_modelview;
|
||||
GLint uloc_project;
|
||||
int width, height;
|
||||
|
||||
GLuint shader_program;
|
||||
|
||||
glfwSetErrorCallback(error_callback);
|
||||
|
||||
if (!glfwInit())
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
|
||||
|
||||
window = glfwCreateWindow(800, 600, "GLFW OpenGL3 Heightmap demo", NULL, NULL);
|
||||
if (! window )
|
||||
{
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Register events callback */
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
|
||||
|
||||
/* Prepare opengl resources for rendering */
|
||||
shader_program = make_shader_program(vertex_shader_text, fragment_shader_text);
|
||||
|
||||
if (shader_program == 0u)
|
||||
{
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
glUseProgram(shader_program);
|
||||
uloc_project = glGetUniformLocation(shader_program, "project");
|
||||
uloc_modelview = glGetUniformLocation(shader_program, "modelview");
|
||||
|
||||
/* Compute the projection matrix */
|
||||
f = 1.0f / tanf(view_angle / 2.0f);
|
||||
projection_matrix[0] = f / aspect_ratio;
|
||||
projection_matrix[5] = f;
|
||||
projection_matrix[10] = (z_far + z_near)/ (z_near - z_far);
|
||||
projection_matrix[11] = -1.0f;
|
||||
projection_matrix[14] = 2.0f * (z_far * z_near) / (z_near - z_far);
|
||||
glUniformMatrix4fv(uloc_project, 1, GL_FALSE, projection_matrix);
|
||||
|
||||
/* Set the camera position */
|
||||
modelview_matrix[12] = -5.0f;
|
||||
modelview_matrix[13] = -5.0f;
|
||||
modelview_matrix[14] = -20.0f;
|
||||
glUniformMatrix4fv(uloc_modelview, 1, GL_FALSE, modelview_matrix);
|
||||
|
||||
/* Create mesh data */
|
||||
init_map();
|
||||
make_mesh(shader_program);
|
||||
|
||||
/* Create vao + vbo to store the mesh */
|
||||
/* Create the vbo to store all the information for the grid and the height */
|
||||
|
||||
/* setup the scene ready for rendering */
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
glViewport(0, 0, width, height);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
/* main loop */
|
||||
frame = 0;
|
||||
iter = 0;
|
||||
last_update_time = glfwGetTime();
|
||||
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
++frame;
|
||||
/* render the next frame */
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glDrawElements(GL_LINES, 2* MAP_NUM_LINES , GL_UNSIGNED_INT, 0);
|
||||
|
||||
/* display and process events through callbacks */
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
/* Check the frame rate and update the heightmap if needed */
|
||||
dt = glfwGetTime();
|
||||
if ((dt - last_update_time) > 0.2)
|
||||
{
|
||||
/* generate the next iteration of the heightmap */
|
||||
if (iter < MAX_ITER)
|
||||
{
|
||||
update_map(NUM_ITER_AT_A_TIME);
|
||||
update_mesh();
|
||||
iter += NUM_ITER_AT_A_TIME;
|
||||
}
|
||||
last_update_time = dt;
|
||||
frame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
//========================================================================
|
||||
// Offscreen rendering example
|
||||
// Copyright (c) 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 <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#if USE_NATIVE_OSMESA
|
||||
#define GLFW_EXPOSE_NATIVE_OSMESA
|
||||
#include <GLFW/glfw3native.h>
|
||||
#endif
|
||||
|
||||
#include "linmath.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include <stb_image_write.h>
|
||||
|
||||
static const struct
|
||||
{
|
||||
float x, y;
|
||||
float r, g, b;
|
||||
} vertices[3] =
|
||||
{
|
||||
{ -0.6f, -0.4f, 1.f, 0.f, 0.f },
|
||||
{ 0.6f, -0.4f, 0.f, 1.f, 0.f },
|
||||
{ 0.f, 0.6f, 0.f, 0.f, 1.f }
|
||||
};
|
||||
|
||||
static const char* vertex_shader_text =
|
||||
"#version 110\n"
|
||||
"uniform mat4 MVP;\n"
|
||||
"attribute vec3 vCol;\n"
|
||||
"attribute vec2 vPos;\n"
|
||||
"varying vec3 color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
|
||||
" color = vCol;\n"
|
||||
"}\n";
|
||||
|
||||
static const char* fragment_shader_text =
|
||||
"#version 110\n"
|
||||
"varying vec3 color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_FragColor = vec4(color, 1.0);\n"
|
||||
"}\n";
|
||||
|
||||
static void error_callback(int error, const char* description)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", description);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
GLFWwindow* window;
|
||||
GLuint vertex_buffer, vertex_shader, fragment_shader, program;
|
||||
GLint mvp_location, vpos_location, vcol_location;
|
||||
float ratio;
|
||||
int width, height;
|
||||
mat4x4 mvp;
|
||||
char* buffer;
|
||||
|
||||
glfwSetErrorCallback(error_callback);
|
||||
|
||||
glfwInitHint(GLFW_COCOA_MENUBAR, GLFW_FALSE);
|
||||
|
||||
if (!glfwInit())
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||
|
||||
window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
|
||||
if (!window)
|
||||
{
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
|
||||
|
||||
// NOTE: OpenGL error checks have been omitted for brevity
|
||||
|
||||
glGenBuffers(1, &vertex_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
|
||||
glCompileShader(vertex_shader);
|
||||
|
||||
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
|
||||
glCompileShader(fragment_shader);
|
||||
|
||||
program = glCreateProgram();
|
||||
glAttachShader(program, vertex_shader);
|
||||
glAttachShader(program, fragment_shader);
|
||||
glLinkProgram(program);
|
||||
|
||||
mvp_location = glGetUniformLocation(program, "MVP");
|
||||
vpos_location = glGetAttribLocation(program, "vPos");
|
||||
vcol_location = glGetAttribLocation(program, "vCol");
|
||||
|
||||
glEnableVertexAttribArray(vpos_location);
|
||||
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
|
||||
sizeof(vertices[0]), (void*) 0);
|
||||
glEnableVertexAttribArray(vcol_location);
|
||||
glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,
|
||||
sizeof(vertices[0]), (void*) (sizeof(float) * 2));
|
||||
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
ratio = width / (float) height;
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
mat4x4_ortho(mvp, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);
|
||||
|
||||
glUseProgram(program);
|
||||
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
#if USE_NATIVE_OSMESA
|
||||
glfwGetOSMesaColorBuffer(window, &width, &height, NULL, (void**) &buffer);
|
||||
#else
|
||||
buffer = calloc(4, width * height);
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
||||
#endif
|
||||
|
||||
// Write image Y-flipped because OpenGL
|
||||
stbi_write_png("offscreen.png",
|
||||
width, height, 4,
|
||||
buffer + (width * 4 * (height - 1)),
|
||||
-width * 4);
|
||||
|
||||
#if USE_NATIVE_OSMESA
|
||||
// Here is where there's nothing
|
||||
#else
|
||||
free(buffer);
|
||||
#endif
|
||||
|
||||
glfwDestroyWindow(window);
|
||||
|
||||
glfwTerminate();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,165 @@
|
|||
//========================================================================
|
||||
// Simple GLFW example
|
||||
// Copyright (c) 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.
|
||||
//
|
||||
//========================================================================
|
||||
//! [code]
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "linmath.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static const struct
|
||||
{
|
||||
float x, y;
|
||||
float r, g, b;
|
||||
} vertices[3] =
|
||||
{
|
||||
{ -0.6f, -0.4f, 1.f, 0.f, 0.f },
|
||||
{ 0.6f, -0.4f, 0.f, 1.f, 0.f },
|
||||
{ 0.f, 0.6f, 0.f, 0.f, 1.f }
|
||||
};
|
||||
|
||||
static const char* vertex_shader_text =
|
||||
"#version 110\n"
|
||||
"uniform mat4 MVP;\n"
|
||||
"attribute vec3 vCol;\n"
|
||||
"attribute vec2 vPos;\n"
|
||||
"varying vec3 color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
|
||||
" color = vCol;\n"
|
||||
"}\n";
|
||||
|
||||
static const char* fragment_shader_text =
|
||||
"#version 110\n"
|
||||
"varying vec3 color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_FragColor = vec4(color, 1.0);\n"
|
||||
"}\n";
|
||||
|
||||
static void error_callback(int error, const char* description)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", description);
|
||||
}
|
||||
|
||||
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
{
|
||||
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
GLFWwindow* window;
|
||||
GLuint vertex_buffer, vertex_shader, fragment_shader, program;
|
||||
GLint mvp_location, vpos_location, vcol_location;
|
||||
|
||||
glfwSetErrorCallback(error_callback);
|
||||
|
||||
if (!glfwInit())
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
|
||||
window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
|
||||
if (!window)
|
||||
{
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
|
||||
glfwSwapInterval(1);
|
||||
|
||||
// NOTE: OpenGL error checks have been omitted for brevity
|
||||
|
||||
glGenBuffers(1, &vertex_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
|
||||
glCompileShader(vertex_shader);
|
||||
|
||||
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
|
||||
glCompileShader(fragment_shader);
|
||||
|
||||
program = glCreateProgram();
|
||||
glAttachShader(program, vertex_shader);
|
||||
glAttachShader(program, fragment_shader);
|
||||
glLinkProgram(program);
|
||||
|
||||
mvp_location = glGetUniformLocation(program, "MVP");
|
||||
vpos_location = glGetAttribLocation(program, "vPos");
|
||||
vcol_location = glGetAttribLocation(program, "vCol");
|
||||
|
||||
glEnableVertexAttribArray(vpos_location);
|
||||
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
|
||||
sizeof(vertices[0]), (void*) 0);
|
||||
glEnableVertexAttribArray(vcol_location);
|
||||
glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,
|
||||
sizeof(vertices[0]), (void*) (sizeof(float) * 2));
|
||||
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
float ratio;
|
||||
int width, height;
|
||||
mat4x4 m, p, mvp;
|
||||
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
ratio = width / (float) height;
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
mat4x4_identity(m);
|
||||
mat4x4_rotate_Z(m, m, (float) glfwGetTime());
|
||||
mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);
|
||||
mat4x4_mul(mvp, p, m);
|
||||
|
||||
glUseProgram(program);
|
||||
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
glfwDestroyWindow(window);
|
||||
|
||||
glfwTerminate();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
//! [code]
|
|
@ -0,0 +1,545 @@
|
|||
//========================================================================
|
||||
// This is an example program for the GLFW library
|
||||
//
|
||||
// The program uses a "split window" view, rendering four views of the
|
||||
// same scene in one window (e.g. uesful for 3D modelling software). This
|
||||
// demo uses scissors to separete the four different rendering areas from
|
||||
// each other.
|
||||
//
|
||||
// (If the code seems a little bit strange here and there, it may be
|
||||
// because I am not a friend of orthogonal projections)
|
||||
//========================================================================
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Make MS math.h define M_PI
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <linmath.h>
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Global variables
|
||||
//========================================================================
|
||||
|
||||
// Mouse position
|
||||
static double xpos = 0, ypos = 0;
|
||||
|
||||
// Window size
|
||||
static int width, height;
|
||||
|
||||
// Active view: 0 = none, 1 = upper left, 2 = upper right, 3 = lower left,
|
||||
// 4 = lower right
|
||||
static int active_view = 0;
|
||||
|
||||
// Rotation around each axis
|
||||
static int rot_x = 0, rot_y = 0, rot_z = 0;
|
||||
|
||||
// Do redraw?
|
||||
static int do_redraw = 1;
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Draw a solid torus (use a display list for the model)
|
||||
//========================================================================
|
||||
|
||||
#define TORUS_MAJOR 1.5
|
||||
#define TORUS_MINOR 0.5
|
||||
#define TORUS_MAJOR_RES 32
|
||||
#define TORUS_MINOR_RES 32
|
||||
|
||||
static void drawTorus(void)
|
||||
{
|
||||
static GLuint torus_list = 0;
|
||||
int i, j, k;
|
||||
double s, t, x, y, z, nx, ny, nz, scale, twopi;
|
||||
|
||||
if (!torus_list)
|
||||
{
|
||||
// Start recording displaylist
|
||||
torus_list = glGenLists(1);
|
||||
glNewList(torus_list, GL_COMPILE_AND_EXECUTE);
|
||||
|
||||
// Draw torus
|
||||
twopi = 2.0 * M_PI;
|
||||
for (i = 0; i < TORUS_MINOR_RES; i++)
|
||||
{
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (j = 0; j <= TORUS_MAJOR_RES; j++)
|
||||
{
|
||||
for (k = 1; k >= 0; k--)
|
||||
{
|
||||
s = (i + k) % TORUS_MINOR_RES + 0.5;
|
||||
t = j % TORUS_MAJOR_RES;
|
||||
|
||||
// Calculate point on surface
|
||||
x = (TORUS_MAJOR + TORUS_MINOR * cos(s * twopi / TORUS_MINOR_RES)) * cos(t * twopi / TORUS_MAJOR_RES);
|
||||
y = TORUS_MINOR * sin(s * twopi / TORUS_MINOR_RES);
|
||||
z = (TORUS_MAJOR + TORUS_MINOR * cos(s * twopi / TORUS_MINOR_RES)) * sin(t * twopi / TORUS_MAJOR_RES);
|
||||
|
||||
// Calculate surface normal
|
||||
nx = x - TORUS_MAJOR * cos(t * twopi / TORUS_MAJOR_RES);
|
||||
ny = y;
|
||||
nz = z - TORUS_MAJOR * sin(t * twopi / TORUS_MAJOR_RES);
|
||||
scale = 1.0 / sqrt(nx*nx + ny*ny + nz*nz);
|
||||
nx *= scale;
|
||||
ny *= scale;
|
||||
nz *= scale;
|
||||
|
||||
glNormal3f((float) nx, (float) ny, (float) nz);
|
||||
glVertex3f((float) x, (float) y, (float) z);
|
||||
}
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
// Stop recording displaylist
|
||||
glEndList();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Playback displaylist
|
||||
glCallList(torus_list);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Draw the scene (a rotating torus)
|
||||
//========================================================================
|
||||
|
||||
static void drawScene(void)
|
||||
{
|
||||
const GLfloat model_diffuse[4] = {1.0f, 0.8f, 0.8f, 1.0f};
|
||||
const GLfloat model_specular[4] = {0.6f, 0.6f, 0.6f, 1.0f};
|
||||
const GLfloat model_shininess = 20.0f;
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
// Rotate the object
|
||||
glRotatef((GLfloat) rot_x * 0.5f, 1.0f, 0.0f, 0.0f);
|
||||
glRotatef((GLfloat) rot_y * 0.5f, 0.0f, 1.0f, 0.0f);
|
||||
glRotatef((GLfloat) rot_z * 0.5f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
// Set model color (used for orthogonal views, lighting disabled)
|
||||
glColor4fv(model_diffuse);
|
||||
|
||||
// Set model material (used for perspective view, lighting enabled)
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, model_diffuse);
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, model_specular);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, model_shininess);
|
||||
|
||||
// Draw torus
|
||||
drawTorus();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Draw a 2D grid (used for orthogonal views)
|
||||
//========================================================================
|
||||
|
||||
static void drawGrid(float scale, int steps)
|
||||
{
|
||||
int i;
|
||||
float x, y;
|
||||
mat4x4 view;
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
// Set background to some dark bluish grey
|
||||
glClearColor(0.05f, 0.05f, 0.2f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Setup modelview matrix (flat XY view)
|
||||
{
|
||||
vec3 eye = { 0.f, 0.f, 1.f };
|
||||
vec3 center = { 0.f, 0.f, 0.f };
|
||||
vec3 up = { 0.f, 1.f, 0.f };
|
||||
mat4x4_look_at(view, eye, center, up);
|
||||
}
|
||||
glLoadMatrixf((const GLfloat*) view);
|
||||
|
||||
// We don't want to update the Z-buffer
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
// Set grid color
|
||||
glColor3f(0.0f, 0.5f, 0.5f);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
|
||||
// Horizontal lines
|
||||
x = scale * 0.5f * (float) (steps - 1);
|
||||
y = -scale * 0.5f * (float) (steps - 1);
|
||||
for (i = 0; i < steps; i++)
|
||||
{
|
||||
glVertex3f(-x, y, 0.0f);
|
||||
glVertex3f(x, y, 0.0f);
|
||||
y += scale;
|
||||
}
|
||||
|
||||
// Vertical lines
|
||||
x = -scale * 0.5f * (float) (steps - 1);
|
||||
y = scale * 0.5f * (float) (steps - 1);
|
||||
for (i = 0; i < steps; i++)
|
||||
{
|
||||
glVertex3f(x, -y, 0.0f);
|
||||
glVertex3f(x, y, 0.0f);
|
||||
x += scale;
|
||||
}
|
||||
|
||||
glEnd();
|
||||
|
||||
// Enable Z-buffer writing again
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Draw all views
|
||||
//========================================================================
|
||||
|
||||
static void drawAllViews(void)
|
||||
{
|
||||
const GLfloat light_position[4] = {0.0f, 8.0f, 8.0f, 1.0f};
|
||||
const GLfloat light_diffuse[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
const GLfloat light_specular[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
const GLfloat light_ambient[4] = {0.2f, 0.2f, 0.3f, 1.0f};
|
||||
float aspect;
|
||||
mat4x4 view, projection;
|
||||
|
||||
// Calculate aspect of window
|
||||
if (height > 0)
|
||||
aspect = (float) width / (float) height;
|
||||
else
|
||||
aspect = 1.f;
|
||||
|
||||
// Clear screen
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Enable scissor test
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
// Enable depth test
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
// ** ORTHOGONAL VIEWS **
|
||||
|
||||
// For orthogonal views, use wireframe rendering
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
// Enable line anti-aliasing
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// Setup orthogonal projection matrix
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(-3.0 * aspect, 3.0 * aspect, -3.0, 3.0, 1.0, 50.0);
|
||||
|
||||
// Upper left view (TOP VIEW)
|
||||
glViewport(0, height / 2, width / 2, height / 2);
|
||||
glScissor(0, height / 2, width / 2, height / 2);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
{
|
||||
vec3 eye = { 0.f, 10.f, 1e-3f };
|
||||
vec3 center = { 0.f, 0.f, 0.f };
|
||||
vec3 up = { 0.f, 1.f, 0.f };
|
||||
mat4x4_look_at( view, eye, center, up );
|
||||
}
|
||||
glLoadMatrixf((const GLfloat*) view);
|
||||
drawGrid(0.5, 12);
|
||||
drawScene();
|
||||
|
||||
// Lower left view (FRONT VIEW)
|
||||
glViewport(0, 0, width / 2, height / 2);
|
||||
glScissor(0, 0, width / 2, height / 2);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
{
|
||||
vec3 eye = { 0.f, 0.f, 10.f };
|
||||
vec3 center = { 0.f, 0.f, 0.f };
|
||||
vec3 up = { 0.f, 1.f, 0.f };
|
||||
mat4x4_look_at( view, eye, center, up );
|
||||
}
|
||||
glLoadMatrixf((const GLfloat*) view);
|
||||
drawGrid(0.5, 12);
|
||||
drawScene();
|
||||
|
||||
// Lower right view (SIDE VIEW)
|
||||
glViewport(width / 2, 0, width / 2, height / 2);
|
||||
glScissor(width / 2, 0, width / 2, height / 2);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
{
|
||||
vec3 eye = { 10.f, 0.f, 0.f };
|
||||
vec3 center = { 0.f, 0.f, 0.f };
|
||||
vec3 up = { 0.f, 1.f, 0.f };
|
||||
mat4x4_look_at( view, eye, center, up );
|
||||
}
|
||||
glLoadMatrixf((const GLfloat*) view);
|
||||
drawGrid(0.5, 12);
|
||||
drawScene();
|
||||
|
||||
// Disable line anti-aliasing
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
// ** PERSPECTIVE VIEW **
|
||||
|
||||
// For perspective view, use solid rendering
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
// Enable face culling (faster rendering)
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
glFrontFace(GL_CW);
|
||||
|
||||
// Setup perspective projection matrix
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
mat4x4_perspective(projection,
|
||||
65.f * (float) M_PI / 180.f,
|
||||
aspect,
|
||||
1.f, 50.f);
|
||||
glLoadMatrixf((const GLfloat*) projection);
|
||||
|
||||
// Upper right view (PERSPECTIVE VIEW)
|
||||
glViewport(width / 2, height / 2, width / 2, height / 2);
|
||||
glScissor(width / 2, height / 2, width / 2, height / 2);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
{
|
||||
vec3 eye = { 3.f, 1.5f, 3.f };
|
||||
vec3 center = { 0.f, 0.f, 0.f };
|
||||
vec3 up = { 0.f, 1.f, 0.f };
|
||||
mat4x4_look_at( view, eye, center, up );
|
||||
}
|
||||
glLoadMatrixf((const GLfloat*) view);
|
||||
|
||||
// Configure and enable light source 1
|
||||
glLightfv(GL_LIGHT1, GL_POSITION, light_position);
|
||||
glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
|
||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
|
||||
glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
|
||||
glEnable(GL_LIGHT1);
|
||||
glEnable(GL_LIGHTING);
|
||||
|
||||
// Draw scene
|
||||
drawScene();
|
||||
|
||||
// Disable lighting
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
// Disable face culling
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
// Disable depth test
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
// Disable scissor test
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
// Draw a border around the active view
|
||||
if (active_view > 0 && active_view != 2)
|
||||
{
|
||||
glViewport(0, 0, width, height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0.0, 2.0, 0.0, 2.0, 0.0, 1.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef((GLfloat) ((active_view - 1) & 1), (GLfloat) (1 - (active_view - 1) / 2), 0.0f);
|
||||
|
||||
glColor3f(1.0f, 1.0f, 0.6f);
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex2i(0, 0);
|
||||
glVertex2i(1, 0);
|
||||
glVertex2i(1, 1);
|
||||
glVertex2i(0, 1);
|
||||
glVertex2i(0, 0);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Framebuffer size callback function
|
||||
//========================================================================
|
||||
|
||||
static void framebufferSizeFun(GLFWwindow* window, int w, int h)
|
||||
{
|
||||
width = w;
|
||||
height = h > 0 ? h : 1;
|
||||
do_redraw = 1;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Window refresh callback function
|
||||
//========================================================================
|
||||
|
||||
static void windowRefreshFun(GLFWwindow* window)
|
||||
{
|
||||
drawAllViews();
|
||||
glfwSwapBuffers(window);
|
||||
do_redraw = 0;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Mouse position callback function
|
||||
//========================================================================
|
||||
|
||||
static void cursorPosFun(GLFWwindow* window, double x, double y)
|
||||
{
|
||||
int wnd_width, wnd_height, fb_width, fb_height;
|
||||
double scale;
|
||||
|
||||
glfwGetWindowSize(window, &wnd_width, &wnd_height);
|
||||
glfwGetFramebufferSize(window, &fb_width, &fb_height);
|
||||
|
||||
scale = (double) fb_width / (double) wnd_width;
|
||||
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
|
||||
// Depending on which view was selected, rotate around different axes
|
||||
switch (active_view)
|
||||
{
|
||||
case 1:
|
||||
rot_x += (int) (y - ypos);
|
||||
rot_z += (int) (x - xpos);
|
||||
do_redraw = 1;
|
||||
break;
|
||||
case 3:
|
||||
rot_x += (int) (y - ypos);
|
||||
rot_y += (int) (x - xpos);
|
||||
do_redraw = 1;
|
||||
break;
|
||||
case 4:
|
||||
rot_y += (int) (x - xpos);
|
||||
rot_z += (int) (y - ypos);
|
||||
do_redraw = 1;
|
||||
break;
|
||||
default:
|
||||
// Do nothing for perspective view, or if no view is selected
|
||||
break;
|
||||
}
|
||||
|
||||
// Remember cursor position
|
||||
xpos = x;
|
||||
ypos = y;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Mouse button callback function
|
||||
//========================================================================
|
||||
|
||||
static void mouseButtonFun(GLFWwindow* window, int button, int action, int mods)
|
||||
{
|
||||
if ((button == GLFW_MOUSE_BUTTON_LEFT) && action == GLFW_PRESS)
|
||||
{
|
||||
// Detect which of the four views was clicked
|
||||
active_view = 1;
|
||||
if (xpos >= width / 2)
|
||||
active_view += 1;
|
||||
if (ypos >= height / 2)
|
||||
active_view += 2;
|
||||
}
|
||||
else if (button == GLFW_MOUSE_BUTTON_LEFT)
|
||||
{
|
||||
// Deselect any previously selected view
|
||||
active_view = 0;
|
||||
}
|
||||
|
||||
do_redraw = 1;
|
||||
}
|
||||
|
||||
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
{
|
||||
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// main
|
||||
//========================================================================
|
||||
|
||||
int main(void)
|
||||
{
|
||||
GLFWwindow* window;
|
||||
|
||||
// Initialise GLFW
|
||||
if (!glfwInit())
|
||||
{
|
||||
fprintf(stderr, "Failed to initialize GLFW\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_SAMPLES, 4);
|
||||
|
||||
// Open OpenGL window
|
||||
window = glfwCreateWindow(500, 500, "Split view demo", NULL, NULL);
|
||||
if (!window)
|
||||
{
|
||||
fprintf(stderr, "Failed to open GLFW window\n");
|
||||
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Set callback functions
|
||||
glfwSetFramebufferSizeCallback(window, framebufferSizeFun);
|
||||
glfwSetWindowRefreshCallback(window, windowRefreshFun);
|
||||
glfwSetCursorPosCallback(window, cursorPosFun);
|
||||
glfwSetMouseButtonCallback(window, mouseButtonFun);
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
|
||||
// Enable vsync
|
||||
glfwMakeContextCurrent(window);
|
||||
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
|
||||
glfwSwapInterval(1);
|
||||
|
||||
if (GLAD_GL_ARB_multisample || GLAD_GL_VERSION_1_3)
|
||||
glEnable(GL_MULTISAMPLE_ARB);
|
||||
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
framebufferSizeFun(window, width, height);
|
||||
|
||||
// Main loop
|
||||
for (;;)
|
||||
{
|
||||
// Only redraw if we need to
|
||||
if (do_redraw)
|
||||
windowRefreshFun(window);
|
||||
|
||||
// Wait for new events
|
||||
glfwWaitEvents();
|
||||
|
||||
// Check if the window should be closed
|
||||
if (glfwWindowShouldClose(window))
|
||||
break;
|
||||
}
|
||||
|
||||
// Close OpenGL window and terminate GLFW
|
||||
glfwTerminate();
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
|
@ -0,0 +1,460 @@
|
|||
/*****************************************************************************
|
||||
* Wave Simulation in OpenGL
|
||||
* (C) 2002 Jakob Thomsen
|
||||
* http://home.in.tum.de/~thomsen
|
||||
* Modified for GLFW by Sylvain Hellegouarch - sh@programmationworld.com
|
||||
* Modified for variable frame rate by Marcus Geelnard
|
||||
* 2003-Jan-31: Minor cleanups and speedups / MG
|
||||
* 2010-10-24: Formatting and cleanup - Camilla Löwy
|
||||
*****************************************************************************/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Make MS math.h define M_PI
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <linmath.h>
|
||||
|
||||
// Maximum delta T to allow for differential calculations
|
||||
#define MAX_DELTA_T 0.01
|
||||
|
||||
// Animation speed (10.0 looks good)
|
||||
#define ANIMATION_SPEED 10.0
|
||||
|
||||
GLfloat alpha = 210.f, beta = -70.f;
|
||||
GLfloat zoom = 2.f;
|
||||
|
||||
double cursorX;
|
||||
double cursorY;
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
GLfloat x, y, z;
|
||||
GLfloat r, g, b;
|
||||
};
|
||||
|
||||
#define GRIDW 50
|
||||
#define GRIDH 50
|
||||
#define VERTEXNUM (GRIDW*GRIDH)
|
||||
|
||||
#define QUADW (GRIDW - 1)
|
||||
#define QUADH (GRIDH - 1)
|
||||
#define QUADNUM (QUADW*QUADH)
|
||||
|
||||
GLuint quad[4 * QUADNUM];
|
||||
struct Vertex vertex[VERTEXNUM];
|
||||
|
||||
/* The grid will look like this:
|
||||
*
|
||||
* 3 4 5
|
||||
* *---*---*
|
||||
* | | |
|
||||
* | 0 | 1 |
|
||||
* | | |
|
||||
* *---*---*
|
||||
* 0 1 2
|
||||
*/
|
||||
|
||||
//========================================================================
|
||||
// Initialize grid geometry
|
||||
//========================================================================
|
||||
|
||||
void init_vertices(void)
|
||||
{
|
||||
int x, y, p;
|
||||
|
||||
// Place the vertices in a grid
|
||||
for (y = 0; y < GRIDH; y++)
|
||||
{
|
||||
for (x = 0; x < GRIDW; x++)
|
||||
{
|
||||
p = y * GRIDW + x;
|
||||
|
||||
vertex[p].x = (GLfloat) (x - GRIDW / 2) / (GLfloat) (GRIDW / 2);
|
||||
vertex[p].y = (GLfloat) (y - GRIDH / 2) / (GLfloat) (GRIDH / 2);
|
||||
vertex[p].z = 0;
|
||||
|
||||
if ((x % 4 < 2) ^ (y % 4 < 2))
|
||||
vertex[p].r = 0.0;
|
||||
else
|
||||
vertex[p].r = 1.0;
|
||||
|
||||
vertex[p].g = (GLfloat) y / (GLfloat) GRIDH;
|
||||
vertex[p].b = 1.f - ((GLfloat) x / (GLfloat) GRIDW + (GLfloat) y / (GLfloat) GRIDH) / 2.f;
|
||||
}
|
||||
}
|
||||
|
||||
for (y = 0; y < QUADH; y++)
|
||||
{
|
||||
for (x = 0; x < QUADW; x++)
|
||||
{
|
||||
p = 4 * (y * QUADW + x);
|
||||
|
||||
quad[p + 0] = y * GRIDW + x; // Some point
|
||||
quad[p + 1] = y * GRIDW + x + 1; // Neighbor at the right side
|
||||
quad[p + 2] = (y + 1) * GRIDW + x + 1; // Upper right neighbor
|
||||
quad[p + 3] = (y + 1) * GRIDW + x; // Upper neighbor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double dt;
|
||||
double p[GRIDW][GRIDH];
|
||||
double vx[GRIDW][GRIDH], vy[GRIDW][GRIDH];
|
||||
double ax[GRIDW][GRIDH], ay[GRIDW][GRIDH];
|
||||
|
||||
//========================================================================
|
||||
// Initialize grid
|
||||
//========================================================================
|
||||
|
||||
void init_grid(void)
|
||||
{
|
||||
int x, y;
|
||||
double dx, dy, d;
|
||||
|
||||
for (y = 0; y < GRIDH; y++)
|
||||
{
|
||||
for (x = 0; x < GRIDW; x++)
|
||||
{
|
||||
dx = (double) (x - GRIDW / 2);
|
||||
dy = (double) (y - GRIDH / 2);
|
||||
d = sqrt(dx * dx + dy * dy);
|
||||
if (d < 0.1 * (double) (GRIDW / 2))
|
||||
{
|
||||
d = d * 10.0;
|
||||
p[x][y] = -cos(d * (M_PI / (double)(GRIDW * 4))) * 100.0;
|
||||
}
|
||||
else
|
||||
p[x][y] = 0.0;
|
||||
|
||||
vx[x][y] = 0.0;
|
||||
vy[x][y] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Draw scene
|
||||
//========================================================================
|
||||
|
||||
void draw_scene(GLFWwindow* window)
|
||||
{
|
||||
// Clear the color and depth buffers
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// We don't want to modify the projection matrix
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
// Move back
|
||||
glTranslatef(0.0, 0.0, -zoom);
|
||||
// Rotate the view
|
||||
glRotatef(beta, 1.0, 0.0, 0.0);
|
||||
glRotatef(alpha, 0.0, 0.0, 1.0);
|
||||
|
||||
glDrawElements(GL_QUADS, 4 * QUADNUM, GL_UNSIGNED_INT, quad);
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Initialize Miscellaneous OpenGL state
|
||||
//========================================================================
|
||||
|
||||
void init_opengl(void)
|
||||
{
|
||||
// Use Gouraud (smooth) shading
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
// Switch on the z-buffer
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(struct Vertex), vertex);
|
||||
glColorPointer(3, GL_FLOAT, sizeof(struct Vertex), &vertex[0].r); // Pointer to the first color
|
||||
|
||||
glPointSize(2.0);
|
||||
|
||||
// Background color is black
|
||||
glClearColor(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Modify the height of each vertex according to the pressure
|
||||
//========================================================================
|
||||
|
||||
void adjust_grid(void)
|
||||
{
|
||||
int pos;
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < GRIDH; y++)
|
||||
{
|
||||
for (x = 0; x < GRIDW; x++)
|
||||
{
|
||||
pos = y * GRIDW + x;
|
||||
vertex[pos].z = (float) (p[x][y] * (1.0 / 50.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Calculate wave propagation
|
||||
//========================================================================
|
||||
|
||||
void calc_grid(void)
|
||||
{
|
||||
int x, y, x2, y2;
|
||||
double time_step = dt * ANIMATION_SPEED;
|
||||
|
||||
// Compute accelerations
|
||||
for (x = 0; x < GRIDW; x++)
|
||||
{
|
||||
x2 = (x + 1) % GRIDW;
|
||||
for(y = 0; y < GRIDH; y++)
|
||||
ax[x][y] = p[x][y] - p[x2][y];
|
||||
}
|
||||
|
||||
for (y = 0; y < GRIDH; y++)
|
||||
{
|
||||
y2 = (y + 1) % GRIDH;
|
||||
for(x = 0; x < GRIDW; x++)
|
||||
ay[x][y] = p[x][y] - p[x][y2];
|
||||
}
|
||||
|
||||
// Compute speeds
|
||||
for (x = 0; x < GRIDW; x++)
|
||||
{
|
||||
for (y = 0; y < GRIDH; y++)
|
||||
{
|
||||
vx[x][y] = vx[x][y] + ax[x][y] * time_step;
|
||||
vy[x][y] = vy[x][y] + ay[x][y] * time_step;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute pressure
|
||||
for (x = 1; x < GRIDW; x++)
|
||||
{
|
||||
x2 = x - 1;
|
||||
for (y = 1; y < GRIDH; y++)
|
||||
{
|
||||
y2 = y - 1;
|
||||
p[x][y] = p[x][y] + (vx[x2][y] - vx[x][y] + vy[x][y2] - vy[x][y]) * time_step;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Print errors
|
||||
//========================================================================
|
||||
|
||||
static void error_callback(int error, const char* description)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", description);
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Handle key strokes
|
||||
//========================================================================
|
||||
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
{
|
||||
if (action != GLFW_PRESS)
|
||||
return;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case GLFW_KEY_ESCAPE:
|
||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||
break;
|
||||
case GLFW_KEY_SPACE:
|
||||
init_grid();
|
||||
break;
|
||||
case GLFW_KEY_LEFT:
|
||||
alpha += 5;
|
||||
break;
|
||||
case GLFW_KEY_RIGHT:
|
||||
alpha -= 5;
|
||||
break;
|
||||
case GLFW_KEY_UP:
|
||||
beta -= 5;
|
||||
break;
|
||||
case GLFW_KEY_DOWN:
|
||||
beta += 5;
|
||||
break;
|
||||
case GLFW_KEY_PAGE_UP:
|
||||
zoom -= 0.25f;
|
||||
if (zoom < 0.f)
|
||||
zoom = 0.f;
|
||||
break;
|
||||
case GLFW_KEY_PAGE_DOWN:
|
||||
zoom += 0.25f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Callback function for mouse button events
|
||||
//========================================================================
|
||||
|
||||
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
|
||||
{
|
||||
if (button != GLFW_MOUSE_BUTTON_LEFT)
|
||||
return;
|
||||
|
||||
if (action == GLFW_PRESS)
|
||||
{
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
glfwGetCursorPos(window, &cursorX, &cursorY);
|
||||
}
|
||||
else
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Callback function for cursor motion events
|
||||
//========================================================================
|
||||
|
||||
void cursor_position_callback(GLFWwindow* window, double x, double y)
|
||||
{
|
||||
if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
alpha += (GLfloat) (x - cursorX) / 10.f;
|
||||
beta += (GLfloat) (y - cursorY) / 10.f;
|
||||
|
||||
cursorX = x;
|
||||
cursorY = y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Callback function for scroll events
|
||||
//========================================================================
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double x, double y)
|
||||
{
|
||||
zoom += (float) y / 4.f;
|
||||
if (zoom < 0)
|
||||
zoom = 0;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Callback function for framebuffer resize events
|
||||
//========================================================================
|
||||
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
||||
{
|
||||
float ratio = 1.f;
|
||||
mat4x4 projection;
|
||||
|
||||
if (height > 0)
|
||||
ratio = (float) width / (float) height;
|
||||
|
||||
// Setup viewport
|
||||
glViewport(0, 0, width, height);
|
||||
|
||||
// Change to the projection matrix and set our viewing volume
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
mat4x4_perspective(projection,
|
||||
60.f * (float) M_PI / 180.f,
|
||||
ratio,
|
||||
1.f, 1024.f);
|
||||
glLoadMatrixf((const GLfloat*) projection);
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// main
|
||||
//========================================================================
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
GLFWwindow* window;
|
||||
double t, dt_total, t_old;
|
||||
int width, height;
|
||||
|
||||
glfwSetErrorCallback(error_callback);
|
||||
|
||||
if (!glfwInit())
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
window = glfwCreateWindow(640, 480, "Wave Simulation", NULL, NULL);
|
||||
if (!window)
|
||||
{
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
glfwSetKeyCallback(window, key_callback);
|
||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||
glfwSetMouseButtonCallback(window, mouse_button_callback);
|
||||
glfwSetCursorPosCallback(window, cursor_position_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
|
||||
glfwSwapInterval(1);
|
||||
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
framebuffer_size_callback(window, width, height);
|
||||
|
||||
// Initialize OpenGL
|
||||
init_opengl();
|
||||
|
||||
// Initialize simulation
|
||||
init_vertices();
|
||||
init_grid();
|
||||
adjust_grid();
|
||||
|
||||
// Initialize timer
|
||||
t_old = glfwGetTime() - 0.01;
|
||||
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
t = glfwGetTime();
|
||||
dt_total = t - t_old;
|
||||
t_old = t;
|
||||
|
||||
// Safety - iterate if dt_total is too large
|
||||
while (dt_total > 0.f)
|
||||
{
|
||||
// Select iteration time step
|
||||
dt = dt_total > MAX_DELTA_T ? MAX_DELTA_T : dt_total;
|
||||
dt_total -= dt;
|
||||
|
||||
// Calculate wave propagation
|
||||
calc_grid();
|
||||
}
|
||||
|
||||
// Compute height of each vertex
|
||||
adjust_grid();
|
||||
|
||||
// Draw wave grid to OpenGL display
|
||||
draw_scene(window);
|
||||
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,519 @@
|
|||
/*************************************************************************
|
||||
* GLFW 3.3 - www.glfw.org
|
||||
* A library for OpenGL, window and input
|
||||
*------------------------------------------------------------------------
|
||||
* 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.
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
#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`
|
||||
* * `GLFW_EXPOSE_NATIVE_MIR`
|
||||
*
|
||||
* 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)
|
||||
// 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
|
||||
#include <windows.h>
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_COCOA)
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#if defined(__OBJC__)
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#else
|
||||
typedef void* id;
|
||||
#endif
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_X11)
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
|
||||
#include <wayland-client.h>
|
||||
#elif defined(GLFW_EXPOSE_NATIVE_MIR)
|
||||
#include <mir_toolkit/mir_client_library.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);
|
||||
#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_MIR)
|
||||
/*! @brief Returns the `MirConnection*` used by GLFW.
|
||||
*
|
||||
* @return The `MirConnection*` 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 MirConnection* glfwGetMirDisplay(void);
|
||||
|
||||
/*! @brief Returns the Mir output ID of the specified monitor.
|
||||
*
|
||||
* @return The Mir output ID of the specified monitor, or zero 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 int glfwGetMirMonitor(GLFWmonitor* monitor);
|
||||
|
||||
/*! @brief Returns the `MirWindow*` of the specified window.
|
||||
*
|
||||
* @return The `MirWindow*` 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 MirWindow* glfwGetMirWindow(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,134 @@
|
|||
|
||||
set(common_HEADERS internal.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_tls.h nsgl_context.h egl_context.h osmesa_context.c)
|
||||
set(glfw_SOURCES ${common_SOURCES} cocoa_init.m cocoa_joystick.m
|
||||
cocoa_monitor.m cocoa_window.m cocoa_time.c posix_tls.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_tls.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_tls.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_tls.c glx_context.c
|
||||
egl_context.c osmesa_context.c)
|
||||
|
||||
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()
|
||||
elseif (_GLFW_WAYLAND)
|
||||
set(glfw_HEADERS ${common_HEADERS} wl_platform.h linux_joystick.h
|
||||
posix_time.h posix_tls.h xkb_unicode.h egl_context.h
|
||||
osmesa_context.h)
|
||||
set(glfw_SOURCES ${common_SOURCES} wl_init.c wl_monitor.c wl_window.c
|
||||
linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c
|
||||
egl_context.c osmesa_context.c)
|
||||
|
||||
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)
|
||||
elseif (_GLFW_MIR)
|
||||
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
|
||||
posix_time.h posix_tls.h xkb_unicode.h egl_context.h
|
||||
osmesa_context.h)
|
||||
set(glfw_SOURCES ${common_SOURCES} mir_init.c mir_monitor.c mir_window.c
|
||||
linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c
|
||||
egl_context.c osmesa_context.c)
|
||||
elseif (_GLFW_OSMESA)
|
||||
set(glfw_HEADERS ${common_HEADERS} null_platform.h null_joystick.h
|
||||
posix_time.h posix_tls.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_tls.c osmesa_context.c)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
# For some reason, CMake doesn't know about .m
|
||||
set_source_files_properties(${glfw_SOURCES} PROPERTIES LANGUAGE C)
|
||||
endif()
|
||||
|
||||
add_library(glfw ${glfw_SOURCES} ${glfw_HEADERS})
|
||||
set_target_properties(glfw PROPERTIES
|
||||
OUTPUT_NAME ${GLFW_LIB_NAME}
|
||||
VERSION ${GLFW_VERSION}
|
||||
SOVERSION ${GLFW_VERSION_MAJOR}
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
FOLDER "GLFW3")
|
||||
|
||||
target_compile_definitions(glfw PRIVATE -D_GLFW_USE_CONFIG_H)
|
||||
target_include_directories(glfw PUBLIC
|
||||
$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>)
|
||||
target_include_directories(glfw PRIVATE
|
||||
"${GLFW_SOURCE_DIR}/src"
|
||||
"${GLFW_BINARY_DIR}/src"
|
||||
${glfw_INCLUDE_DIRS})
|
||||
|
||||
# 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.
|
||||
target_compile_definitions(glfw PRIVATE
|
||||
"$<$<BOOL:${MINGW}>:UNICODE;WINVER=0x0501>")
|
||||
|
||||
# Enable a reasonable set of warnings (no, -Wextra is not reasonable)
|
||||
target_compile_options(glfw PRIVATE
|
||||
"$<$<C_COMPILER_ID:Clang>:-Wall>"
|
||||
"$<$<C_COMPILER_ID:GNU>:-Wall>")
|
||||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
if (WIN32)
|
||||
if (MINGW)
|
||||
# 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()
|
||||
elseif (APPLE)
|
||||
# Add -fno-common to work around a bug in Apple's GCC
|
||||
target_compile_options(glfw PRIVATE "-fno-common")
|
||||
|
||||
set_target_properties(glfw PROPERTIES
|
||||
INSTALL_NAME_DIR "lib${LIB_SUFFIX}")
|
||||
elseif (UNIX)
|
||||
# Hide symbols not explicitly tagged for export from the shared library
|
||||
target_compile_options(glfw PRIVATE "-fvisibility=hidden")
|
||||
endif()
|
||||
|
||||
target_compile_definitions(glfw INTERFACE -DGLFW_DLL)
|
||||
target_link_libraries(glfw PRIVATE ${glfw_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(glfw INTERFACE ${glfw_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
target_compile_definitions(glfw PRIVATE _CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
if (GLFW_INSTALL)
|
||||
install(TARGETS glfw EXPORT glfwTargets DESTINATION lib${LIB_SUFFIX})
|
||||
endif()
|
||||
|
|
@ -0,0 +1,375 @@
|
|||
//========================================================================
|
||||
// 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
#include <sys/param.h> // For MAXPATHLEN
|
||||
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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 GLFWLayoutListener : NSObject
|
||||
@end
|
||||
|
||||
@implementation GLFWLayoutListener
|
||||
|
||||
- (void)selectedKeyboardInputSourceChanged:(NSObject* )object
|
||||
{
|
||||
updateUnicodeDataNS();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformInit(void)
|
||||
{
|
||||
_glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if (_glfw.hints.init.ns.chdir)
|
||||
changeToResourcesDirectory();
|
||||
|
||||
_glfw.ns.listener = [[GLFWLayoutListener alloc] init];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:_glfw.ns.listener
|
||||
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;
|
||||
}
|
||||
|
||||
void _glfwPlatformTerminate(void)
|
||||
{
|
||||
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.listener)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
removeObserver:_glfw.ns.listener
|
||||
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
removeObserver:_glfw.ns.listener];
|
||||
[_glfw.ns.listener release];
|
||||
_glfw.ns.listener = nil;
|
||||
}
|
||||
|
||||
[_glfw.ns.cursor release];
|
||||
_glfw.ns.cursor = nil;
|
||||
|
||||
free(_glfw.ns.clipboardString);
|
||||
|
||||
_glfwTerminateNSGL();
|
||||
_glfwTerminateJoysticksNS();
|
||||
|
||||
[_glfw.ns.autoreleasePool release];
|
||||
_glfw.ns.autoreleasePool = nil;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetVersionString(void)
|
||||
{
|
||||
return _GLFW_VERSION_NUMBER " Cocoa NSGL"
|
||||
#if defined(_GLFW_BUILD_DLL)
|
||||
" dynamic"
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
//========================================================================
|
||||
// GLFW 3.3 Cocoa - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_cocoa_joystick_h_
|
||||
#define _glfw3_cocoa_joystick_h_
|
||||
|
||||
#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
|
||||
|
||||
|
||||
// Cocoa-specific per-joystick data
|
||||
//
|
||||
typedef struct _GLFWjoystickNS
|
||||
{
|
||||
IOHIDDeviceRef device;
|
||||
CFMutableArrayRef axes;
|
||||
CFMutableArrayRef buttons;
|
||||
CFMutableArrayRef hats;
|
||||
} _GLFWjoystickNS;
|
||||
|
||||
|
||||
void _glfwInitJoysticksNS(void);
|
||||
void _glfwTerminateJoysticksNS(void);
|
||||
|
||||
#endif // _glfw3_cocoa_joystick_h_
|
|
@ -0,0 +1,397 @@
|
|||
//========================================================================
|
||||
// GLFW 3.3 Cocoa - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2016 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#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;
|
||||
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;
|
||||
}
|
||||
|
||||
// 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(_GLFW_JOYSTICK_ID(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];
|
||||
CFIndex i;
|
||||
CFStringRef productKey;
|
||||
_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);
|
||||
|
||||
productKey = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
|
||||
if (productKey)
|
||||
{
|
||||
CFStringGetCString(productKey,
|
||||
name,
|
||||
sizeof(name),
|
||||
kCFStringEncodingUTF8);
|
||||
}
|
||||
else
|
||||
strncpy(name, "Unknown", sizeof(name));
|
||||
|
||||
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;
|
||||
|
||||
switch (IOHIDElementGetUsagePage(native))
|
||||
{
|
||||
case kHIDPage_GenericDesktop:
|
||||
{
|
||||
switch (IOHIDElementGetUsage(native))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case kHIDPage_Button:
|
||||
target = buttons;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (target)
|
||||
{
|
||||
_GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));
|
||||
element->native = native;
|
||||
element->minimum = IOHIDElementGetLogicalMin(native);
|
||||
element->maximum = IOHIDElementGetLogicalMax(native);
|
||||
CFArrayAppendValue(target, element);
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(elements);
|
||||
|
||||
js = _glfwAllocJoystick(name,
|
||||
CFArrayGetCount(axes),
|
||||
CFArrayGetCount(buttons),
|
||||
CFArrayGetCount(hats));
|
||||
|
||||
js->ns.device = device;
|
||||
js->ns.axes = axes;
|
||||
js->ns.buttons = buttons;
|
||||
js->ns.hats = hats;
|
||||
|
||||
_glfwInputJoystick(_GLFW_JOYSTICK_ID(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 (int 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(int jid, int mode)
|
||||
{
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
|
||||
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 delta = axis->maximum - axis->minimum;
|
||||
if (delta == 0)
|
||||
_glfwInputJoystickAxis(jid, i, 0.f);
|
||||
else
|
||||
{
|
||||
const float value = (2.f * (raw - axis->minimum) / delta) - 1.f;
|
||||
_glfwInputJoystickAxis(jid, i, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else 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;
|
||||
_glfwInputJoystickButton(jid, i, value);
|
||||
}
|
||||
|
||||
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(jid, i, states[state]);
|
||||
}
|
||||
}
|
||||
|
||||
return js->present;
|
||||
}
|
||||
|
|
@ -0,0 +1,475 @@
|
|||
//========================================================================
|
||||
// GLFW 3.3 macOS - 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <IOKit/graphics/IOGraphicsLib.h>
|
||||
#include <CoreVideo/CVBase.h>
|
||||
#include <CoreVideo/CVDisplayLink.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
|
||||
|
||||
// Get the name of the specified display, or NULL
|
||||
//
|
||||
static char* getDisplayName(CGDirectDisplayID displayID)
|
||||
{
|
||||
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,
|
||||
CVDisplayLinkRef link)
|
||||
{
|
||||
GLFWvidmode result;
|
||||
result.width = (int) CGDisplayModeGetWidth(mode);
|
||||
result.height = (int) CGDisplayModeGetHeight(mode);
|
||||
result.refreshRate = (int) CGDisplayModeGetRefreshRate(mode);
|
||||
|
||||
if (result.refreshRate == 0)
|
||||
{
|
||||
const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
|
||||
if (!(time.flags & kCVTimeIsIndefinite))
|
||||
result.refreshRate = (int) (time.timeScale / (double) time.timeValue);
|
||||
}
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Poll for changes in the set of connected monitors
|
||||
//
|
||||
void _glfwPollMonitorsNS(void)
|
||||
{
|
||||
uint32_t i, j, displayCount, disconnectedCount;
|
||||
CGDirectDisplayID* displays;
|
||||
_GLFWmonitor** disconnected = NULL;
|
||||
|
||||
CGGetOnlineDisplayList(0, NULL, &displayCount);
|
||||
displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
||||
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
||||
|
||||
disconnectedCount = _glfw.monitorCount;
|
||||
if (disconnectedCount)
|
||||
{
|
||||
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
|
||||
memcpy(disconnected,
|
||||
_glfw.monitors,
|
||||
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
||||
}
|
||||
|
||||
for (i = 0; i < displayCount; i++)
|
||||
{
|
||||
_GLFWmonitor* monitor;
|
||||
const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);
|
||||
|
||||
if (CGDisplayIsAsleep(displays[i]))
|
||||
continue;
|
||||
|
||||
for (j = 0; j < disconnectedCount; j++)
|
||||
{
|
||||
// HACK: Compare unit numbers instead of display IDs to work around
|
||||
// display replacement on machines with automatic graphics
|
||||
// switching
|
||||
if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber)
|
||||
{
|
||||
disconnected[j] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const CGSize size = CGDisplayScreenSize(displays[i]);
|
||||
char* name = getDisplayName(displays[i]);
|
||||
if (!name)
|
||||
name = strdup("Unknown");
|
||||
|
||||
monitor = _glfwAllocMonitor(name, size.width, size.height);
|
||||
monitor->ns.displayID = displays[i];
|
||||
monitor->ns.unitNumber = unitNumber;
|
||||
|
||||
free(name);
|
||||
|
||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
||||
}
|
||||
|
||||
for (i = 0; i < disconnectedCount; i++)
|
||||
{
|
||||
if (disconnected[i])
|
||||
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
|
||||
}
|
||||
|
||||
free(disconnected);
|
||||
free(displays);
|
||||
}
|
||||
|
||||
// Change the current video mode
|
||||
//
|
||||
GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||
{
|
||||
CFArrayRef modes;
|
||||
CFIndex count, i;
|
||||
CVDisplayLinkRef link;
|
||||
CGDisplayModeRef native = NULL;
|
||||
GLFWvidmode current;
|
||||
const GLFWvidmode* best;
|
||||
|
||||
best = _glfwChooseVideoMode(monitor, desired);
|
||||
_glfwPlatformGetVideoMode(monitor, ¤t);
|
||||
if (_glfwCompareVideoModes(¤t, best) == 0)
|
||||
return GLFW_TRUE;
|
||||
|
||||
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
|
||||
|
||||
modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
|
||||
count = CFArrayGetCount(modes);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
|
||||
if (!modeIsGood(dm))
|
||||
continue;
|
||||
|
||||
const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
|
||||
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);
|
||||
CVDisplayLinkRelease(link);
|
||||
|
||||
if (!native)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Monitor mode list changed");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// 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 _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
const CGRect bounds = CGDisplayBounds(monitor->ns.displayID);
|
||||
|
||||
if (xpos)
|
||||
*xpos = (int) bounds.origin.x;
|
||||
if (ypos)
|
||||
*ypos = (int) bounds.origin.y;
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||
{
|
||||
CFArrayRef modes;
|
||||
CFIndex found, i, j;
|
||||
GLFWvidmode* result;
|
||||
CVDisplayLinkRef link;
|
||||
|
||||
*count = 0;
|
||||
|
||||
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
|
||||
|
||||
modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
|
||||
found = CFArrayGetCount(modes);
|
||||
result = calloc(found, sizeof(GLFWvidmode));
|
||||
|
||||
for (i = 0; i < found; i++)
|
||||
{
|
||||
CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
|
||||
if (!modeIsGood(dm))
|
||||
continue;
|
||||
|
||||
const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
|
||||
|
||||
for (j = 0; j < *count; j++)
|
||||
{
|
||||
if (_glfwCompareVideoModes(result + j, &mode) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// Skip duplicate modes
|
||||
if (i < *count)
|
||||
continue;
|
||||
|
||||
(*count)++;
|
||||
result[*count - 1] = mode;
|
||||
}
|
||||
|
||||
CFRelease(modes);
|
||||
CVDisplayLinkRelease(link);
|
||||
return result;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
|
||||
{
|
||||
CGDisplayModeRef displayMode;
|
||||
CVDisplayLinkRef link;
|
||||
|
||||
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
|
||||
|
||||
displayMode = CGDisplayCopyDisplayMode(monitor->ns.displayID);
|
||||
*mode = vidmodeFromCGDisplayMode(displayMode, link);
|
||||
CGDisplayModeRelease(displayMode);
|
||||
|
||||
CVDisplayLinkRelease(link);
|
||||
}
|
||||
|
||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
{
|
||||
uint32_t i, 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 (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);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||
{
|
||||
int i;
|
||||
CGGammaValue* values = calloc(ramp->size * 3, sizeof(CGGammaValue));
|
||||
|
||||
for (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);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// 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,167 @@
|
|||
//========================================================================
|
||||
// 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_cocoa_platform_h_
|
||||
#define _glfw3_cocoa_platform_h_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#if defined(__OBJC__)
|
||||
#import <Carbon/Carbon.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#else
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
typedef void* id;
|
||||
#endif
|
||||
|
||||
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
|
||||
|
||||
typedef struct VkMacOSSurfaceCreateInfoMVK
|
||||
{
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkMacOSSurfaceCreateFlagsMVK flags;
|
||||
const void* pView;
|
||||
} VkMacOSSurfaceCreateInfoMVK;
|
||||
|
||||
typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
|
||||
#include "posix_tls.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.view)
|
||||
#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;
|
||||
|
||||
// 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;
|
||||
id autoreleasePool;
|
||||
id cursor;
|
||||
TISInputSourceRef inputSource;
|
||||
IOHIDManagerRef hidManager;
|
||||
id unicodeData;
|
||||
id listener;
|
||||
|
||||
char keyName[64];
|
||||
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;
|
||||
|
||||
} _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);
|
||||
GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
|
||||
|
||||
#endif // _glfw3_cocoa_platform_h_
|
|
@ -0,0 +1,60 @@
|
|||
//========================================================================
|
||||
// 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#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,720 @@
|
|||
//========================================================================
|
||||
// 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
{
|
||||
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 %i",
|
||||
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 %i",
|
||||
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 %i",
|
||||
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 %i",
|
||||
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 %i",
|
||||
ctxconfig->release);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
||||
{
|
||||
int i;
|
||||
_GLFWwindow* window;
|
||||
const char* version;
|
||||
const char* prefixes[] =
|
||||
{
|
||||
"OpenGL ES-CM ",
|
||||
"OpenGL ES-CL ",
|
||||
"OpenGL ES ",
|
||||
NULL
|
||||
};
|
||||
|
||||
window = _glfwPlatformGetTls(&_glfw.context);
|
||||
|
||||
window->context.source = ctxconfig->source;
|
||||
window->context.client = GLFW_OPENGL_API;
|
||||
|
||||
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");
|
||||
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");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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");
|
||||
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);
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
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.context);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
if (window && window->context.client == GLFW_NO_API)
|
||||
{
|
||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||
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.context);
|
||||
}
|
||||
|
||||
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, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
window->context.swapBuffers(window);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSwapInterval(int interval)
|
||||
{
|
||||
_GLFWwindow* window;
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
window = _glfwPlatformGetTls(&_glfw.context);
|
||||
if (!window)
|
||||
{
|
||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
||||
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.context);
|
||||
if (!window)
|
||||
{
|
||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (*extension == '\0')
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_VALUE, "Extension name is 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.context);
|
||||
if (!window)
|
||||
{
|
||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return window->context.getProcAddress(procname);
|
||||
}
|
||||
|
|
@ -0,0 +1,763 @@
|
|||
//========================================================================
|
||||
// GLFW 3.3 EGL - 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#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)
|
||||
// Only consider EGLConfigs with associated Visuals
|
||||
if (!getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
|
||||
continue;
|
||||
#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.context, window);
|
||||
}
|
||||
|
||||
static void swapBuffersEGL(_GLFWwindow* window)
|
||||
{
|
||||
if (window != _glfwPlatformGetTls(&_glfw.context))
|
||||
{
|
||||
_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.context);
|
||||
|
||||
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_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 setEGLattrib(attribName, attribValue) \
|
||||
{ \
|
||||
attribs[index++] = attribName; \
|
||||
attribs[index++] = attribValue; \
|
||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
}
|
||||
|
||||
// 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 (_glfw.egl.KHR_create_context_no_error)
|
||||
{
|
||||
if (ctxconfig->noerror)
|
||||
flags |= EGL_CONTEXT_OPENGL_NO_ERROR_KHR;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctxconfig->debug)
|
||||
flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
|
||||
|
||||
if (ctxconfig->robustness)
|
||||
{
|
||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||
{
|
||||
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||
EGL_NO_RESET_NOTIFICATION_KHR);
|
||||
}
|
||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||
{
|
||||
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||
EGL_LOSE_CONTEXT_ON_RESET_KHR);
|
||||
}
|
||||
|
||||
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
|
||||
}
|
||||
|
||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||
{
|
||||
setEGLattrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
|
||||
setEGLattrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
|
||||
}
|
||||
|
||||
if (mask)
|
||||
setEGLattrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
|
||||
|
||||
if (flags)
|
||||
setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
|
||||
}
|
||||
|
||||
if (_glfw.egl.KHR_context_flush_control)
|
||||
{
|
||||
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||
{
|
||||
setEGLattrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||
EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
|
||||
}
|
||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||
{
|
||||
setEGLattrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||
EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
|
||||
}
|
||||
}
|
||||
|
||||
setEGLattrib(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
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
if (fbconfig->sRGB)
|
||||
{
|
||||
if (_glfw.egl.KHR_gl_colorspace)
|
||||
{
|
||||
setEGLattrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||
}
|
||||
}
|
||||
|
||||
setEGLattrib(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_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_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_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 setEGLattrib
|
||||
|
||||
// Returns the Visual and depth of the chosen EGLConfig
|
||||
//
|
||||
#if defined(_GLFW_X11)
|
||||
GLFWbool _glfwChooseVisualEGL(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,222 @@
|
|||
//========================================================================
|
||||
// GLFW 3.3 EGL - 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_egl_context_h_
|
||||
#define _glfw3_egl_context_h_
|
||||
|
||||
#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;
|
||||
#elif defined(_GLFW_MIR)
|
||||
#define EGLAPIENTRY
|
||||
typedef MirEGLNativeDisplayType EGLNativeDisplayType;
|
||||
typedef MirEGLNativeWindowType 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 _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig,
|
||||
Visual** visual, int* depth);
|
||||
#endif /*_GLFW_X11*/
|
||||
|
||||
#endif // _glfw3_egl_context_h_
|
|
@ -0,0 +1,13 @@
|
|||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
includedir=${prefix}/include
|
||||
libdir=${exec_prefix}/lib@LIB_SUFFIX@
|
||||
|
||||
Name: GLFW
|
||||
Description: A multi-platform library for OpenGL, window and input
|
||||
Version: @GLFW_VERSION_FULL@
|
||||
URL: http://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,57 @@
|
|||
//========================================================================
|
||||
// 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 Mir
|
||||
#cmakedefine _GLFW_MIR
|
||||
// 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
|
||||
|
|
@ -0,0 +1,677 @@
|
|||
//========================================================================
|
||||
// GLFW 3.3 GLX - 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#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 (!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;
|
||||
}
|
||||
|
||||
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.context, window);
|
||||
}
|
||||
|
||||
static void swapBuffersGLX(_GLFWwindow* window)
|
||||
{
|
||||
glXSwapBuffers(_glfw.x11.display, window->context.glx.window);
|
||||
}
|
||||
|
||||
static void swapIntervalGLX(int interval)
|
||||
{
|
||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.context);
|
||||
|
||||
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 dlsym(_glfw.glx.handle, procname);
|
||||
}
|
||||
|
||||
// Destroy the OpenGL context
|
||||
//
|
||||
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(__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 = dlopen(sonames[i], RTLD_LAZY | RTLD_GLOBAL);
|
||||
if (_glfw.glx.handle)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_glfw.glx.handle)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to load GLX");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.glx.GetFBConfigs =
|
||||
dlsym(_glfw.glx.handle, "glXGetFBConfigs");
|
||||
_glfw.glx.GetFBConfigAttrib =
|
||||
dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib");
|
||||
_glfw.glx.GetClientString =
|
||||
dlsym(_glfw.glx.handle, "glXGetClientString");
|
||||
_glfw.glx.QueryExtension =
|
||||
dlsym(_glfw.glx.handle, "glXQueryExtension");
|
||||
_glfw.glx.QueryVersion =
|
||||
dlsym(_glfw.glx.handle, "glXQueryVersion");
|
||||
_glfw.glx.DestroyContext =
|
||||
dlsym(_glfw.glx.handle, "glXDestroyContext");
|
||||
_glfw.glx.MakeCurrent =
|
||||
dlsym(_glfw.glx.handle, "glXMakeCurrent");
|
||||
_glfw.glx.SwapBuffers =
|
||||
dlsym(_glfw.glx.handle, "glXSwapBuffers");
|
||||
_glfw.glx.QueryExtensionsString =
|
||||
dlsym(_glfw.glx.handle, "glXQueryExtensionsString");
|
||||
_glfw.glx.CreateNewContext =
|
||||
dlsym(_glfw.glx.handle, "glXCreateNewContext");
|
||||
_glfw.glx.CreateWindow =
|
||||
dlsym(_glfw.glx.handle, "glXCreateWindow");
|
||||
_glfw.glx.DestroyWindow =
|
||||
dlsym(_glfw.glx.handle, "glXDestroyWindow");
|
||||
_glfw.glx.GetProcAddress =
|
||||
dlsym(_glfw.glx.handle, "glXGetProcAddress");
|
||||
_glfw.glx.GetProcAddressARB =
|
||||
dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
|
||||
_glfw.glx.GetVisualFromFBConfig =
|
||||
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_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)
|
||||
{
|
||||
dlclose(_glfw.glx.handle);
|
||||
_glfw.glx.handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define setGLXattrib(attribName, attribValue) \
|
||||
{ \
|
||||
attribs[index++] = attribName; \
|
||||
attribs[index++] = attribValue; \
|
||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
}
|
||||
|
||||
// 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->noerror)
|
||||
flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;
|
||||
|
||||
if (ctxconfig->robustness)
|
||||
{
|
||||
if (_glfw.glx.ARB_create_context_robustness)
|
||||
{
|
||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||
{
|
||||
setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
GLX_NO_RESET_NOTIFICATION_ARB);
|
||||
}
|
||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||
{
|
||||
setGLXattrib(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)
|
||||
{
|
||||
setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||
}
|
||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||
{
|
||||
setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
setGLXattrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||
setGLXattrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||
}
|
||||
|
||||
if (mask)
|
||||
setGLXattrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||
|
||||
if (flags)
|
||||
setGLXattrib(GLX_CONTEXT_FLAGS_ARB, flags);
|
||||
|
||||
setGLXattrib(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 setGLXattrib
|
||||
|
||||
// Returns the Visual and depth of the chosen GLXFBConfig
|
||||
//
|
||||
GLFWbool _glfwChooseVisualGLX(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,183 @@
|
|||
//========================================================================
|
||||
// GLFW 3.3 GLX - 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_glx_context_h_
|
||||
#define _glfw3_glx_context_h_
|
||||
|
||||
#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
|
||||
|
||||
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_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 _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig,
|
||||
Visual** visual, int* depth);
|
||||
|
||||
#endif // _glfw3_glx_context_h_
|
|
@ -0,0 +1,263 @@
|
|||
//========================================================================
|
||||
// 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
// The global variables below comprise all 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 int _glfwErrorCode;
|
||||
static GLFWerrorfun _glfwErrorCallback;
|
||||
static _GLFWinitconfig _glfwInitHints =
|
||||
{
|
||||
GLFW_TRUE, // hat buttons
|
||||
{
|
||||
GLFW_TRUE, // menubar
|
||||
GLFW_TRUE // chdir
|
||||
}
|
||||
};
|
||||
|
||||
// Returns a generic string representation of the specified error
|
||||
//
|
||||
static const char* getErrorString(int error)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case GLFW_NOT_INITIALIZED:
|
||||
return "The GLFW library is not initialized";
|
||||
case GLFW_NO_CURRENT_CONTEXT:
|
||||
return "There is no current context";
|
||||
case GLFW_INVALID_ENUM:
|
||||
return "Invalid argument for enum parameter";
|
||||
case GLFW_INVALID_VALUE:
|
||||
return "Invalid value for parameter";
|
||||
case GLFW_OUT_OF_MEMORY:
|
||||
return "Out of memory";
|
||||
case GLFW_API_UNAVAILABLE:
|
||||
return "The requested API is unavailable";
|
||||
case GLFW_VERSION_UNAVAILABLE:
|
||||
return "The requested API version is unavailable";
|
||||
case GLFW_PLATFORM_ERROR:
|
||||
return "An undocumented platform-specific error occurred";
|
||||
case GLFW_FORMAT_UNAVAILABLE:
|
||||
return "The requested format is unavailable";
|
||||
case GLFW_NO_WINDOW_CONTEXT:
|
||||
return "The specified window has no context";
|
||||
default:
|
||||
return "ERROR: UNKNOWN GLFW ERROR";
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
_glfwTerminateVulkan();
|
||||
_glfwPlatformTerminate();
|
||||
|
||||
if (_glfwPlatformIsValidTls(&_glfw.error))
|
||||
_glfwErrorCode = (int) (intptr_t) _glfwPlatformGetTls(&_glfw.error);
|
||||
|
||||
_glfwPlatformDestroyTls(&_glfw.context);
|
||||
_glfwPlatformDestroyTls(&_glfw.error);
|
||||
|
||||
memset(&_glfw, 0, sizeof(_glfw));
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW event API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwInputError(int error, const char* format, ...)
|
||||
{
|
||||
if (_glfw.initialized)
|
||||
_glfwPlatformSetTls(&_glfw.error, (void*) (intptr_t) error);
|
||||
else
|
||||
_glfwErrorCode = error;
|
||||
|
||||
if (_glfwErrorCallback)
|
||||
{
|
||||
char buffer[8192];
|
||||
const char* description;
|
||||
|
||||
if (format)
|
||||
{
|
||||
int count;
|
||||
va_list vl;
|
||||
|
||||
va_start(vl, format);
|
||||
count = vsnprintf(buffer, sizeof(buffer), format, vl);
|
||||
va_end(vl);
|
||||
|
||||
if (count < 0)
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
|
||||
description = buffer;
|
||||
}
|
||||
else
|
||||
description = getErrorString(error);
|
||||
|
||||
_glfwErrorCallback(error, 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 (!_glfwPlatformCreateTls(&_glfw.error))
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwPlatformCreateTls(&_glfw.context))
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfwPlatformSetTls(&_glfw.error, (void*) (intptr_t) _glfwErrorCode);
|
||||
|
||||
_glfw.initialized = GLFW_TRUE;
|
||||
_glfw.timer.offset = _glfwPlatformGetTimerValue();
|
||||
|
||||
// Not all window hints have zero as their default value
|
||||
glfwDefaultWindowHints();
|
||||
|
||||
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 %i", 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(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (_glfw.initialized)
|
||||
{
|
||||
error = (int) (intptr_t) _glfwPlatformGetTls(&_glfw.error);
|
||||
_glfwPlatformSetTls(&_glfw.error, (intptr_t) GLFW_NO_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = _glfwErrorCode;
|
||||
_glfwErrorCode = GLFW_NO_ERROR;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
|
||||
{
|
||||
_GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
|
@ -0,0 +1,802 @@
|
|||
//========================================================================
|
||||
// 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <float.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// Internal key state used for sticky keys
|
||||
#define _GLFW_STICK 3
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW event API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
{
|
||||
if (key >= 0 && key <= GLFW_KEY_LAST)
|
||||
{
|
||||
GLFWbool repeated = GLFW_FALSE;
|
||||
|
||||
if (action == GLFW_RELEASE && window->keys[key] == GLFW_RELEASE)
|
||||
return;
|
||||
|
||||
if (action == GLFW_PRESS && window->keys[key] == GLFW_PRESS)
|
||||
repeated = GLFW_TRUE;
|
||||
|
||||
if (action == GLFW_RELEASE && window->stickyKeys)
|
||||
window->keys[key] = _GLFW_STICK;
|
||||
else
|
||||
window->keys[key] = (char) action;
|
||||
|
||||
if (repeated)
|
||||
action = GLFW_REPEAT;
|
||||
}
|
||||
|
||||
if (window->callbacks.key)
|
||||
window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods);
|
||||
}
|
||||
|
||||
void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain)
|
||||
{
|
||||
if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
|
||||
return;
|
||||
|
||||
if (window->callbacks.charmods)
|
||||
window->callbacks.charmods((GLFWwindow*) window, codepoint, mods);
|
||||
|
||||
if (plain)
|
||||
{
|
||||
if (window->callbacks.character)
|
||||
window->callbacks.character((GLFWwindow*) window, codepoint);
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
if (window->callbacks.scroll)
|
||||
window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
|
||||
}
|
||||
|
||||
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
|
||||
{
|
||||
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
|
||||
return;
|
||||
|
||||
if (action == GLFW_RELEASE && window->stickyMouseButtons)
|
||||
window->mouseButtons[button] = _GLFW_STICK;
|
||||
else
|
||||
window->mouseButtons[button] = (char) action;
|
||||
|
||||
if (window->callbacks.mouseButton)
|
||||
window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods);
|
||||
}
|
||||
|
||||
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
|
||||
return;
|
||||
|
||||
window->virtualCursorPosX = xpos;
|
||||
window->virtualCursorPosY = ypos;
|
||||
|
||||
if (window->callbacks.cursorPos)
|
||||
window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos);
|
||||
}
|
||||
|
||||
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
|
||||
{
|
||||
if (window->callbacks.cursorEnter)
|
||||
window->callbacks.cursorEnter((GLFWwindow*) window, entered);
|
||||
}
|
||||
|
||||
void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
|
||||
{
|
||||
if (window->callbacks.drop)
|
||||
window->callbacks.drop((GLFWwindow*) window, count, paths);
|
||||
}
|
||||
|
||||
void _glfwInputJoystick(int jid, int event)
|
||||
{
|
||||
if (_glfw.callbacks.joystick)
|
||||
_glfw.callbacks.joystick(jid, event);
|
||||
}
|
||||
|
||||
void _glfwInputJoystickAxis(int jid, int axis, float value)
|
||||
{
|
||||
_glfw.joysticks[jid].axes[axis] = value;
|
||||
}
|
||||
|
||||
void _glfwInputJoystickButton(int jid, int button, char value)
|
||||
{
|
||||
_glfw.joysticks[jid].buttons[button] = value;
|
||||
}
|
||||
|
||||
void _glfwInputJoystickHat(int jid, int hat, char value)
|
||||
{
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
const int base = js->buttonCount + hat * 4;
|
||||
|
||||
js->buttons[base + 0] = (value & 0x01) ? GLFW_PRESS : GLFW_RELEASE;
|
||||
js->buttons[base + 1] = (value & 0x02) ? GLFW_PRESS : GLFW_RELEASE;
|
||||
js->buttons[base + 2] = (value & 0x04) ? GLFW_PRESS : GLFW_RELEASE;
|
||||
js->buttons[base + 3] = (value & 0x08) ? GLFW_PRESS : GLFW_RELEASE;
|
||||
|
||||
js->hats[hat] = value;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwIsPrintable(int key)
|
||||
{
|
||||
return (key >= GLFW_KEY_APOSTROPHE && key <= GLFW_KEY_WORLD_2) ||
|
||||
(key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD) ||
|
||||
key == GLFW_KEY_KP_EQUAL;
|
||||
}
|
||||
|
||||
_GLFWjoystick* _glfwAllocJoystick(const char* name,
|
||||
int axisCount,
|
||||
int buttonCount,
|
||||
int hatCount)
|
||||
{
|
||||
int jid;
|
||||
_GLFWjoystick* js;
|
||||
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (!_glfw.joysticks[jid].present)
|
||||
break;
|
||||
}
|
||||
|
||||
if (jid > GLFW_JOYSTICK_LAST)
|
||||
return NULL;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
js->present = GLFW_TRUE;
|
||||
js->name = strdup(name);
|
||||
js->axes = calloc(axisCount, sizeof(float));
|
||||
js->buttons = calloc(buttonCount + hatCount * 4, 1);
|
||||
js->hats = calloc(hatCount, 1);
|
||||
js->axisCount = axisCount;
|
||||
js->buttonCount = buttonCount;
|
||||
js->hatCount = hatCount;
|
||||
|
||||
return js;
|
||||
}
|
||||
|
||||
void _glfwFreeJoystick(_GLFWjoystick* js)
|
||||
{
|
||||
free(js->name);
|
||||
free(js->axes);
|
||||
free(js->buttons);
|
||||
free(js->hats);
|
||||
memset(js, 0, sizeof(_GLFWjoystick));
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW public API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case GLFW_CURSOR:
|
||||
return window->cursorMode;
|
||||
case GLFW_STICKY_KEYS:
|
||||
return window->stickyKeys;
|
||||
case GLFW_STICKY_MOUSE_BUTTONS:
|
||||
return window->stickyMouseButtons;
|
||||
default:
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case GLFW_CURSOR:
|
||||
{
|
||||
if (value != GLFW_CURSOR_NORMAL &&
|
||||
value != GLFW_CURSOR_HIDDEN &&
|
||||
value != GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid cursor mode %i",
|
||||
value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (window->cursorMode == value)
|
||||
return;
|
||||
|
||||
window->cursorMode = value;
|
||||
|
||||
_glfwPlatformGetCursorPos(window,
|
||||
&window->virtualCursorPosX,
|
||||
&window->virtualCursorPosY);
|
||||
|
||||
if (_glfwPlatformWindowFocused(window))
|
||||
_glfwPlatformSetCursorMode(window, value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case GLFW_STICKY_KEYS:
|
||||
{
|
||||
if (window->stickyKeys == value)
|
||||
return;
|
||||
|
||||
if (!value)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Release all sticky keys
|
||||
for (i = 0; i <= GLFW_KEY_LAST; i++)
|
||||
{
|
||||
if (window->keys[i] == _GLFW_STICK)
|
||||
window->keys[i] = GLFW_RELEASE;
|
||||
}
|
||||
}
|
||||
|
||||
window->stickyKeys = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
case GLFW_STICKY_MOUSE_BUTTONS:
|
||||
{
|
||||
if (window->stickyMouseButtons == value)
|
||||
return;
|
||||
|
||||
if (!value)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Release all sticky mouse buttons
|
||||
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
|
||||
{
|
||||
if (window->mouseButtons[i] == _GLFW_STICK)
|
||||
window->mouseButtons[i] = GLFW_RELEASE;
|
||||
}
|
||||
}
|
||||
|
||||
window->stickyMouseButtons = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode);
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetKeyName(int key, int scancode)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
return _glfwPlatformGetKeyName(key, scancode);
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetKeyScancode(int key)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(-1);
|
||||
|
||||
if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
|
||||
return GLFW_RELEASE;
|
||||
}
|
||||
|
||||
return _glfwPlatformGetKeyScancode(key);
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
|
||||
|
||||
if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
|
||||
return GLFW_RELEASE;
|
||||
}
|
||||
|
||||
if (window->keys[key] == _GLFW_STICK)
|
||||
{
|
||||
// Sticky mode: release key now
|
||||
window->keys[key] = GLFW_RELEASE;
|
||||
return GLFW_PRESS;
|
||||
}
|
||||
|
||||
return (int) window->keys[key];
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
|
||||
|
||||
if (button < GLFW_MOUSE_BUTTON_1 || button > GLFW_MOUSE_BUTTON_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid mouse button %i", button);
|
||||
return GLFW_RELEASE;
|
||||
}
|
||||
|
||||
if (window->mouseButtons[button] == _GLFW_STICK)
|
||||
{
|
||||
// Sticky mode: release mouse button now
|
||||
window->mouseButtons[button] = GLFW_RELEASE;
|
||||
return GLFW_PRESS;
|
||||
}
|
||||
|
||||
return (int) window->mouseButtons[button];
|
||||
}
|
||||
|
||||
GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
if (xpos)
|
||||
*xpos = 0;
|
||||
if (ypos)
|
||||
*ypos = 0;
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
if (xpos)
|
||||
*xpos = window->virtualCursorPosX;
|
||||
if (ypos)
|
||||
*ypos = window->virtualCursorPosY;
|
||||
}
|
||||
else
|
||||
_glfwPlatformGetCursorPos(window, xpos, ypos);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
if (xpos != xpos || xpos < -DBL_MAX || xpos > DBL_MAX ||
|
||||
ypos != ypos || ypos < -DBL_MAX || ypos > DBL_MAX)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_VALUE,
|
||||
"Invalid cursor position %f %f",
|
||||
xpos, ypos);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_glfwPlatformWindowFocused(window))
|
||||
return;
|
||||
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
// Only update the accumulated position if the cursor is disabled
|
||||
window->virtualCursorPosX = xpos;
|
||||
window->virtualCursorPosY = ypos;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update system cursor position
|
||||
_glfwPlatformSetCursorPos(window, xpos, ypos);
|
||||
}
|
||||
}
|
||||
|
||||
GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)
|
||||
{
|
||||
_GLFWcursor* cursor;
|
||||
|
||||
assert(image != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
cursor = calloc(1, sizeof(_GLFWcursor));
|
||||
cursor->next = _glfw.cursorListHead;
|
||||
_glfw.cursorListHead = cursor;
|
||||
|
||||
if (!_glfwPlatformCreateCursor(cursor, image, xhot, yhot))
|
||||
{
|
||||
glfwDestroyCursor((GLFWcursor*) cursor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (GLFWcursor*) cursor;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape)
|
||||
{
|
||||
_GLFWcursor* cursor;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (shape != GLFW_ARROW_CURSOR &&
|
||||
shape != GLFW_IBEAM_CURSOR &&
|
||||
shape != GLFW_CROSSHAIR_CURSOR &&
|
||||
shape != GLFW_HAND_CURSOR &&
|
||||
shape != GLFW_HRESIZE_CURSOR &&
|
||||
shape != GLFW_VRESIZE_CURSOR)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor %i", shape);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cursor = calloc(1, sizeof(_GLFWcursor));
|
||||
cursor->next = _glfw.cursorListHead;
|
||||
_glfw.cursorListHead = cursor;
|
||||
|
||||
if (!_glfwPlatformCreateStandardCursor(cursor, shape))
|
||||
{
|
||||
glfwDestroyCursor((GLFWcursor*) cursor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (GLFWcursor*) cursor;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwDestroyCursor(GLFWcursor* handle)
|
||||
{
|
||||
_GLFWcursor* cursor = (_GLFWcursor*) handle;
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
if (cursor == NULL)
|
||||
return;
|
||||
|
||||
// Make sure the cursor is not being used by any window
|
||||
{
|
||||
_GLFWwindow* window;
|
||||
|
||||
for (window = _glfw.windowListHead; window; window = window->next)
|
||||
{
|
||||
if (window->cursor == cursor)
|
||||
glfwSetCursor((GLFWwindow*) window, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
_glfwPlatformDestroyCursor(cursor);
|
||||
|
||||
// Unlink cursor from global linked list
|
||||
{
|
||||
_GLFWcursor** prev = &_glfw.cursorListHead;
|
||||
|
||||
while (*prev != cursor)
|
||||
prev = &((*prev)->next);
|
||||
|
||||
*prev = cursor->next;
|
||||
}
|
||||
|
||||
free(cursor);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) windowHandle;
|
||||
_GLFWcursor* cursor = (_GLFWcursor*) cursorHandle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
window->cursor = cursor;
|
||||
|
||||
_glfwPlatformSetCursor(window, cursor);
|
||||
}
|
||||
|
||||
GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
_GLFW_SWAP_POINTERS(window->callbacks.key, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
_GLFW_SWAP_POINTERS(window->callbacks.character, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmodsfun cbfun)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
_GLFW_SWAP_POINTERS(window->callbacks.charmods, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle,
|
||||
GLFWmousebuttonfun cbfun)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
_GLFW_SWAP_POINTERS(window->callbacks.mouseButton, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle,
|
||||
GLFWcursorposfun cbfun)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
_GLFW_SWAP_POINTERS(window->callbacks.cursorPos, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* handle,
|
||||
GLFWcursorenterfun cbfun)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
_GLFW_SWAP_POINTERS(window->callbacks.cursorEnter, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle,
|
||||
GLFWscrollfun cbfun)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
_GLFW_SWAP_POINTERS(window->callbacks.scroll, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
_GLFW_SWAP_POINTERS(window->callbacks.drop, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI int glfwJoystickPresent(int jid)
|
||||
{
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", jid);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!_glfw.joysticks[jid].present)
|
||||
return GLFW_FALSE;
|
||||
|
||||
return _glfwPlatformPollJoystick(jid, _GLFW_POLL_PRESENCE);
|
||||
}
|
||||
|
||||
GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
|
||||
{
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||
assert(count != NULL);
|
||||
|
||||
*count = 0;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", jid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_glfw.joysticks[jid].present)
|
||||
return NULL;
|
||||
|
||||
if (!_glfwPlatformPollJoystick(jid, _GLFW_POLL_AXES))
|
||||
return NULL;
|
||||
|
||||
*count = _glfw.joysticks[jid].axisCount;
|
||||
return _glfw.joysticks[jid].axes;
|
||||
}
|
||||
|
||||
GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
|
||||
{
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||
assert(count != NULL);
|
||||
|
||||
*count = 0;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", jid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_glfw.joysticks[jid].present)
|
||||
return NULL;
|
||||
|
||||
if (!_glfwPlatformPollJoystick(jid, _GLFW_POLL_BUTTONS))
|
||||
return NULL;
|
||||
|
||||
if (_glfw.hints.init.hatButtons)
|
||||
{
|
||||
*count = _glfw.joysticks[jid].buttonCount +
|
||||
_glfw.joysticks[jid].hatCount * 4;
|
||||
}
|
||||
else
|
||||
*count = _glfw.joysticks[jid].buttonCount;
|
||||
|
||||
return _glfw.joysticks[jid].buttons;
|
||||
}
|
||||
|
||||
GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
|
||||
{
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||
assert(count != NULL);
|
||||
|
||||
*count = 0;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", jid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_glfw.joysticks[jid].present)
|
||||
return NULL;
|
||||
|
||||
if (!_glfwPlatformPollJoystick(jid, _GLFW_POLL_BUTTONS))
|
||||
return NULL;
|
||||
|
||||
*count = _glfw.joysticks[jid].hatCount;
|
||||
return _glfw.joysticks[jid].hats;
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetJoystickName(int jid)
|
||||
{
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", jid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_glfw.joysticks[jid].present)
|
||||
return NULL;
|
||||
|
||||
if (!_glfwPlatformPollJoystick(jid, _GLFW_POLL_PRESENCE))
|
||||
return NULL;
|
||||
|
||||
return _glfw.joysticks[jid].name;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
_GLFW_SWAP_POINTERS(_glfw.callbacks.joystick, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
assert(string != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
_glfwPlatformSetClipboardString(window, string);
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
return _glfwPlatformGetClipboardString(window);
|
||||
}
|
||||
|
||||
GLFWAPI double glfwGetTime(void)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(0.0);
|
||||
return (double) (_glfwPlatformGetTimerValue() - _glfw.timer.offset) /
|
||||
_glfwPlatformGetTimerFrequency();
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSetTime(double time)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
if (time != time || time < 0.0 || time > 18446744073.0)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time);
|
||||
return;
|
||||
}
|
||||
|
||||
_glfw.timer.offset = _glfwPlatformGetTimerValue() -
|
||||
(uint64_t) (time * _glfwPlatformGetTimerFrequency());
|
||||
}
|
||||
|
||||
GLFWAPI uint64_t glfwGetTimerValue(void)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||
return _glfwPlatformGetTimerValue();
|
||||
}
|
||||
|
||||
GLFWAPI uint64_t glfwGetTimerFrequency(void)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||
return _glfwPlatformGetTimerFrequency();
|
||||
}
|
||||
|
|
@ -0,0 +1,963 @@
|
|||
//========================================================================
|
||||
// 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_internal_h_
|
||||
#define _glfw3_internal_h_
|
||||
|
||||
|
||||
#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
|
||||
|
||||
typedef int GLFWbool;
|
||||
|
||||
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 _GLFWjoystick _GLFWjoystick;
|
||||
typedef struct _GLFWtls _GLFWtls;
|
||||
|
||||
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_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
|
||||
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
|
||||
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000053000,
|
||||
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_MIR)
|
||||
#include "mir_platform.h"
|
||||
#elif defined(_GLFW_OSMESA)
|
||||
#include "null_platform.h"
|
||||
#else
|
||||
#error "No supported window creation API selected"
|
||||
#endif
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Doxygen group definitions
|
||||
//========================================================================
|
||||
|
||||
/*! @defgroup platform Platform interface
|
||||
* @brief The interface implemented by the platform-specific code.
|
||||
*
|
||||
* The platform API is the interface exposed by the platform-specific code for
|
||||
* each platform and is called by the shared code of the public API It mirrors
|
||||
* the public API except it uses objects instead of handles.
|
||||
*/
|
||||
/*! @defgroup event Event interface
|
||||
* @brief The interface used by the platform-specific code to report events.
|
||||
*
|
||||
* The event API is used by the platform-specific code to notify the shared
|
||||
* code of events that can be translated into state changes and/or callback
|
||||
* calls.
|
||||
*/
|
||||
/*! @defgroup utility Utility functions
|
||||
* @brief Various utility functions for internal use.
|
||||
*
|
||||
* These functions are shared code and may be used by any part of GLFW
|
||||
* Each platform may add its own utility functions, but those must only be
|
||||
* called by the platform-specific code
|
||||
*/
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Helper macros
|
||||
//========================================================================
|
||||
|
||||
// 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; \
|
||||
}
|
||||
|
||||
// Maps a joystick pointer to an ID
|
||||
#define _GLFW_JOYSTICK_ID(js) ((int) ((js) - _glfw.joysticks))
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Platform-independent structures
|
||||
//========================================================================
|
||||
|
||||
/*! @brief Initialization configuration.
|
||||
*
|
||||
* Parameters relating to the initialization of the library.
|
||||
*/
|
||||
struct _GLFWinitconfig
|
||||
{
|
||||
GLFWbool hatButtons;
|
||||
struct {
|
||||
GLFWbool menubar;
|
||||
GLFWbool chdir;
|
||||
} ns;
|
||||
};
|
||||
|
||||
/*! @brief 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;
|
||||
struct {
|
||||
GLFWbool retina;
|
||||
GLFWbool frame;
|
||||
} ns;
|
||||
};
|
||||
|
||||
/*! @brief 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;
|
||||
};
|
||||
|
||||
/*! @brief 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;
|
||||
uintptr_t handle;
|
||||
};
|
||||
|
||||
/*! @brief 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;
|
||||
};
|
||||
|
||||
/*! @brief Window and context structure.
|
||||
*/
|
||||
struct _GLFWwindow
|
||||
{
|
||||
struct _GLFWwindow* next;
|
||||
|
||||
// Window settings and state
|
||||
GLFWbool resizable;
|
||||
GLFWbool decorated;
|
||||
GLFWbool autoIconify;
|
||||
GLFWbool floating;
|
||||
GLFWbool shouldClose;
|
||||
void* userPointer;
|
||||
GLFWvidmode videoMode;
|
||||
_GLFWmonitor* monitor;
|
||||
_GLFWcursor* cursor;
|
||||
|
||||
int minwidth, minheight;
|
||||
int maxwidth, maxheight;
|
||||
int numer, denom;
|
||||
|
||||
GLFWbool stickyKeys;
|
||||
GLFWbool stickyMouseButtons;
|
||||
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;
|
||||
|
||||
_GLFWcontext context;
|
||||
|
||||
struct {
|
||||
GLFWwindowposfun pos;
|
||||
GLFWwindowsizefun size;
|
||||
GLFWwindowclosefun close;
|
||||
GLFWwindowrefreshfun refresh;
|
||||
GLFWwindowfocusfun focus;
|
||||
GLFWwindowiconifyfun iconify;
|
||||
GLFWwindowmaximizefun maximize;
|
||||
GLFWframebuffersizefun fbsize;
|
||||
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;
|
||||
};
|
||||
|
||||
/*! @brief Monitor structure.
|
||||
*/
|
||||
struct _GLFWmonitor
|
||||
{
|
||||
char* name;
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
/*! @brief Cursor structure
|
||||
*/
|
||||
struct _GLFWcursor
|
||||
{
|
||||
_GLFWcursor* next;
|
||||
|
||||
// This is defined in the window API's platform.h
|
||||
_GLFW_PLATFORM_CURSOR_STATE;
|
||||
};
|
||||
|
||||
/*! @brief Joystick structure
|
||||
*/
|
||||
struct _GLFWjoystick
|
||||
{
|
||||
GLFWbool present;
|
||||
float* axes;
|
||||
int axisCount;
|
||||
unsigned char* buttons;
|
||||
int buttonCount;
|
||||
unsigned char* hats;
|
||||
int hatCount;
|
||||
char* name;
|
||||
|
||||
// This is defined in the joystick API's joystick.h
|
||||
_GLFW_PLATFORM_JOYSTICK_STATE;
|
||||
};
|
||||
|
||||
/*! @brief Thread local storage structure.
|
||||
*/
|
||||
struct _GLFWtls
|
||||
{
|
||||
// This is defined in the platform's tls.h
|
||||
_GLFW_PLATFORM_TLS_STATE;
|
||||
};
|
||||
|
||||
/*! @brief Library global data.
|
||||
*/
|
||||
struct _GLFWlibrary
|
||||
{
|
||||
GLFWbool initialized;
|
||||
|
||||
struct {
|
||||
_GLFWinitconfig init;
|
||||
_GLFWfbconfig framebuffer;
|
||||
_GLFWwndconfig window;
|
||||
_GLFWctxconfig context;
|
||||
int refreshRate;
|
||||
} hints;
|
||||
|
||||
_GLFWcursor* cursorListHead;
|
||||
|
||||
_GLFWwindow* windowListHead;
|
||||
|
||||
_GLFWmonitor** monitors;
|
||||
int monitorCount;
|
||||
|
||||
_GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1];
|
||||
|
||||
_GLFWtls error;
|
||||
_GLFWtls context;
|
||||
|
||||
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;
|
||||
#elif defined(_GLFW_X11)
|
||||
GLFWbool KHR_xlib_surface;
|
||||
GLFWbool KHR_xcb_surface;
|
||||
#elif defined(_GLFW_WAYLAND)
|
||||
GLFWbool KHR_wayland_surface;
|
||||
#elif defined(_GLFW_MIR)
|
||||
GLFWbool KHR_mir_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
|
||||
//========================================================================
|
||||
|
||||
/*! @brief All global data shared between compilation units.
|
||||
*/
|
||||
extern _GLFWlibrary _glfw;
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Platform API functions
|
||||
//========================================================================
|
||||
|
||||
/*! @addtogroup platform @{ */
|
||||
|
||||
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);
|
||||
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* _glfwPlatformGetKeyName(int key, int scancode);
|
||||
int _glfwPlatformGetKeyScancode(int key);
|
||||
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
|
||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
|
||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
|
||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
|
||||
|
||||
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string);
|
||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window);
|
||||
|
||||
int _glfwPlatformPollJoystick(int jid, int mode);
|
||||
|
||||
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 _glfwPlatformIconifyWindow(_GLFWwindow* window);
|
||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window);
|
||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window);
|
||||
void _glfwPlatformHideWindow(_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);
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
|
||||
|
||||
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 _glfwPlatformIsValidTls(_GLFWtls* tls);
|
||||
|
||||
/*! @} */
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Event API functions
|
||||
//========================================================================
|
||||
|
||||
/*! @brief Notifies shared code that a window has lost or received input focus.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] focused `GLFW_TRUE` if the window received focus, or `GLFW_FALSE`
|
||||
* if it lost focus.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused);
|
||||
|
||||
/*! @brief Notifies shared code that a window has moved.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] xpos The new x-coordinate of the client area of the window.
|
||||
* @param[in] ypos The new y-coordinate of the client area of the window.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos);
|
||||
|
||||
/*! @brief Notifies shared code that a window has been resized.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] width The new width of the client area of the window.
|
||||
* @param[in] height The new height of the client area of the window.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
|
||||
|
||||
/*! @brief Notifies shared code that a window framebuffer has been resized.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] width The new width, in pixels, of the framebuffer.
|
||||
* @param[in] height The new height, in pixels, of the framebuffer.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
|
||||
|
||||
/*! @brief Notifies shared code that a window has been iconified or restored.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] iconified `GLFW_TRUE` if the window was iconified, or
|
||||
* `GLFW_FALSE` if it was restored.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified);
|
||||
|
||||
/*! @brief Notifies shared code that a window has been maximized or restored.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] maximized `GLFW_TRUE` if the window was maximized, or
|
||||
* `GLFW_FALSE` if it was restored.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized);
|
||||
|
||||
/*! @brief Notifies shared code that a window's contents needs updating.
|
||||
* @param[in] window The window that received the event.
|
||||
*/
|
||||
void _glfwInputWindowDamage(_GLFWwindow* window);
|
||||
|
||||
/*! @brief Notifies shared code that the user wishes to close a window.
|
||||
* @param[in] window The window that received the event.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputWindowCloseRequest(_GLFWwindow* window);
|
||||
|
||||
/*! @brief Notifies shared code that a window has changed its desired monitor.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] monitor The new desired monitor, or `NULL`.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor);
|
||||
|
||||
/*! @brief Notifies shared code of a physical key event.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] key The key that was pressed or released.
|
||||
* @param[in] scancode The system-specific scan code of the key.
|
||||
* @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE.
|
||||
* @param[in] mods The modifiers pressed when the event was generated.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||
|
||||
/*! @brief Notifies shared code of a Unicode character input event.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] codepoint The Unicode code point of the input character.
|
||||
* @param[in] mods Bit field describing which modifier keys were held down.
|
||||
* @param[in] plain `GLFW_TRUE` if the character is regular text input, or
|
||||
* `GLFW_FALSE` otherwise.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain);
|
||||
|
||||
/*! @brief Notifies shared code of a scroll event.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] xoffset The scroll offset along the x-axis.
|
||||
* @param[in] yoffset The scroll offset along the y-axis.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset);
|
||||
|
||||
/*! @brief Notifies shared code of a mouse button click event.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] button The button that was pressed or released.
|
||||
* @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE.
|
||||
* @param[in] mods The modifiers pressed when the event was generated.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
||||
|
||||
/*! @brief Notifies shared code of a cursor motion event.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] xpos The new x-coordinate of the cursor, relative to the left
|
||||
* edge of the client area of the window.
|
||||
* @param[in] ypos The new y-coordinate of the cursor, relative to the top edge
|
||||
* of the client area of the window.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
||||
|
||||
/*! @brief Notifies shared code of a cursor enter/leave event.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] entered `GLFW_TRUE` if the cursor entered the client area of the
|
||||
* window, or `GLFW_FALSE` if it left it.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered);
|
||||
|
||||
/*! @brief Notifies shared code of a monitor connection or disconnection.
|
||||
* @param[in] monitor The monitor that was connected or disconnected.
|
||||
* @param[in] action One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
|
||||
* @param[in] placement `_GLFW_INSERT_FIRST` or `_GLFW_INSERT_LAST`.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement);
|
||||
|
||||
/*! @brief Notifies shared code that a full screen window has acquired or
|
||||
* released a monitor.
|
||||
* @param[in] monitor The monitor that was acquired or released.
|
||||
* @param[in] window The window that acquired the monitor, or `NULL`.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window);
|
||||
|
||||
/*! @brief Notifies shared code of an error.
|
||||
* @param[in] error The error code most suitable for the error.
|
||||
* @param[in] format The `printf` style format string of the error
|
||||
* description.
|
||||
* @ingroup event
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
void _glfwInputError(int error, const char* format, ...) __attribute__((format(printf, 2, 3)));
|
||||
#else
|
||||
void _glfwInputError(int error, const char* format, ...);
|
||||
#endif
|
||||
|
||||
/*! @brief Notifies shared code of files or directories dropped on a window.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] count The number of dropped objects.
|
||||
* @param[in] names The names of the dropped objects.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
|
||||
|
||||
/*! @brief Notifies shared code of a joystick connection or disconnection.
|
||||
* @param[in] jid The joystick that was connected or disconnected.
|
||||
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputJoystick(int jid, int event);
|
||||
|
||||
/*! @brief Notifies shared code of the new value of a joystick axis.
|
||||
* @param[in] jid The joystick whose axis to update.
|
||||
* @param[in] axis The index of the axis to update.
|
||||
* @param[in] value The new value of the axis.
|
||||
*/
|
||||
void _glfwInputJoystickAxis(int jid, int axis, float value);
|
||||
|
||||
/*! @brief Notifies shared code of the new value of a joystick button.
|
||||
* @param[in] jid The joystick whose button to update.
|
||||
* @param[in] button The index of the button to update.
|
||||
* @param[in] value The new value of the button.
|
||||
*/
|
||||
void _glfwInputJoystickButton(int jid, int button, char value);
|
||||
|
||||
/*! @brief Notifies shared code of the new value of a joystick hat.
|
||||
* @param[in] jid The joystick whose hat to update.
|
||||
* @param[in] button The index of the hat to update.
|
||||
* @param[in] value The new value of the hat.
|
||||
*/
|
||||
void _glfwInputJoystickHat(int jid, int hat, char value);
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Utility functions
|
||||
//========================================================================
|
||||
|
||||
/*! @brief Chooses the video mode most closely matching the desired one.
|
||||
* @ingroup utility
|
||||
*/
|
||||
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
|
||||
const GLFWvidmode* desired);
|
||||
|
||||
/*! @brief Performs lexical comparison between two @ref GLFWvidmode structures.
|
||||
* @ingroup utility
|
||||
*/
|
||||
int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second);
|
||||
|
||||
/*! @brief Splits a color depth into red, green and blue bit depths.
|
||||
* @ingroup utility
|
||||
*/
|
||||
void _glfwSplitBPP(int bpp, int* red, int* green, int* blue);
|
||||
|
||||
/*! @brief Searches an extension string for the specified extension.
|
||||
* @param[in] string The extension string to search.
|
||||
* @param[in] extensions The extension to search for.
|
||||
* @return `GLFW_TRUE` if the extension was found, or `GLFW_FALSE` otherwise.
|
||||
* @ingroup utility
|
||||
*/
|
||||
GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions);
|
||||
|
||||
/*! @brief Chooses the framebuffer config that best matches the desired one.
|
||||
* @param[in] desired The desired framebuffer config.
|
||||
* @param[in] alternatives The framebuffer configs supported by the system.
|
||||
* @param[in] count The number of entries in the alternatives array.
|
||||
* @return The framebuffer config most closely matching the desired one, or @c
|
||||
* NULL if none fulfilled the hard constraints of the desired values.
|
||||
* @ingroup utility
|
||||
*/
|
||||
const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
||||
const _GLFWfbconfig* alternatives,
|
||||
unsigned int count);
|
||||
|
||||
/*! @brief Retrieves the attributes of the current context.
|
||||
* @param[in] ctxconfig The desired context attributes.
|
||||
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if the context is
|
||||
* unusable.
|
||||
* @ingroup utility
|
||||
*/
|
||||
GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig);
|
||||
|
||||
/*! @brief Checks whether the desired context attributes are valid.
|
||||
* @param[in] ctxconfig The context attributes to check.
|
||||
* @return `GLFW_TRUE` if the context attributes are valid, or `GLFW_FALSE`
|
||||
* otherwise.
|
||||
* @ingroup utility
|
||||
*
|
||||
* 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);
|
||||
|
||||
/*! @brief Allocates red, green and blue value arrays of the specified size.
|
||||
* @ingroup utility
|
||||
*/
|
||||
void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size);
|
||||
|
||||
/*! @brief Frees the red, green and blue value arrays and clears the struct.
|
||||
* @ingroup utility
|
||||
*/
|
||||
void _glfwFreeGammaArrays(GLFWgammaramp* ramp);
|
||||
|
||||
/*! @brief Allocates and returns a monitor object with the specified name
|
||||
* and dimensions.
|
||||
* @param[in] name The name of the monitor.
|
||||
* @param[in] widthMM The width, in mm, of the monitor's display area.
|
||||
* @param[in] heightMM The height, in mm, of the monitor's display area.
|
||||
* @return The newly created object.
|
||||
* @ingroup utility
|
||||
*/
|
||||
_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM);
|
||||
|
||||
/*! @brief Frees a monitor object and any data associated with it.
|
||||
* @ingroup utility
|
||||
*/
|
||||
void _glfwFreeMonitor(_GLFWmonitor* monitor);
|
||||
|
||||
/*! @brief Returns an available joystick object with arrays and name allocated.
|
||||
* @ingroup utility
|
||||
*/
|
||||
_GLFWjoystick* _glfwAllocJoystick(const char* name, int axisCount, int buttonCount, int hatCount);
|
||||
|
||||
/*! @brief Frees arrays and name and flags the joystick object as unused.
|
||||
* @ingroup utility
|
||||
*/
|
||||
void _glfwFreeJoystick(_GLFWjoystick* js);
|
||||
|
||||
/*! @ingroup utility
|
||||
*/
|
||||
GLFWbool _glfwIsPrintable(int key);
|
||||
|
||||
/*! @ingroup utility
|
||||
*/
|
||||
GLFWbool _glfwInitVulkan(int mode);
|
||||
|
||||
/*! @ingroup utility
|
||||
*/
|
||||
void _glfwTerminateVulkan(void);
|
||||
|
||||
/*! @ingroup utility
|
||||
*/
|
||||
const char* _glfwGetVulkanResultString(VkResult result);
|
||||
|
||||
#endif // _glfw3_internal_h_
|
|
@ -0,0 +1,286 @@
|
|||
//========================================================================
|
||||
// GLFW 3.3 Linux - 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <linux/joystick.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>
|
||||
|
||||
|
||||
// Attempt to open the specified joystick device
|
||||
//
|
||||
static GLFWbool openJoystickDevice(const char* path)
|
||||
{
|
||||
char axisCount, buttonCount;
|
||||
char name[256] = "";
|
||||
int jid, fd, version;
|
||||
_GLFWjoystick* js;
|
||||
|
||||
for (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;
|
||||
}
|
||||
|
||||
fd = open(path, O_RDONLY | O_NONBLOCK);
|
||||
if (fd == -1)
|
||||
return GLFW_FALSE;
|
||||
|
||||
// Verify that the joystick driver version is at least 1.0
|
||||
ioctl(fd, JSIOCGVERSION, &version);
|
||||
if (version < 0x010000)
|
||||
{
|
||||
// It's an old 0.x interface (we don't support it)
|
||||
close(fd);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
|
||||
strncpy(name, "Unknown", sizeof(name));
|
||||
|
||||
ioctl(fd, JSIOCGAXES, &axisCount);
|
||||
ioctl(fd, JSIOCGBUTTONS, &buttonCount);
|
||||
|
||||
js = _glfwAllocJoystick(name, axisCount, buttonCount, 0);
|
||||
if (!js)
|
||||
{
|
||||
close(fd);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
js->linjs.path = strdup(path);
|
||||
js->linjs.fd = fd;
|
||||
|
||||
_glfwInputJoystick(_GLFW_JOYSTICK_ID(js), GLFW_CONNECTED);
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// Frees all resources associated with the specified joystick
|
||||
//
|
||||
static void closeJoystick(_GLFWjoystick* js)
|
||||
{
|
||||
close(js->linjs.fd);
|
||||
free(js->linjs.path);
|
||||
_glfwFreeJoystick(js);
|
||||
_glfwInputJoystick(_GLFW_JOYSTICK_ID(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)
|
||||
{
|
||||
DIR* dir;
|
||||
int count = 0;
|
||||
const char* dirname = "/dev/input";
|
||||
|
||||
_glfw.linjs.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||
if (_glfw.linjs.inotify == -1)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Linux: Failed to initialize inotify: %s",
|
||||
strerror(errno));
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
// HACK: Register for IN_ATTRIB as well 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);
|
||||
if (_glfw.linjs.watch == -1)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Linux: Failed to watch for joystick connections in %s: %s",
|
||||
dirname,
|
||||
strerror(errno));
|
||||
// Continue without device connection notifications
|
||||
}
|
||||
|
||||
if (regcomp(&_glfw.linjs.regex, "^js[0-9]\\+$", 0) != 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
dir = opendir(dirname);
|
||||
if (dir)
|
||||
{
|
||||
struct dirent* entry;
|
||||
|
||||
while ((entry = readdir(dir)))
|
||||
{
|
||||
char path[20];
|
||||
regmatch_t match;
|
||||
|
||||
if (regexec(&_glfw.linjs.regex, entry->d_name, 1, &match, 0) != 0)
|
||||
continue;
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
|
||||
if (openJoystickDevice(path))
|
||||
count++;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Linux: Failed to open joystick device directory %s: %s",
|
||||
dirname,
|
||||
strerror(errno));
|
||||
// Continue with no joysticks detected
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) == 0)
|
||||
{
|
||||
char path[20];
|
||||
snprintf(path, sizeof(path), "/dev/input/%s", e->name);
|
||||
|
||||
if (e->mask & (IN_CREATE | IN_ATTRIB))
|
||||
openJoystickDevice(path);
|
||||
else if (e->mask & IN_DELETE)
|
||||
{
|
||||
int jid;
|
||||
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
||||
{
|
||||
closeJoystick(_glfw.joysticks + jid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
offset += sizeof(struct inotify_event) + e->len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformPollJoystick(int jid, int mode)
|
||||
{
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
|
||||
// Read all queued events (non-blocking)
|
||||
for (;;)
|
||||
{
|
||||
struct js_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;
|
||||
}
|
||||
|
||||
// Clear the initial-state bit
|
||||
e.type &= ~JS_EVENT_INIT;
|
||||
|
||||
if (e.type == JS_EVENT_AXIS)
|
||||
_glfwInputJoystickAxis(jid, e.number, e.value / 32767.0f);
|
||||
else if (e.type == JS_EVENT_BUTTON)
|
||||
_glfwInputJoystickButton(jid, e.number, e.value ? 1 : 0);
|
||||
}
|
||||
|
||||
return js->present;
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
//========================================================================
|
||||
// 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_linux_joystick_h_
|
||||
#define _glfw3_linux_joystick_h_
|
||||
|
||||
#include <regex.h>
|
||||
|
||||
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickLinux linjs
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs
|
||||
|
||||
|
||||
// Linux-specific joystick data
|
||||
//
|
||||
typedef struct _GLFWjoystickLinux
|
||||
{
|
||||
int fd;
|
||||
char* path;
|
||||
} _GLFWjoystickLinux;
|
||||
|
||||
// Linux-specific joystick API data
|
||||
//
|
||||
typedef struct _GLFWlibraryLinux
|
||||
{
|
||||
int inotify;
|
||||
int watch;
|
||||
regex_t regex;
|
||||
} _GLFWlibraryLinux;
|
||||
|
||||
|
||||
GLFWbool _glfwInitJoysticksLinux(void);
|
||||
void _glfwTerminateJoysticksLinux(void);
|
||||
void _glfwDetectJoystickConnectionLinux(void);
|
||||
|
||||
#endif // _glfw3_linux_joystick_h_
|
|
@ -0,0 +1,240 @@
|
|||
//========================================================================
|
||||
// GLFW 3.3 Mir - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.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 "internal.h"
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
// Create key code translation tables
|
||||
//
|
||||
static void createKeyTables(void)
|
||||
{
|
||||
int scancode;
|
||||
|
||||
memset(_glfw.mir.keycodes, -1, sizeof(_glfw.mir.keycodes));
|
||||
memset(_glfw.mir.scancodes, -1, sizeof(_glfw.mir.scancodes));
|
||||
|
||||
_glfw.mir.keycodes[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
|
||||
_glfw.mir.keycodes[KEY_1] = GLFW_KEY_1;
|
||||
_glfw.mir.keycodes[KEY_2] = GLFW_KEY_2;
|
||||
_glfw.mir.keycodes[KEY_3] = GLFW_KEY_3;
|
||||
_glfw.mir.keycodes[KEY_4] = GLFW_KEY_4;
|
||||
_glfw.mir.keycodes[KEY_5] = GLFW_KEY_5;
|
||||
_glfw.mir.keycodes[KEY_6] = GLFW_KEY_6;
|
||||
_glfw.mir.keycodes[KEY_7] = GLFW_KEY_7;
|
||||
_glfw.mir.keycodes[KEY_8] = GLFW_KEY_8;
|
||||
_glfw.mir.keycodes[KEY_9] = GLFW_KEY_9;
|
||||
_glfw.mir.keycodes[KEY_0] = GLFW_KEY_0;
|
||||
_glfw.mir.keycodes[KEY_SPACE] = GLFW_KEY_SPACE;
|
||||
_glfw.mir.keycodes[KEY_MINUS] = GLFW_KEY_MINUS;
|
||||
_glfw.mir.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL;
|
||||
_glfw.mir.keycodes[KEY_Q] = GLFW_KEY_Q;
|
||||
_glfw.mir.keycodes[KEY_W] = GLFW_KEY_W;
|
||||
_glfw.mir.keycodes[KEY_E] = GLFW_KEY_E;
|
||||
_glfw.mir.keycodes[KEY_R] = GLFW_KEY_R;
|
||||
_glfw.mir.keycodes[KEY_T] = GLFW_KEY_T;
|
||||
_glfw.mir.keycodes[KEY_Y] = GLFW_KEY_Y;
|
||||
_glfw.mir.keycodes[KEY_U] = GLFW_KEY_U;
|
||||
_glfw.mir.keycodes[KEY_I] = GLFW_KEY_I;
|
||||
_glfw.mir.keycodes[KEY_O] = GLFW_KEY_O;
|
||||
_glfw.mir.keycodes[KEY_P] = GLFW_KEY_P;
|
||||
_glfw.mir.keycodes[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
|
||||
_glfw.mir.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
|
||||
_glfw.mir.keycodes[KEY_A] = GLFW_KEY_A;
|
||||
_glfw.mir.keycodes[KEY_S] = GLFW_KEY_S;
|
||||
_glfw.mir.keycodes[KEY_D] = GLFW_KEY_D;
|
||||
_glfw.mir.keycodes[KEY_F] = GLFW_KEY_F;
|
||||
_glfw.mir.keycodes[KEY_G] = GLFW_KEY_G;
|
||||
_glfw.mir.keycodes[KEY_H] = GLFW_KEY_H;
|
||||
_glfw.mir.keycodes[KEY_J] = GLFW_KEY_J;
|
||||
_glfw.mir.keycodes[KEY_K] = GLFW_KEY_K;
|
||||
_glfw.mir.keycodes[KEY_L] = GLFW_KEY_L;
|
||||
_glfw.mir.keycodes[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
|
||||
_glfw.mir.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
|
||||
_glfw.mir.keycodes[KEY_Z] = GLFW_KEY_Z;
|
||||
_glfw.mir.keycodes[KEY_X] = GLFW_KEY_X;
|
||||
_glfw.mir.keycodes[KEY_C] = GLFW_KEY_C;
|
||||
_glfw.mir.keycodes[KEY_V] = GLFW_KEY_V;
|
||||
_glfw.mir.keycodes[KEY_B] = GLFW_KEY_B;
|
||||
_glfw.mir.keycodes[KEY_N] = GLFW_KEY_N;
|
||||
_glfw.mir.keycodes[KEY_M] = GLFW_KEY_M;
|
||||
_glfw.mir.keycodes[KEY_COMMA] = GLFW_KEY_COMMA;
|
||||
_glfw.mir.keycodes[KEY_DOT] = GLFW_KEY_PERIOD;
|
||||
_glfw.mir.keycodes[KEY_SLASH] = GLFW_KEY_SLASH;
|
||||
_glfw.mir.keycodes[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
|
||||
_glfw.mir.keycodes[KEY_ESC] = GLFW_KEY_ESCAPE;
|
||||
_glfw.mir.keycodes[KEY_TAB] = GLFW_KEY_TAB;
|
||||
_glfw.mir.keycodes[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
|
||||
_glfw.mir.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
|
||||
_glfw.mir.keycodes[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
|
||||
_glfw.mir.keycodes[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
|
||||
_glfw.mir.keycodes[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
|
||||
_glfw.mir.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
|
||||
_glfw.mir.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
|
||||
_glfw.mir.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
|
||||
_glfw.mir.keycodes[KEY_MENU] = GLFW_KEY_MENU;
|
||||
_glfw.mir.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
|
||||
_glfw.mir.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
|
||||
_glfw.mir.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
|
||||
_glfw.mir.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
|
||||
_glfw.mir.keycodes[KEY_PAUSE] = GLFW_KEY_PAUSE;
|
||||
_glfw.mir.keycodes[KEY_DELETE] = GLFW_KEY_DELETE;
|
||||
_glfw.mir.keycodes[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
|
||||
_glfw.mir.keycodes[KEY_ENTER] = GLFW_KEY_ENTER;
|
||||
_glfw.mir.keycodes[KEY_HOME] = GLFW_KEY_HOME;
|
||||
_glfw.mir.keycodes[KEY_END] = GLFW_KEY_END;
|
||||
_glfw.mir.keycodes[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
|
||||
_glfw.mir.keycodes[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
|
||||
_glfw.mir.keycodes[KEY_INSERT] = GLFW_KEY_INSERT;
|
||||
_glfw.mir.keycodes[KEY_LEFT] = GLFW_KEY_LEFT;
|
||||
_glfw.mir.keycodes[KEY_RIGHT] = GLFW_KEY_RIGHT;
|
||||
_glfw.mir.keycodes[KEY_DOWN] = GLFW_KEY_DOWN;
|
||||
_glfw.mir.keycodes[KEY_UP] = GLFW_KEY_UP;
|
||||
_glfw.mir.keycodes[KEY_F1] = GLFW_KEY_F1;
|
||||
_glfw.mir.keycodes[KEY_F2] = GLFW_KEY_F2;
|
||||
_glfw.mir.keycodes[KEY_F3] = GLFW_KEY_F3;
|
||||
_glfw.mir.keycodes[KEY_F4] = GLFW_KEY_F4;
|
||||
_glfw.mir.keycodes[KEY_F5] = GLFW_KEY_F5;
|
||||
_glfw.mir.keycodes[KEY_F6] = GLFW_KEY_F6;
|
||||
_glfw.mir.keycodes[KEY_F7] = GLFW_KEY_F7;
|
||||
_glfw.mir.keycodes[KEY_F8] = GLFW_KEY_F8;
|
||||
_glfw.mir.keycodes[KEY_F9] = GLFW_KEY_F9;
|
||||
_glfw.mir.keycodes[KEY_F10] = GLFW_KEY_F10;
|
||||
_glfw.mir.keycodes[KEY_F11] = GLFW_KEY_F11;
|
||||
_glfw.mir.keycodes[KEY_F12] = GLFW_KEY_F12;
|
||||
_glfw.mir.keycodes[KEY_F13] = GLFW_KEY_F13;
|
||||
_glfw.mir.keycodes[KEY_F14] = GLFW_KEY_F14;
|
||||
_glfw.mir.keycodes[KEY_F15] = GLFW_KEY_F15;
|
||||
_glfw.mir.keycodes[KEY_F16] = GLFW_KEY_F16;
|
||||
_glfw.mir.keycodes[KEY_F17] = GLFW_KEY_F17;
|
||||
_glfw.mir.keycodes[KEY_F18] = GLFW_KEY_F18;
|
||||
_glfw.mir.keycodes[KEY_F19] = GLFW_KEY_F19;
|
||||
_glfw.mir.keycodes[KEY_F20] = GLFW_KEY_F20;
|
||||
_glfw.mir.keycodes[KEY_F21] = GLFW_KEY_F21;
|
||||
_glfw.mir.keycodes[KEY_F22] = GLFW_KEY_F22;
|
||||
_glfw.mir.keycodes[KEY_F23] = GLFW_KEY_F23;
|
||||
_glfw.mir.keycodes[KEY_F24] = GLFW_KEY_F24;
|
||||
_glfw.mir.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
|
||||
_glfw.mir.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
|
||||
_glfw.mir.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
|
||||
_glfw.mir.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
|
||||
_glfw.mir.keycodes[KEY_KP0] = GLFW_KEY_KP_0;
|
||||
_glfw.mir.keycodes[KEY_KP1] = GLFW_KEY_KP_1;
|
||||
_glfw.mir.keycodes[KEY_KP2] = GLFW_KEY_KP_2;
|
||||
_glfw.mir.keycodes[KEY_KP3] = GLFW_KEY_KP_3;
|
||||
_glfw.mir.keycodes[KEY_KP4] = GLFW_KEY_KP_4;
|
||||
_glfw.mir.keycodes[KEY_KP5] = GLFW_KEY_KP_5;
|
||||
_glfw.mir.keycodes[KEY_KP6] = GLFW_KEY_KP_6;
|
||||
_glfw.mir.keycodes[KEY_KP7] = GLFW_KEY_KP_7;
|
||||
_glfw.mir.keycodes[KEY_KP8] = GLFW_KEY_KP_8;
|
||||
_glfw.mir.keycodes[KEY_KP9] = GLFW_KEY_KP_9;
|
||||
_glfw.mir.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
|
||||
_glfw.mir.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
|
||||
_glfw.mir.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
|
||||
|
||||
for (scancode = 0; scancode < 256; scancode++)
|
||||
{
|
||||
if (_glfw.mir.keycodes[scancode] > 0)
|
||||
_glfw.mir.scancodes[_glfw.mir.keycodes[scancode]] = scancode;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformInit(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
_glfw.mir.connection = mir_connect_sync(NULL, __PRETTY_FUNCTION__);
|
||||
|
||||
if (!mir_connection_is_valid(_glfw.mir.connection))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unable to connect to server: %s",
|
||||
mir_connection_get_error_message(_glfw.mir.connection));
|
||||
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.mir.display =
|
||||
mir_connection_get_egl_native_display(_glfw.mir.connection);
|
||||
|
||||
createKeyTables();
|
||||
|
||||
if (!_glfwInitJoysticksLinux())
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfwInitTimerPOSIX();
|
||||
|
||||
_glfw.mir.eventQueue = calloc(1, sizeof(EventQueue));
|
||||
_glfwInitEventQueueMir(_glfw.mir.eventQueue);
|
||||
|
||||
error = pthread_mutex_init(&_glfw.mir.eventMutex, NULL);
|
||||
if (error)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Failed to create event mutex: %s",
|
||||
strerror(error));
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfwPollMonitorsMir();
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformTerminate(void)
|
||||
{
|
||||
_glfwTerminateEGL();
|
||||
_glfwTerminateJoysticksLinux();
|
||||
|
||||
_glfwDeleteEventQueueMir(_glfw.mir.eventQueue);
|
||||
|
||||
pthread_mutex_destroy(&_glfw.mir.eventMutex);
|
||||
|
||||
mir_connection_release(_glfw.mir.connection);
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetVersionString(void)
|
||||
{
|
||||
return _GLFW_VERSION_NUMBER " Mir EGL"
|
||||
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
|
||||
" clock_gettime"
|
||||
#else
|
||||
" gettimeofday"
|
||||
#endif
|
||||
" /dev/js"
|
||||
#if defined(_GLFW_BUILD_DLL)
|
||||
" shared"
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
//========================================================================
|
||||
// GLFW 3.3 Mir - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.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 "internal.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Poll for changes in the set of connected monitors
|
||||
//
|
||||
void _glfwPollMonitorsMir(void)
|
||||
{
|
||||
int i;
|
||||
MirDisplayConfig* displayConfig =
|
||||
mir_connection_create_display_configuration(_glfw.mir.connection);
|
||||
|
||||
int numOutputs = mir_display_config_get_num_outputs(displayConfig);
|
||||
|
||||
for (i = 0; i < numOutputs; i++)
|
||||
{
|
||||
const MirOutput* output = mir_display_config_get_output(displayConfig, i);
|
||||
MirOutputConnectionState state = mir_output_get_connection_state(output);
|
||||
bool enabled = mir_output_is_enabled(output);
|
||||
|
||||
if (enabled && state == mir_output_connection_state_connected)
|
||||
{
|
||||
int widthMM = mir_output_get_physical_width_mm(output);
|
||||
int heightMM = mir_output_get_physical_height_mm(output);
|
||||
int x = mir_output_get_position_x(output);
|
||||
int y = mir_output_get_position_y(output);
|
||||
int id = mir_output_get_id(output);
|
||||
size_t currentMode = mir_output_get_current_mode_index(output);
|
||||
const char* name = mir_output_type_name(mir_output_get_type(output));
|
||||
|
||||
_GLFWmonitor* monitor = _glfwAllocMonitor(name,
|
||||
widthMM,
|
||||
heightMM);
|
||||
monitor->mir.x = x;
|
||||
monitor->mir.y = y;
|
||||
monitor->mir.outputId = id;
|
||||
monitor->mir.curMode = currentMode;
|
||||
monitor->modes = _glfwPlatformGetVideoModes(monitor, &monitor->modeCount);
|
||||
|
||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
||||
}
|
||||
}
|
||||
|
||||
mir_display_config_release(displayConfig);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
if (xpos)
|
||||
*xpos = monitor->mir.x;
|
||||
if (ypos)
|
||||
*ypos = monitor->mir.y;
|
||||
}
|
||||
|
||||
static void FillInRGBBitsFromPixelFormat(GLFWvidmode* mode, const MirPixelFormat pf)
|
||||
{
|
||||
switch (pf)
|
||||
{
|
||||
case mir_pixel_format_rgb_565:
|
||||
mode->redBits = 5;
|
||||
mode->greenBits = 6;
|
||||
mode->blueBits = 5;
|
||||
break;
|
||||
case mir_pixel_format_rgba_5551:
|
||||
mode->redBits = 5;
|
||||
mode->greenBits = 5;
|
||||
mode->blueBits = 5;
|
||||
break;
|
||||
case mir_pixel_format_rgba_4444:
|
||||
mode->redBits = 4;
|
||||
mode->greenBits = 4;
|
||||
mode->blueBits = 4;
|
||||
break;
|
||||
case mir_pixel_format_abgr_8888:
|
||||
case mir_pixel_format_xbgr_8888:
|
||||
case mir_pixel_format_argb_8888:
|
||||
case mir_pixel_format_xrgb_8888:
|
||||
case mir_pixel_format_bgr_888:
|
||||
case mir_pixel_format_rgb_888:
|
||||
default:
|
||||
mode->redBits = 8;
|
||||
mode->greenBits = 8;
|
||||
mode->blueBits = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||
{
|
||||
int i;
|
||||
GLFWvidmode* modes = NULL;
|
||||
MirDisplayConfig* displayConfig =
|
||||
mir_connection_create_display_configuration(_glfw.mir.connection);
|
||||
|
||||
int numOutputs = mir_display_config_get_num_outputs(displayConfig);
|
||||
|
||||
for (i = 0; i < numOutputs; i++)
|
||||
{
|
||||
const MirOutput* output = mir_display_config_get_output(displayConfig, i);
|
||||
int id = mir_output_get_id(output);
|
||||
|
||||
if (id != monitor->mir.outputId)
|
||||
continue;
|
||||
|
||||
MirOutputConnectionState state = mir_output_get_connection_state(output);
|
||||
bool enabled = mir_output_is_enabled(output);
|
||||
|
||||
// We must have been disconnected
|
||||
if (!enabled || state != mir_output_connection_state_connected)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Monitor no longer connected");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int numModes = mir_output_get_num_modes(output);
|
||||
modes = calloc(numModes, sizeof(GLFWvidmode));
|
||||
|
||||
for (*found = 0; *found < numModes; (*found)++)
|
||||
{
|
||||
const MirOutputMode* mode = mir_output_get_mode(output, *found);
|
||||
int width = mir_output_mode_get_width(mode);
|
||||
int height = mir_output_mode_get_height(mode);
|
||||
double refreshRate = mir_output_mode_get_refresh_rate(mode);
|
||||
MirPixelFormat currentFormat = mir_output_get_current_pixel_format(output);
|
||||
|
||||
modes[*found].width = width;
|
||||
modes[*found].height = height;
|
||||
modes[*found].refreshRate = refreshRate;
|
||||
|
||||
FillInRGBBitsFromPixelFormat(&modes[*found], currentFormat);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
mir_display_config_release(displayConfig);
|
||||
|
||||
return modes;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||
{
|
||||
*mode = monitor->modes[monitor->mir.curMode];
|
||||
}
|
||||
|
||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW native API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWAPI int glfwGetMirMonitor(GLFWmonitor* handle)
|
||||
{
|
||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||
return monitor->mir.outputId;
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
//========================================================================
|
||||
// GLFW 3.3 Mir - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_mir_platform_h_
|
||||
#define _glfw3_mir_platform_h_
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <pthread.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <mir_toolkit/mir_client_library.h>
|
||||
|
||||
typedef VkFlags VkMirWindowCreateFlagsKHR;
|
||||
|
||||
typedef struct VkMirWindowCreateInfoKHR
|
||||
{
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkMirWindowCreateFlagsKHR flags;
|
||||
MirConnection* connection;
|
||||
MirWindow* mirWindow;
|
||||
} VkMirWindowCreateInfoKHR;
|
||||
|
||||
typedef VkResult (APIENTRY *PFN_vkCreateMirWindowKHR)(VkInstance,const VkMirWindowCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice,uint32_t,MirConnection*);
|
||||
|
||||
#include "posix_tls.h"
|
||||
#include "posix_time.h"
|
||||
#include "linux_joystick.h"
|
||||
#include "xkb_unicode.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->mir.nativeWindow)
|
||||
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.mir.display)
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowMir mir
|
||||
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorMir mir
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir
|
||||
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir
|
||||
|
||||
#define _GLFW_PLATFORM_CONTEXT_STATE
|
||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
|
||||
|
||||
|
||||
// Mir-specific Event Queue
|
||||
//
|
||||
typedef struct EventQueue
|
||||
{
|
||||
TAILQ_HEAD(, EventNode) head;
|
||||
} EventQueue;
|
||||
|
||||
// Mir-specific per-window data
|
||||
//
|
||||
typedef struct _GLFWwindowMir
|
||||
{
|
||||
MirWindow* window;
|
||||
int width;
|
||||
int height;
|
||||
MirEGLNativeWindowType nativeWindow;
|
||||
_GLFWcursor* currentCursor;
|
||||
|
||||
} _GLFWwindowMir;
|
||||
|
||||
// Mir-specific per-monitor data
|
||||
//
|
||||
typedef struct _GLFWmonitorMir
|
||||
{
|
||||
int curMode;
|
||||
int outputId;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
} _GLFWmonitorMir;
|
||||
|
||||
// Mir-specific global data
|
||||
//
|
||||
typedef struct _GLFWlibraryMir
|
||||
{
|
||||
MirConnection* connection;
|
||||
MirEGLNativeDisplayType display;
|
||||
EventQueue* eventQueue;
|
||||
|
||||
short int keycodes[256];
|
||||
short int scancodes[GLFW_KEY_LAST + 1];
|
||||
|
||||
pthread_mutex_t eventMutex;
|
||||
pthread_cond_t eventCond;
|
||||
|
||||
// The window whose disabled cursor mode is active
|
||||
_GLFWwindow* disabledCursorWindow;
|
||||
|
||||
} _GLFWlibraryMir;
|
||||
|
||||
// Mir-specific per-cursor data
|
||||
// TODO: Only system cursors are implemented in Mir atm. Need to wait for support.
|
||||
//
|
||||
typedef struct _GLFWcursorMir
|
||||
{
|
||||
MirCursorConfiguration* conf;
|
||||
MirBufferStream* customCursor;
|
||||
char const* cursorName; // only needed for system cursors
|
||||
} _GLFWcursorMir;
|
||||
|
||||
|
||||
extern void _glfwPollMonitorsMir(void);
|
||||
extern void _glfwInitEventQueueMir(EventQueue* queue);
|
||||
extern void _glfwDeleteEventQueueMir(EventQueue* queue);
|
||||
|
||||
#endif // _glfw3_mir_platform_h_
|
|
@ -0,0 +1,932 @@
|
|||
//========================================================================
|
||||
// GLFW 3.3 Mir - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.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 "internal.h"
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
typedef struct EventNode
|
||||
{
|
||||
TAILQ_ENTRY(EventNode) entries;
|
||||
const MirEvent* event;
|
||||
_GLFWwindow* window;
|
||||
} EventNode;
|
||||
|
||||
static void deleteNode(EventQueue* queue, EventNode* node)
|
||||
{
|
||||
mir_event_unref(node->event);
|
||||
free(node);
|
||||
}
|
||||
|
||||
static GLFWbool emptyEventQueue(EventQueue* queue)
|
||||
{
|
||||
return queue->head.tqh_first == NULL;
|
||||
}
|
||||
|
||||
// TODO The mir_event_ref is not supposed to be used but ... its needed
|
||||
// in this case. Need to wait until we can read from an FD set up by mir
|
||||
// for single threaded event handling.
|
||||
static EventNode* newEventNode(const MirEvent* event, _GLFWwindow* context)
|
||||
{
|
||||
EventNode* newNode = calloc(1, sizeof(EventNode));
|
||||
newNode->event = mir_event_ref(event);
|
||||
newNode->window = context;
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
static void enqueueEvent(const MirEvent* event, _GLFWwindow* context)
|
||||
{
|
||||
pthread_mutex_lock(&_glfw.mir.eventMutex);
|
||||
|
||||
EventNode* newNode = newEventNode(event, context);
|
||||
TAILQ_INSERT_TAIL(&_glfw.mir.eventQueue->head, newNode, entries);
|
||||
|
||||
pthread_cond_signal(&_glfw.mir.eventCond);
|
||||
|
||||
pthread_mutex_unlock(&_glfw.mir.eventMutex);
|
||||
}
|
||||
|
||||
static EventNode* dequeueEvent(EventQueue* queue)
|
||||
{
|
||||
EventNode* node = NULL;
|
||||
|
||||
pthread_mutex_lock(&_glfw.mir.eventMutex);
|
||||
|
||||
node = queue->head.tqh_first;
|
||||
|
||||
if (node)
|
||||
TAILQ_REMOVE(&queue->head, node, entries);
|
||||
|
||||
pthread_mutex_unlock(&_glfw.mir.eventMutex);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static MirPixelFormat findValidPixelFormat(void)
|
||||
{
|
||||
unsigned int i, validFormats, mirPixelFormats = 32;
|
||||
MirPixelFormat formats[mir_pixel_formats];
|
||||
|
||||
mir_connection_get_available_surface_formats(_glfw.mir.connection, formats,
|
||||
mirPixelFormats, &validFormats);
|
||||
|
||||
for (i = 0; i < validFormats; i++)
|
||||
{
|
||||
if (formats[i] == mir_pixel_format_abgr_8888 ||
|
||||
formats[i] == mir_pixel_format_xbgr_8888 ||
|
||||
formats[i] == mir_pixel_format_argb_8888 ||
|
||||
formats[i] == mir_pixel_format_xrgb_8888)
|
||||
{
|
||||
return formats[i];
|
||||
}
|
||||
}
|
||||
|
||||
return mir_pixel_format_invalid;
|
||||
}
|
||||
|
||||
static int mirModToGLFWMod(uint32_t mods)
|
||||
{
|
||||
int publicMods = 0x0;
|
||||
|
||||
if (mods & mir_input_event_modifier_alt)
|
||||
publicMods |= GLFW_MOD_ALT;
|
||||
else if (mods & mir_input_event_modifier_shift)
|
||||
publicMods |= GLFW_MOD_SHIFT;
|
||||
else if (mods & mir_input_event_modifier_ctrl)
|
||||
publicMods |= GLFW_MOD_CONTROL;
|
||||
else if (mods & mir_input_event_modifier_meta)
|
||||
publicMods |= GLFW_MOD_SUPER;
|
||||
|
||||
return publicMods;
|
||||
}
|
||||
|
||||
static int toGLFWKeyCode(uint32_t key)
|
||||
{
|
||||
if (key < sizeof(_glfw.mir.keycodes) / sizeof(_glfw.mir.keycodes[0]))
|
||||
return _glfw.mir.keycodes[key];
|
||||
|
||||
return GLFW_KEY_UNKNOWN;
|
||||
}
|
||||
|
||||
static void handleKeyEvent(const MirKeyboardEvent* key_event, _GLFWwindow* window)
|
||||
{
|
||||
const int action = mir_keyboard_event_action (key_event);
|
||||
const int scan_code = mir_keyboard_event_scan_code(key_event);
|
||||
const int key_code = mir_keyboard_event_key_code (key_event);
|
||||
const int modifiers = mir_keyboard_event_modifiers(key_event);
|
||||
|
||||
const int pressed = action == mir_keyboard_action_up ? GLFW_RELEASE : GLFW_PRESS;
|
||||
const int mods = mirModToGLFWMod(modifiers);
|
||||
const long text = _glfwKeySym2Unicode(key_code);
|
||||
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
||||
|
||||
_glfwInputKey(window, toGLFWKeyCode(scan_code), scan_code, pressed, mods);
|
||||
|
||||
if (text != -1)
|
||||
_glfwInputChar(window, text, mods, plain);
|
||||
}
|
||||
|
||||
static void handlePointerButton(_GLFWwindow* window,
|
||||
int pressed,
|
||||
const MirPointerEvent* pointer_event)
|
||||
{
|
||||
int mods = mir_pointer_event_modifiers(pointer_event);
|
||||
const int publicMods = mirModToGLFWMod(mods);
|
||||
MirPointerButton button = mir_pointer_button_primary;
|
||||
static uint32_t oldButtonStates = 0;
|
||||
uint32_t newButtonStates = mir_pointer_event_buttons(pointer_event);
|
||||
int publicButton = GLFW_MOUSE_BUTTON_LEFT;
|
||||
|
||||
// XOR our old button states our new states to figure out what was added or removed
|
||||
button = newButtonStates ^ oldButtonStates;
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case mir_pointer_button_primary:
|
||||
publicButton = GLFW_MOUSE_BUTTON_LEFT;
|
||||
break;
|
||||
case mir_pointer_button_secondary:
|
||||
publicButton = GLFW_MOUSE_BUTTON_RIGHT;
|
||||
break;
|
||||
case mir_pointer_button_tertiary:
|
||||
publicButton = GLFW_MOUSE_BUTTON_MIDDLE;
|
||||
break;
|
||||
case mir_pointer_button_forward:
|
||||
// FIXME What is the forward button?
|
||||
publicButton = GLFW_MOUSE_BUTTON_4;
|
||||
break;
|
||||
case mir_pointer_button_back:
|
||||
// FIXME What is the back button?
|
||||
publicButton = GLFW_MOUSE_BUTTON_5;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
oldButtonStates = newButtonStates;
|
||||
|
||||
_glfwInputMouseClick(window, publicButton, pressed, publicMods);
|
||||
}
|
||||
|
||||
static void handlePointerMotion(_GLFWwindow* window,
|
||||
const MirPointerEvent* pointer_event)
|
||||
{
|
||||
const int hscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll);
|
||||
const int vscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll);
|
||||
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
if (_glfw.mir.disabledCursorWindow != window)
|
||||
return;
|
||||
|
||||
const int dx = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_x);
|
||||
const int dy = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_y);
|
||||
const int current_x = window->virtualCursorPosX;
|
||||
const int current_y = window->virtualCursorPosY;
|
||||
|
||||
_glfwInputCursorPos(window, dx + current_x, dy + current_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
const int x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x);
|
||||
const int y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y);
|
||||
|
||||
_glfwInputCursorPos(window, x, y);
|
||||
}
|
||||
|
||||
if (hscroll != 0 || vscroll != 0)
|
||||
_glfwInputScroll(window, hscroll, vscroll);
|
||||
}
|
||||
|
||||
static void handlePointerEvent(const MirPointerEvent* pointer_event,
|
||||
_GLFWwindow* window)
|
||||
{
|
||||
int action = mir_pointer_event_action(pointer_event);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case mir_pointer_action_button_down:
|
||||
handlePointerButton(window, GLFW_PRESS, pointer_event);
|
||||
break;
|
||||
case mir_pointer_action_button_up:
|
||||
handlePointerButton(window, GLFW_RELEASE, pointer_event);
|
||||
break;
|
||||
case mir_pointer_action_motion:
|
||||
handlePointerMotion(window, pointer_event);
|
||||
break;
|
||||
case mir_pointer_action_enter:
|
||||
case mir_pointer_action_leave:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void handleInput(const MirInputEvent* input_event, _GLFWwindow* window)
|
||||
{
|
||||
int type = mir_input_event_get_type(input_event);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case mir_input_event_type_key:
|
||||
handleKeyEvent(mir_input_event_get_keyboard_event(input_event), window);
|
||||
break;
|
||||
case mir_input_event_type_pointer:
|
||||
handlePointerEvent(mir_input_event_get_pointer_event(input_event), window);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void handleEvent(const MirEvent* event, _GLFWwindow* window)
|
||||
{
|
||||
int type = mir_event_get_type(event);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case mir_event_type_input:
|
||||
handleInput(mir_event_get_input_event(event), window);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void addNewEvent(MirWindow* window, const MirEvent* event, void* context)
|
||||
{
|
||||
enqueueEvent(event, context);
|
||||
}
|
||||
|
||||
static GLFWbool createWindow(_GLFWwindow* window)
|
||||
{
|
||||
MirWindowSpec* spec;
|
||||
MirBufferUsage buffer_usage = mir_buffer_usage_hardware;
|
||||
MirPixelFormat pixel_format = findValidPixelFormat();
|
||||
|
||||
if (pixel_format == mir_pixel_format_invalid)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unable to find a correct pixel format");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
spec = mir_create_normal_window_spec(_glfw.mir.connection,
|
||||
window->mir.width,
|
||||
window->mir.height);
|
||||
|
||||
mir_window_spec_set_pixel_format(spec, pixel_format);
|
||||
mir_window_spec_set_buffer_usage(spec, buffer_usage);
|
||||
|
||||
window->mir.window = mir_create_window_sync(spec);
|
||||
mir_window_spec_release(spec);
|
||||
|
||||
if (!mir_window_is_valid(window->mir.window))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unable to create window: %s",
|
||||
mir_window_get_error_message(window->mir.window));
|
||||
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
mir_window_set_event_handler(window->mir.window, addNewEvent, window);
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
static void setWindowConfinement(_GLFWwindow* window, MirPointerConfinementState state)
|
||||
{
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_pointer_confinement(spec, state);
|
||||
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwInitEventQueueMir(EventQueue* queue)
|
||||
{
|
||||
TAILQ_INIT(&queue->head);
|
||||
}
|
||||
|
||||
void _glfwDeleteEventQueueMir(EventQueue* queue)
|
||||
{
|
||||
if (queue)
|
||||
{
|
||||
EventNode* node, *node_next;
|
||||
node = queue->head.tqh_first;
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
node_next = node->entries.tqe_next;
|
||||
|
||||
TAILQ_REMOVE(&queue->head, node, entries);
|
||||
deleteNode(queue, node);
|
||||
|
||||
node = node_next;
|
||||
}
|
||||
|
||||
free(queue);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
if (window->monitor)
|
||||
{
|
||||
GLFWvidmode mode;
|
||||
_glfwPlatformGetVideoMode(window->monitor, &mode);
|
||||
|
||||
mir_window_set_state(window->mir.window, mir_window_state_fullscreen);
|
||||
|
||||
if (wndconfig->width > mode.width || wndconfig->height > mode.height)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Requested window size too large: %ix%i",
|
||||
wndconfig->width, wndconfig->height);
|
||||
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
window->mir.width = wndconfig->width;
|
||||
window->mir.height = wndconfig->height;
|
||||
window->mir.currentCursor = NULL;
|
||||
|
||||
if (!createWindow(window))
|
||||
return GLFW_FALSE;
|
||||
|
||||
window->mir.nativeWindow = mir_buffer_stream_get_egl_native_window(
|
||||
mir_window_get_buffer_stream(window->mir.window));
|
||||
|
||||
if (ctxconfig->client != GLFW_NO_API)
|
||||
{
|
||||
if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||
|
||||
ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwInitEGL())
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwInitOSMesa())
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (_glfw.mir.disabledCursorWindow == window)
|
||||
_glfw.mir.disabledCursorWindow = NULL;
|
||||
|
||||
if (mir_window_is_valid(window->mir.window))
|
||||
{
|
||||
mir_window_release_sync(window->mir.window);
|
||||
window->mir.window= NULL;
|
||||
}
|
||||
|
||||
if (window->context.destroy)
|
||||
window->context.destroy(window);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||
{
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_name(spec, title);
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
||||
int count, const GLFWimage* images)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||
{
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_width (spec, width);
|
||||
mir_window_spec_set_height(spec, height);
|
||||
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||
int minwidth, int minheight,
|
||||
int maxwidth, int maxheight)
|
||||
{
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_max_width (spec, maxwidth);
|
||||
mir_window_spec_set_max_height(spec, maxheight);
|
||||
mir_window_spec_set_min_width (spec, minwidth);
|
||||
mir_window_spec_set_min_height(spec, minheight);
|
||||
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||
int* left, int* top,
|
||||
int* right, int* bottom)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
||||
{
|
||||
if (width)
|
||||
*width = window->mir.width;
|
||||
if (height)
|
||||
*height = window->mir.height;
|
||||
}
|
||||
|
||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||
{
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_state(spec, mir_window_state_minimized);
|
||||
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
||||
{
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_state(spec, mir_window_state_restored);
|
||||
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||
{
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_state(spec, mir_window_state_maximized);
|
||||
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||
{
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_state(spec, mir_window_state_hidden);
|
||||
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||
{
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_state(spec, mir_window_state_restored);
|
||||
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
_GLFWmonitor* monitor,
|
||||
int xpos, int ypos,
|
||||
int width, int height,
|
||||
int refreshRate)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
||||
{
|
||||
return mir_window_get_focus_state(window->mir.window) == mir_window_focus_state_focused;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
||||
{
|
||||
return mir_window_get_visibility(window->mir.window) == mir_window_visibility_exposed;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||
{
|
||||
return mir_window_get_state(window->mir.window) == mir_window_state_maximized;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void _glfwPlatformPollEvents(void)
|
||||
{
|
||||
EventNode* node = NULL;
|
||||
|
||||
while ((node = dequeueEvent(_glfw.mir.eventQueue)))
|
||||
{
|
||||
handleEvent(node->event, node->window);
|
||||
deleteNode(_glfw.mir.eventQueue, node);
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformWaitEvents(void)
|
||||
{
|
||||
pthread_mutex_lock(&_glfw.mir.eventMutex);
|
||||
|
||||
while (emptyEventQueue(_glfw.mir.eventQueue))
|
||||
pthread_cond_wait(&_glfw.mir.eventCond, &_glfw.mir.eventMutex);
|
||||
|
||||
pthread_mutex_unlock(&_glfw.mir.eventMutex);
|
||||
|
||||
_glfwPlatformPollEvents();
|
||||
}
|
||||
|
||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||
{
|
||||
pthread_mutex_lock(&_glfw.mir.eventMutex);
|
||||
|
||||
if (emptyEventQueue(_glfw.mir.eventQueue))
|
||||
{
|
||||
struct timespec time;
|
||||
clock_gettime(CLOCK_REALTIME, &time);
|
||||
time.tv_sec += (long) timeout;
|
||||
time.tv_nsec += (long) ((timeout - (long) timeout) * 1e9);
|
||||
pthread_cond_timedwait(&_glfw.mir.eventCond, &_glfw.mir.eventMutex, &time);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&_glfw.mir.eventMutex);
|
||||
|
||||
_glfwPlatformPollEvents();
|
||||
}
|
||||
|
||||
void _glfwPlatformPostEmptyEvent(void)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
|
||||
{
|
||||
if (width)
|
||||
*width = window->mir.width;
|
||||
if (height)
|
||||
*height = window->mir.height;
|
||||
}
|
||||
|
||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
{
|
||||
MirBufferStream* stream;
|
||||
|
||||
int i_w = image->width;
|
||||
int i_h = image->height;
|
||||
|
||||
stream = mir_connection_create_buffer_stream_sync(_glfw.mir.connection,
|
||||
i_w, i_h,
|
||||
mir_pixel_format_argb_8888,
|
||||
mir_buffer_usage_software);
|
||||
|
||||
cursor->mir.conf = mir_cursor_configuration_from_buffer_stream(stream, xhot, yhot);
|
||||
|
||||
MirGraphicsRegion region;
|
||||
mir_buffer_stream_get_graphics_region(stream, ®ion);
|
||||
|
||||
unsigned char* pixels = image->pixels;
|
||||
char* dest = region.vaddr;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < i_w * i_h; i++, pixels += 4)
|
||||
{
|
||||
unsigned int alpha = pixels[3];
|
||||
*dest++ = (char)(pixels[2] * alpha / 255);
|
||||
*dest++ = (char)(pixels[1] * alpha / 255);
|
||||
*dest++ = (char)(pixels[0] * alpha / 255);
|
||||
*dest++ = (char)alpha;
|
||||
}
|
||||
|
||||
mir_buffer_stream_swap_buffers_sync(stream);
|
||||
cursor->mir.customCursor = stream;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
static const char* getSystemCursorName(int shape)
|
||||
{
|
||||
switch (shape)
|
||||
{
|
||||
case GLFW_ARROW_CURSOR:
|
||||
return mir_arrow_cursor_name;
|
||||
case GLFW_IBEAM_CURSOR:
|
||||
return mir_caret_cursor_name;
|
||||
case GLFW_CROSSHAIR_CURSOR:
|
||||
return mir_crosshair_cursor_name;
|
||||
case GLFW_HAND_CURSOR:
|
||||
return mir_open_hand_cursor_name;
|
||||
case GLFW_HRESIZE_CURSOR:
|
||||
return mir_horizontal_resize_cursor_name;
|
||||
case GLFW_VRESIZE_CURSOR:
|
||||
return mir_vertical_resize_cursor_name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||
{
|
||||
cursor->mir.conf = NULL;
|
||||
cursor->mir.customCursor = NULL;
|
||||
cursor->mir.cursorName = getSystemCursorName(shape);
|
||||
|
||||
return cursor->mir.cursorName != NULL;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
||||
{
|
||||
if (cursor->mir.conf)
|
||||
mir_cursor_configuration_destroy(cursor->mir.conf);
|
||||
if (cursor->mir.customCursor)
|
||||
mir_buffer_stream_release_sync(cursor->mir.customCursor);
|
||||
}
|
||||
|
||||
static void setCursorNameForWindow(MirWindow* window, char const* name)
|
||||
{
|
||||
MirWindowSpec* spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_cursor_name(spec, name);
|
||||
mir_window_apply_spec(window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
||||
{
|
||||
if (cursor)
|
||||
{
|
||||
window->mir.currentCursor = cursor;
|
||||
|
||||
if (cursor->mir.cursorName)
|
||||
{
|
||||
setCursorNameForWindow(window->mir.window, cursor->mir.cursorName);
|
||||
}
|
||||
else if (cursor->mir.conf)
|
||||
{
|
||||
mir_window_configure_cursor(window->mir.window, cursor->mir.conf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setCursorNameForWindow(window->mir.window, mir_default_cursor_name);
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||
{
|
||||
if (mode == GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
_glfw.mir.disabledCursorWindow = window;
|
||||
setWindowConfinement(window, mir_pointer_confined_to_window);
|
||||
setCursorNameForWindow(window->mir.window, mir_disabled_cursor_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we were disabled before lets undo that!
|
||||
if (_glfw.mir.disabledCursorWindow == window)
|
||||
{
|
||||
_glfw.mir.disabledCursorWindow = NULL;
|
||||
setWindowConfinement(window, mir_pointer_unconfined);
|
||||
}
|
||||
|
||||
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
||||
{
|
||||
_glfwPlatformSetCursor(window, window->mir.currentCursor);
|
||||
}
|
||||
else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
||||
{
|
||||
setCursorNameForWindow(window->mir.window, mir_disabled_cursor_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetKeyName(int key, int scancode)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int _glfwPlatformGetKeyScancode(int key)
|
||||
{
|
||||
return _glfw.mir.scancodes[key];
|
||||
}
|
||||
|
||||
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
{
|
||||
if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_mir_surface)
|
||||
return;
|
||||
|
||||
extensions[0] = "VK_KHR_surface";
|
||||
extensions[1] = "VK_KHR_mir_surface";
|
||||
}
|
||||
|
||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
PFN_vkGetPhysicalDeviceMirPresentationSupportKHR vkGetPhysicalDeviceMirPresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
|
||||
if (!vkGetPhysicalDeviceMirPresentationSupportKHR)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Mir: Vulkan instance missing VK_KHR_mir_surface extension");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return vkGetPhysicalDeviceMirPresentationSupportKHR(device,
|
||||
queuefamily,
|
||||
_glfw.mir.connection);
|
||||
}
|
||||
|
||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
_GLFWwindow* window,
|
||||
const VkAllocationCallbacks* allocator,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
VkResult err;
|
||||
VkMirWindowCreateInfoKHR sci;
|
||||
PFN_vkCreateMirWindowKHR vkCreateMirWindowKHR;
|
||||
|
||||
vkCreateMirWindowKHR = (PFN_vkCreateMirWindowKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkCreateMirWindowKHR");
|
||||
if (!vkCreateMirWindowKHR)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Mir: Vulkan instance missing VK_KHR_mir_surface extension");
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
}
|
||||
|
||||
memset(&sci, 0, sizeof(sci));
|
||||
sci.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR;
|
||||
sci.connection = _glfw.mir.connection;
|
||||
sci.mirWindow = window->mir.window;
|
||||
|
||||
err = vkCreateMirWindowKHR(instance, &sci, allocator, surface);
|
||||
if (err)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Failed to create Vulkan surface: %s",
|
||||
_glfwGetVulkanResultString(err));
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW native API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWAPI MirConnection* glfwGetMirDisplay(void)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
return _glfw.mir.connection;
|
||||
}
|
||||
|
||||
GLFWAPI MirWindow* glfwGetMirWindow(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
return window->mir.window;
|
||||
}
|
||||
|
|
@ -0,0 +1,441 @@
|
|||
//========================================================================
|
||||
// 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#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;
|
||||
|
||||
// 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 //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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,
|
||||
(_glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
|
||||
_glfw.monitors[0] = monitor;
|
||||
}
|
||||
else
|
||||
_glfw.monitors[_glfw.monitorCount - 1] = monitor;
|
||||
}
|
||||
else if (action == GLFW_DISCONNECTED)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _glfw.monitorCount; i++)
|
||||
{
|
||||
if (_glfw.monitors[i] == monitor)
|
||||
{
|
||||
_glfw.monitorCount--;
|
||||
memmove(_glfw.monitors + i,
|
||||
_glfw.monitors + i + 1,
|
||||
(_glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_glfw.callbacks.monitor)
|
||||
_glfw.callbacks.monitor((GLFWmonitor*) monitor, action);
|
||||
|
||||
if (action == GLFW_DISCONNECTED)
|
||||
_glfwFreeMonitor(monitor);
|
||||
}
|
||||
|
||||
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
|
||||
{
|
||||
monitor->window = window;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
_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 = strdup(name);
|
||||
|
||||
return monitor;
|
||||
}
|
||||
|
||||
void _glfwFreeMonitor(_GLFWmonitor* monitor)
|
||||
{
|
||||
if (monitor == NULL)
|
||||
return;
|
||||
|
||||
_glfwFreeGammaArrays(&monitor->originalRamp);
|
||||
_glfwFreeGammaArrays(&monitor->currentRamp);
|
||||
|
||||
free(monitor->modes);
|
||||
free(monitor->name);
|
||||
free(monitor);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
|
||||
{
|
||||
free(ramp->red);
|
||||
free(ramp->green);
|
||||
free(ramp->blue);
|
||||
|
||||
memset(ramp, 0, sizeof(GLFWgammaramp));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm)
|
||||
{
|
||||
return compareVideoModes(fm, sm);
|
||||
}
|
||||
|
||||
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 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 const char* glfwGetMonitorName(GLFWmonitor* handle)
|
||||
{
|
||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||
assert(monitor != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
return monitor->name;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
unsigned short values[256];
|
||||
GLFWgammaramp ramp;
|
||||
assert(handle != NULL);
|
||||
assert(gamma == gamma);
|
||||
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;
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
double value;
|
||||
|
||||
// Calculate intensity
|
||||
value = i / 255.0;
|
||||
// Apply gamma curve
|
||||
value = pow(value, 1.0 / gamma) * 65535.0 + 0.5;
|
||||
|
||||
// Clamp to value range
|
||||
if (value > 65535.0)
|
||||
value = 65535.0;
|
||||
|
||||
values[i] = (unsigned short) value;
|
||||
}
|
||||
|
||||
ramp.red = values;
|
||||
ramp.green = values;
|
||||
ramp.blue = values;
|
||||
ramp.size = 256;
|
||||
|
||||
glfwSetGammaRamp(handle, &ramp);
|
||||
}
|
||||
|
||||
GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
|
||||
{
|
||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||
assert(monitor != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
_glfwFreeGammaArrays(&monitor->currentRamp);
|
||||
_glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp);
|
||||
|
||||
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)
|
||||
_glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp);
|
||||
|
||||
_glfwPlatformSetGammaRamp(monitor, ramp);
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
//========================================================================
|
||||
// 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_nsgl_context_h_
|
||||
#define _glfw3_nsgl_context_h_
|
||||
|
||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl
|
||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl
|
||||
|
||||
|
||||
// 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);
|
||||
|
||||
#endif // _glfw3_nsgl_context_h_
|
|
@ -0,0 +1,321 @@
|
|||
//========================================================================
|
||||
// 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
static void makeContextCurrentNSGL(_GLFWwindow* window)
|
||||
{
|
||||
if (window)
|
||||
[window->context.nsgl.object makeCurrentContext];
|
||||
else
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
|
||||
_glfwPlatformSetTls(&_glfw.context, window);
|
||||
}
|
||||
|
||||
static void swapBuffersNSGL(_GLFWwindow* window)
|
||||
{
|
||||
// ARP appears to be unnecessary, but this is future-proof
|
||||
[window->context.nsgl.object flushBuffer];
|
||||
}
|
||||
|
||||
static void swapIntervalNSGL(int interval)
|
||||
{
|
||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.context);
|
||||
|
||||
GLint sync = interval;
|
||||
[window->context.nsgl.object setValues:&sync
|
||||
forParameter:NSOpenGLCPSwapInterval];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Destroy the OpenGL context
|
||||
//
|
||||
static void destroyContextNSGL(_GLFWwindow* window)
|
||||
{
|
||||
[window->context.nsgl.pixelFormat release];
|
||||
window->context.nsgl.pixelFormat = nil;
|
||||
|
||||
[window->context.nsgl.object release];
|
||||
window->context.nsgl.object = nil;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// 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)
|
||||
{
|
||||
unsigned int attributeCount = 0;
|
||||
|
||||
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 on
|
||||
// macOS but are not a hard constraint, so ignore and continue
|
||||
|
||||
// Context release behaviors (GL_KHR_context_flush_control) are not yet
|
||||
// supported on macOS but are not a hard constraint, so ignore and continue
|
||||
|
||||
#define ADD_ATTR(x) { attributes[attributeCount++] = x; }
|
||||
#define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); }
|
||||
|
||||
// Arbitrary array size here
|
||||
NSOpenGLPixelFormatAttribute attributes[40];
|
||||
|
||||
ADD_ATTR(NSOpenGLPFAAccelerated);
|
||||
ADD_ATTR(NSOpenGLPFAClosestPolicy);
|
||||
|
||||
if (ctxconfig->nsgl.offline)
|
||||
{
|
||||
ADD_ATTR(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
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 100800
|
||||
ADD_ATTR(kCGLPFASupportsAutomaticGraphicsSwitching);
|
||||
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
||||
}
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
|
||||
if (ctxconfig->major >= 4)
|
||||
{
|
||||
ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
|
||||
}
|
||||
else
|
||||
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
||||
if (ctxconfig->major >= 3)
|
||||
{
|
||||
ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
|
||||
}
|
||||
|
||||
if (ctxconfig->major <= 2)
|
||||
{
|
||||
if (fbconfig->auxBuffers != GLFW_DONT_CARE)
|
||||
ADD_ATTR2(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;
|
||||
|
||||
ADD_ATTR2(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;
|
||||
|
||||
ADD_ATTR2(NSOpenGLPFAColorSize, colorBits);
|
||||
}
|
||||
|
||||
if (fbconfig->alphaBits != GLFW_DONT_CARE)
|
||||
ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
|
||||
|
||||
if (fbconfig->depthBits != GLFW_DONT_CARE)
|
||||
ADD_ATTR2(NSOpenGLPFADepthSize, fbconfig->depthBits);
|
||||
|
||||
if (fbconfig->stencilBits != GLFW_DONT_CARE)
|
||||
ADD_ATTR2(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
|
||||
ADD_ATTR(NSOpenGLPFAStereo);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (fbconfig->doublebuffer)
|
||||
ADD_ATTR(NSOpenGLPFADoubleBuffer);
|
||||
|
||||
if (fbconfig->samples != GLFW_DONT_CARE)
|
||||
{
|
||||
if (fbconfig->samples == 0)
|
||||
{
|
||||
ADD_ATTR2(NSOpenGLPFASampleBuffers, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ADD_ATTR2(NSOpenGLPFASampleBuffers, 1);
|
||||
ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
|
||||
// framebuffer, so there's no need (and no way) to request it
|
||||
|
||||
ADD_ATTR(0);
|
||||
|
||||
#undef ADD_ATTR
|
||||
#undef ADD_ATTR2
|
||||
|
||||
window->context.nsgl.pixelFormat =
|
||||
[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
|
||||
if (window->context.nsgl.pixelFormat == nil)
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"NSGL: Failed to find a suitable pixel format");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
NSOpenGLContext* share = NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
[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 NULL;
|
||||
}
|
||||
|
||||
return window->context.nsgl.object;
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
//========================================================================
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#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,38 @@
|
|||
//========================================================================
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformPollJoystick(int jid, int mode)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
//========================================================================
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_null_joystick_h_
|
||||
#define _glfw3_null_joystick_h_
|
||||
|
||||
#define _GLFW_PLATFORM_JOYSTICK_STATE int nulljs
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int nulljs
|
||||
|
||||
|
||||
#endif // _glfw3_null_joystick_h_
|
|
@ -0,0 +1,55 @@
|
|||
//========================================================================
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// 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.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||
{
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue