mirror of
https://github.com/glfw/glfw.git
synced 2026-09-24 01:28:58 +00:00
Compare commits
195 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 30306e5470 | |||
| 755f913b02 | |||
| fb6fbcf700 | |||
| adf130965c | |||
| be65829055 | |||
| e0084617d5 | |||
| 8b2da399ee | |||
| e163d21f23 | |||
| 0d759c8c1a | |||
| 87ad8c0561 | |||
| 842aeb8c47 | |||
| 3dc53e21e5 | |||
| f5cbdbab4f | |||
| cf9079c783 | |||
| 0b65053ffd | |||
| 7c6a8775eb | |||
| 40da56fbf7 | |||
| c8e068712b | |||
| f6f0771770 | |||
| 4ad00fa388 | |||
| 4b4cb9ce66 | |||
| 67eadf1e97 | |||
| 6123937bde | |||
| da3a77b4e3 | |||
| 255f9f0234 | |||
| ba4504a9c7 | |||
| 7e13a4909e | |||
| afe4aadade | |||
| 8db7528ac7 | |||
| 2d39dff84a | |||
| b69b4a9f2a | |||
| 85a01bfd9b | |||
| 352a4f2757 | |||
| 41287694cb | |||
| 04a439a0a0 | |||
| e528a8c7a4 | |||
| 362751e4ef | |||
| 0db3940cc4 | |||
| e2bb5e1726 | |||
| 572ac09660 | |||
| 9f5a483256 | |||
| cc752ad6a0 | |||
| ce2ec035f4 | |||
| 20ed0a15a4 | |||
| a02aeaf972 | |||
| ca8912375c | |||
| 6b8d490249 | |||
| 84b512c62c | |||
| 1343ef5915 | |||
| 65f3bb01be | |||
| 10805cb6ec | |||
| dd01dd7bef | |||
| 1057bd38cf | |||
| fcd6ec99d3 | |||
| d2113dc9f5 | |||
| 3d62ff0e07 | |||
| 90adbe0451 | |||
| f6defeff5d | |||
| 0a1225d0df | |||
| 527952102a | |||
| 8a4e939a10 | |||
| f8395886d3 | |||
| 9527c93a1c | |||
| 37e13361f5 | |||
| bb6db74167 | |||
| 1f95fac699 | |||
| 24e4e674a5 | |||
| 460e5d792d | |||
| 02d821c0ab | |||
| d12b34388d | |||
| e686f5a249 | |||
| 33c7c28dde | |||
| 04c057238b | |||
| bfe55118dd | |||
| f825af06f0 | |||
| 2205bdd469 | |||
| 0f3b69c79d | |||
| cf10e318d6 | |||
| 1ab9dbab60 | |||
| 4f0fc55385 | |||
| 23195693ed | |||
| a7fa41612c | |||
| 5f91ea34de | |||
| ea9c186e36 | |||
| a97477337d | |||
| fec6f187d1 | |||
| 1a96c294ee | |||
| 19a28e2c9f | |||
| 1984d40e33 | |||
| cf4206d987 | |||
| cc4c232956 | |||
| 226f85efcb | |||
| 2aa8e17c88 | |||
| 3365139a6c | |||
| 2cc3c16ab1 | |||
| 3a0b397054 | |||
| b15eaeda16 | |||
| e049190ff1 | |||
| dba59cf903 | |||
| 56122cbe2f | |||
| c77edaee34 | |||
| 21ce21cc07 | |||
| 6cf15615e8 | |||
| a1399426c3 | |||
| 81249724e3 | |||
| bdcffa90eb | |||
| 1ee4c4ba62 | |||
| 7935a366f4 | |||
| 08b3af4387 | |||
| 8e96402819 | |||
| 1c104a385d | |||
| ec6f0811a0 | |||
| a257e7a3ee | |||
| acaddf9cd9 | |||
| bb50368d55 | |||
| 8503d53018 | |||
| 8d4ba0aa83 | |||
| 5abf7841f8 | |||
| ff67e06844 | |||
| 5f74c2afdf | |||
| 96b3f17d02 | |||
| 58c2c10cdb | |||
| e6cc3c4752 | |||
| 9f0e359d73 | |||
| 82c5dfc30a | |||
| ee2d036bbf | |||
| cf363103d2 | |||
| 41af5aaae2 | |||
| f0212f3f15 | |||
| 81144bb969 | |||
| b00a7d0619 | |||
| ef6dec17ba | |||
| b067bb6304 | |||
| ed18c145cd | |||
| 8247e6069d | |||
| 38ca109766 | |||
| 6d5753c548 | |||
| 0fa909a889 | |||
| 38ae319bea | |||
| 287e30239c | |||
| 530fc5a431 | |||
| d3e25db395 | |||
| f3cd42887d | |||
| 3c52cb1790 | |||
| 8309e0ecb0 | |||
| 22e9451192 | |||
| a1641cdec9 | |||
| 8f0fd7ecf5 | |||
| c7f564e866 | |||
| c9ae3f4efe | |||
| 6d0698ba0e | |||
| 155da0cd09 | |||
| b4f3adb6ee | |||
| 6b232bd8f6 | |||
| 323d4a484d | |||
| 6af25fb423 | |||
| 35b6c72634 | |||
| 5f7f6319eb | |||
| 47592fbf42 | |||
| 80a38c1e45 | |||
| c599ea0737 | |||
| 9040c64e5b | |||
| 905073a506 | |||
| 656666e722 | |||
| 460c34df4b | |||
| d1ea1ec21b | |||
| e253beaa2b | |||
| 9021e52a6f | |||
| 5b6e67119f | |||
| ad1739c63f | |||
| b415b9aacf | |||
| dc9d287e33 | |||
| 135be952fe | |||
| c21a8573b4 | |||
| 5733b0e4cb | |||
| 5c3f8efd23 | |||
| 076d9311fa | |||
| c5099ff407 | |||
| 4277e9f5d6 | |||
| 882b770ecb | |||
| a21f586c3b | |||
| 2fbd948a67 | |||
| 49cf82a0ac | |||
| 6412dcb896 | |||
| 16e80258b8 | |||
| b875bbcdf1 | |||
| 6b21c4f6c9 | |||
| e8bceaa284 | |||
| 59abeeb097 | |||
| d95b79f9eb | |||
| 1861cf4975 | |||
| 427c79b24b | |||
| f3270d4ce8 | |||
| 4974585d04 | |||
| 5268914b3f |
+6
-5
@@ -3,12 +3,16 @@
|
|||||||
_ReSharper*
|
_ReSharper*
|
||||||
*.opensdf
|
*.opensdf
|
||||||
*.sdf
|
*.sdf
|
||||||
|
*.suo
|
||||||
*.dir
|
*.dir
|
||||||
*.vcxproj*
|
*.vcxproj*
|
||||||
*.sln
|
*.sln
|
||||||
Win32
|
Win32
|
||||||
|
x64
|
||||||
Debug
|
Debug
|
||||||
Release
|
Release
|
||||||
|
MinSizeRel
|
||||||
|
RelWithDebInfo
|
||||||
|
|
||||||
# CMake files
|
# CMake files
|
||||||
Makefile
|
Makefile
|
||||||
@@ -21,6 +25,7 @@ cmake_uninstall.cmake
|
|||||||
docs/Doxyfile
|
docs/Doxyfile
|
||||||
docs/html
|
docs/html
|
||||||
docs/warnings.txt
|
docs/warnings.txt
|
||||||
|
docs/doxygen_sqlite3.db
|
||||||
src/glfw_config.h
|
src/glfw_config.h
|
||||||
src/glfw3.pc
|
src/glfw3.pc
|
||||||
src/glfw3Config.cmake
|
src/glfw3Config.cmake
|
||||||
@@ -50,20 +55,16 @@ examples/simple
|
|||||||
examples/wave
|
examples/wave
|
||||||
tests/*.app
|
tests/*.app
|
||||||
tests/*.exe
|
tests/*.exe
|
||||||
tests/accuracy
|
|
||||||
tests/clipboard
|
tests/clipboard
|
||||||
tests/cursor
|
tests/cursor
|
||||||
tests/cursoranim
|
|
||||||
tests/defaults
|
|
||||||
tests/empty
|
tests/empty
|
||||||
tests/events
|
tests/events
|
||||||
tests/fsaa
|
|
||||||
tests/gamma
|
tests/gamma
|
||||||
tests/glfwinfo
|
tests/glfwinfo
|
||||||
tests/iconify
|
tests/iconify
|
||||||
tests/joysticks
|
tests/joysticks
|
||||||
tests/monitors
|
tests/monitors
|
||||||
tests/peter
|
tests/msaa
|
||||||
tests/reopen
|
tests/reopen
|
||||||
tests/sharing
|
tests/sharing
|
||||||
tests/tearing
|
tests/tearing
|
||||||
|
|||||||
@@ -5,33 +5,33 @@
|
|||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>English</string>
|
<string>English</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>${APPLE_GUI_EXECUTABLE}</string>
|
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
|
||||||
<key>CFBundleGetInfoString</key>
|
<key>CFBundleGetInfoString</key>
|
||||||
<string>${APPLE_GUI_INFO_STRING}</string>
|
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>${APPLE_GUI_ICON}</string>
|
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>${APPLE_GUI_IDENTIFIER}</string>
|
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundleLongVersionString</key>
|
<key>CFBundleLongVersionString</key>
|
||||||
<string>${APPLE_GUI_LONG_VERSION_STRING}</string>
|
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>${APPLE_GUI_BUNDLE_NAME}</string>
|
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>${APPLE_GUI_SHORT_VERSION_STRING}</string>
|
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>${APPLE_GUI_BUNDLE_VERSION}</string>
|
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
|
||||||
<key>CSResourcesFileMapped</key>
|
<key>CSResourcesFileMapped</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>LSRequiresCarbon</key>
|
<key>LSRequiresCarbon</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>${APPLE_GUI_COPYRIGHT}</string>
|
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
||||||
<key>NSHighResolutionCapable</key>
|
<key>NSHighResolutionCapable</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
find_path(EGL_INCLUDE_DIR NAMES EGL/egl.h PATHS /opt/vc/include)
|
find_path(EGL_INCLUDE_DIR NAMES EGL/egl.h PATHS /opt/vc/include)
|
||||||
|
|
||||||
set(EGL_NAMES ${EGL_NAMES} egl EGL)
|
set(EGL_NAMES ${EGL_NAMES} egl EGL libEGL)
|
||||||
find_library(EGL_LIBRARY NAMES ${EGL_NAMES} PATHS /opt/vc/lib)
|
find_library(EGL_LIBRARY NAMES ${EGL_NAMES} PATHS /opt/vc/lib)
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
find_path(GLESv1_INCLUDE_DIR NAMES GLES/gl.h PATHS /opt/vc/include)
|
find_path(GLESv1_INCLUDE_DIR NAMES GLES/gl.h PATHS /opt/vc/include)
|
||||||
|
|
||||||
set(GLESv1_NAMES ${GLESv1_NAMES} GLESv1_CM)
|
set(GLESv1_NAMES ${GLESv1_NAMES} GLESv1_CM libGLES_CM)
|
||||||
find_library(GLESv1_LIBRARY NAMES ${GLESv1_NAMES} PATHS /opt/vc/lib)
|
find_library(GLESv1_LIBRARY NAMES ${GLESv1_NAMES} PATHS /opt/vc/lib)
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
find_path(GLESv2_INCLUDE_DIR NAMES GLES2/gl2.h PATHS /opt/vc/include)
|
find_path(GLESv2_INCLUDE_DIR NAMES GLES2/gl2.h PATHS /opt/vc/include)
|
||||||
|
|
||||||
set(GLESv2_NAMES ${GLESv2_NAMES} GLESv2)
|
set(GLESv2_NAMES ${GLESv2_NAMES} GLESv2 libGLESv2)
|
||||||
find_library(GLESv2_LIBRARY NAMES ${GLESv2_NAMES} PATHS /opt/vc/lib)
|
find_library(GLESv2_LIBRARY NAMES ${GLESv2_NAMES} PATHS /opt/vc/lib)
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|||||||
+38
-73
@@ -1,8 +1,8 @@
|
|||||||
project(GLFW C)
|
project(GLFW C)
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 2.8.9)
|
cmake_minimum_required(VERSION 2.8.12)
|
||||||
|
|
||||||
if (CMAKE_VERSION VERSION_EQUAL "3.0" OR CMAKE_VERSION VERSION_GREATER "3.0")
|
if (NOT CMAKE_VERSION VERSION_LESS "3.0")
|
||||||
# Until all major package systems have moved to CMake 3,
|
# Until all major package systems have moved to CMake 3,
|
||||||
# we stick with the older INSTALL_NAME_DIR mechanism
|
# we stick with the older INSTALL_NAME_DIR mechanism
|
||||||
cmake_policy(SET CMP0042 OLD)
|
cmake_policy(SET CMP0042 OLD)
|
||||||
@@ -10,7 +10,7 @@ endif()
|
|||||||
|
|
||||||
set(GLFW_VERSION_MAJOR "3")
|
set(GLFW_VERSION_MAJOR "3")
|
||||||
set(GLFW_VERSION_MINOR "1")
|
set(GLFW_VERSION_MINOR "1")
|
||||||
set(GLFW_VERSION_PATCH "1")
|
set(GLFW_VERSION_PATCH "2")
|
||||||
set(GLFW_VERSION_EXTRA "")
|
set(GLFW_VERSION_EXTRA "")
|
||||||
set(GLFW_VERSION "${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}")
|
set(GLFW_VERSION "${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}")
|
||||||
set(GLFW_VERSION_FULL "${GLFW_VERSION}.${GLFW_VERSION_PATCH}${GLFW_VERSION_EXTRA}")
|
set(GLFW_VERSION_FULL "${GLFW_VERSION}.${GLFW_VERSION_PATCH}${GLFW_VERSION_EXTRA}")
|
||||||
@@ -26,8 +26,7 @@ option(GLFW_INSTALL "Generate installation target" ON)
|
|||||||
option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF)
|
option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
option(GLFW_USE_DWM_SWAP_INTERVAL "Set swap interval even when DWM compositing is enabled" OFF)
|
option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF)
|
||||||
option(GLFW_USE_OPTIMUS_HPG "Force use of high-performance GPU on Optimus systems" OFF)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
@@ -58,6 +57,8 @@ elseif (GLFW_USE_MIR)
|
|||||||
set(GLFW_USE_EGL ON)
|
set(GLFW_USE_EGL ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules")
|
||||||
|
|
||||||
if (GLFW_USE_EGL)
|
if (GLFW_USE_EGL)
|
||||||
set(GLFW_CLIENT_LIBRARY "opengl" CACHE STRING
|
set(GLFW_CLIENT_LIBRARY "opengl" CACHE STRING
|
||||||
"The client library to use; one of opengl, glesv1 or glesv2")
|
"The client library to use; one of opengl, glesv1 or glesv2")
|
||||||
@@ -72,7 +73,6 @@ if (GLFW_USE_EGL)
|
|||||||
message(FATAL_ERROR "Unsupported client library")
|
message(FATAL_ERROR "Unsupported client library")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMake/modules")
|
|
||||||
find_package(EGL REQUIRED)
|
find_package(EGL REQUIRED)
|
||||||
|
|
||||||
if (NOT _GLFW_USE_OPENGL)
|
if (NOT _GLFW_USE_OPENGL)
|
||||||
@@ -137,7 +137,6 @@ endif()
|
|||||||
|
|
||||||
if (MINGW)
|
if (MINGW)
|
||||||
# Enable link-time exploit mitigation features enabled by default on MSVC
|
# Enable link-time exploit mitigation features enabled by default on MSVC
|
||||||
|
|
||||||
include(CheckCCompilerFlag)
|
include(CheckCCompilerFlag)
|
||||||
|
|
||||||
# Compatibility with data execution prevention (DEP)
|
# Compatibility with data execution prevention (DEP)
|
||||||
@@ -160,6 +159,12 @@ if (MINGW)
|
|||||||
if (_GLFW_HAS_64ASLR)
|
if (_GLFW_HAS_64ASLR)
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--high-entropy-va ${CMAKE_SHARED_LINKER_FLAGS}")
|
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--high-entropy-va ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# HACK: When building on MinGW, WINVER and UNICODE need to be defined before
|
||||||
|
# the inclusion of stddef.h (by glfw3.h), which is itself included before
|
||||||
|
# win32_platform.h. We define them here until a saner solution can be found
|
||||||
|
# NOTE: MinGW-w64 and Visual C++ do /not/ need this hack.
|
||||||
|
add_definitions(-DUNICODE -DWINVER=0x0501)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
@@ -204,6 +209,25 @@ else()
|
|||||||
message(FATAL_ERROR "No supported platform was detected")
|
message(FATAL_ERROR "No supported platform was detected")
|
||||||
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()
|
||||||
|
endif()
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
# Use Win32 for window creation
|
# Use Win32 for window creation
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
@@ -211,19 +235,8 @@ if (_GLFW_WIN32)
|
|||||||
|
|
||||||
list(APPEND glfw_PKG_LIBS "-lgdi32")
|
list(APPEND glfw_PKG_LIBS "-lgdi32")
|
||||||
|
|
||||||
if (GLFW_USE_DWM_SWAP_INTERVAL)
|
if (GLFW_USE_HYBRID_HPG)
|
||||||
set(_GLFW_USE_DWM_SWAP_INTERVAL 1)
|
set(_GLFW_USE_HYBRID_HPG 1)
|
||||||
endif()
|
|
||||||
if (GLFW_USE_OPTIMUS_HPG)
|
|
||||||
set(_GLFW_USE_OPTIMUS_HPG 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# HACK: When building on MinGW, WINVER and UNICODE need to be defined before
|
|
||||||
# the inclusion of stddef.h (by glfw3.h), which is itself included before
|
|
||||||
# win32_platform.h. We define them here until a saner solution can be found
|
|
||||||
# NOTE: MinGW-w64 and Visual C++ do /not/ need this hack.
|
|
||||||
if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU")
|
|
||||||
add_definitions(-DUNICODE -DWINVER=0x0501)
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -250,9 +263,6 @@ if (_GLFW_X11)
|
|||||||
# Set up library and include paths
|
# Set up library and include paths
|
||||||
list(APPEND glfw_INCLUDE_DIRS "${X11_X11_INCLUDE_PATH}")
|
list(APPEND glfw_INCLUDE_DIRS "${X11_X11_INCLUDE_PATH}")
|
||||||
list(APPEND glfw_LIBRARIES "${X11_X11_LIB}" "${CMAKE_THREAD_LIBS_INIT}")
|
list(APPEND glfw_LIBRARIES "${X11_X11_LIB}" "${CMAKE_THREAD_LIBS_INIT}")
|
||||||
if (UNIX AND NOT APPLE)
|
|
||||||
list(APPEND glfw_LIBRARIES "${RT_LIBRARY}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Check for XRandR (modern resolution switching and gamma control)
|
# Check for XRandR (modern resolution switching and gamma control)
|
||||||
if (NOT X11_Xrandr_FOUND)
|
if (NOT X11_Xrandr_FOUND)
|
||||||
@@ -309,20 +319,6 @@ if (_GLFW_X11)
|
|||||||
|
|
||||||
list(APPEND glfw_INCLUDE_DIR "${X11_Xkb_INCLUDE_PATH}")
|
list(APPEND glfw_INCLUDE_DIR "${X11_Xkb_INCLUDE_PATH}")
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
||||||
# Check for Xcursor
|
# Check for Xcursor
|
||||||
if (NOT X11_Xcursor_FOUND)
|
if (NOT X11_Xcursor_FOUND)
|
||||||
message(FATAL_ERROR "The Xcursor libraries and headers were not found")
|
message(FATAL_ERROR "The Xcursor libraries and headers were not found")
|
||||||
@@ -348,13 +344,6 @@ if (_GLFW_WAYLAND)
|
|||||||
list(APPEND glfw_PKG_DEPS "xkbcommon")
|
list(APPEND glfw_PKG_DEPS "xkbcommon")
|
||||||
list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
|
list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
|
||||||
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
|
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
|
||||||
|
|
||||||
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()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
@@ -371,13 +360,6 @@ if (_GLFW_MIR)
|
|||||||
list(APPEND glfw_PKG_DEPS "xkbcommon")
|
list(APPEND glfw_PKG_DEPS "xkbcommon")
|
||||||
list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
|
list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
|
||||||
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
|
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
|
||||||
|
|
||||||
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()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
@@ -390,32 +372,10 @@ if (_GLFW_GLX)
|
|||||||
|
|
||||||
list(APPEND glfw_PKG_DEPS "gl")
|
list(APPEND glfw_PKG_DEPS "gl")
|
||||||
|
|
||||||
include(CheckFunctionExists)
|
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_LIBRARIES "${OPENGL_gl_LIBRARY}")
|
|
||||||
check_function_exists(glXGetProcAddress _GLFW_HAS_GLXGETPROCADDRESS)
|
|
||||||
check_function_exists(glXGetProcAddressARB _GLFW_HAS_GLXGETPROCADDRESSARB)
|
|
||||||
check_function_exists(glXGetProcAddressEXT _GLFW_HAS_GLXGETPROCADDRESSEXT)
|
|
||||||
|
|
||||||
if (NOT _GLFW_HAS_GLXGETPROCADDRESS AND
|
|
||||||
NOT _GLFW_HAS_GLXGETPROCADDRESSARB AND
|
|
||||||
NOT _GLFW_HAS_GLXGETPROCADDRESSEXT)
|
|
||||||
message(WARNING "No glXGetProcAddressXXX variant found")
|
|
||||||
|
|
||||||
# Check for dlopen support as a fallback
|
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_DL_LIBS}")
|
|
||||||
check_function_exists(dlopen _GLFW_HAS_DLOPEN)
|
|
||||||
if (NOT _GLFW_HAS_DLOPEN)
|
|
||||||
message(FATAL_ERROR "No entry point retrieval mechanism found")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (CMAKE_DL_LIBS)
|
if (CMAKE_DL_LIBS)
|
||||||
list(APPEND glfw_LIBRARIES "${CMAKE_DL_LIBS}")
|
list(APPEND glfw_LIBRARIES "${CMAKE_DL_LIBS}")
|
||||||
list(APPEND glfw_PKG_LIBS "-l${CMAKE_DL_LIBS}")
|
list(APPEND glfw_PKG_LIBS "-l${CMAKE_DL_LIBS}")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
@@ -442,6 +402,11 @@ if (_GLFW_EGL)
|
|||||||
list(APPEND glfw_PKG_DEPS "glesv2")
|
list(APPEND glfw_PKG_DEPS "glesv2")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (CMAKE_DL_LIBS)
|
||||||
|
list(APPEND glfw_LIBRARIES "${CMAKE_DL_LIBS}")
|
||||||
|
list(APPEND glfw_PKG_LIBS "-l${CMAKE_DL_LIBS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
|
|||||||
@@ -6,8 +6,9 @@ GLFW is a free, Open Source, multi-platform library for OpenGL and OpenGL ES
|
|||||||
application development. It provides a simple, platform-independent API for
|
application development. It provides a simple, platform-independent API for
|
||||||
creating windows and contexts, reading input, handling events, etc.
|
creating windows and contexts, reading input, handling events, etc.
|
||||||
|
|
||||||
Version 3.1.1 adds fixes for a number of bugs that together affect all supported
|
Version 3.1.2 adds fixes for a large number of bugs that together affect all
|
||||||
platforms, most notably workarounds for bugs in some popular window managers.
|
supported platforms, as well as dynamic loading work that simplifies compilation
|
||||||
|
and linking.
|
||||||
|
|
||||||
If you are new to GLFW, you may find the
|
If you are new to GLFW, you may find the
|
||||||
[introductory tutorial](http://www.glfw.org/docs/latest/quick.html) for GLFW
|
[introductory tutorial](http://www.glfw.org/docs/latest/quick.html) for GLFW
|
||||||
@@ -59,30 +60,69 @@ GLFW bundles a number of dependencies in the `deps/` directory.
|
|||||||
examples
|
examples
|
||||||
- An OpenGL 3.2 core loader generated by
|
- An OpenGL 3.2 core loader generated by
|
||||||
[glad](https://github.com/Dav1dde/glad) for examples using modern OpenGL
|
[glad](https://github.com/Dav1dde/glad) for examples using modern OpenGL
|
||||||
|
- [linmath.h](https://github.com/datenwolf/linmath.h) for linear algebra in
|
||||||
|
examples
|
||||||
|
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
- Made library compilation fail if any header option macros are defined
|
- Made all client API functions dynamically loaded
|
||||||
- Removed support for LCC and Borland C++
|
- Changed minimum required CMake version to 2.8.12
|
||||||
- Bugfix: `glfwSetTime` silently accepted invalid values
|
- Replaced GLU with [linmath.h](https://github.com/datenwolf/linmath.h) in
|
||||||
- [Cocoa] Bugfix: `NSHighResolutionCapable` was not enabled for test and
|
|
||||||
example programs
|
example programs
|
||||||
- [Cocoa] Bugfix: Sleeping monitors were not included in the monitor list
|
- Merged all cursor test programs into the `cursor` program
|
||||||
- [Cocoa] Bugfix: `glfwSetWindowSize` did not change the video mode for full
|
- Removed all mention of GLU in examples, build files and package dependencies
|
||||||
screen windows
|
- Bugfix: Initialization failed on headless systems
|
||||||
- [X11] Added support for Cygwin-X
|
- Bugfix: The cached current context could get out of sync
|
||||||
- [X11] Made XInput2 optional at compile-time
|
- Bugfix: `glfwIconifyWindow` did not restore the original video mode for full
|
||||||
- [X11] Made Xxf86vm optional at compile-time
|
screen windows created with `GLFW_AUTO_ICONIFY`
|
||||||
- [X11] Bugfix: Moved `_NET_REQUEST_FRAME_EXTENTS` request to
|
- [Win32] Renamed hybrid GPU override compile-time option to
|
||||||
`glfwGetWindowFrameSize` and added protocol-breaking timeout
|
`_GLFW_USE_HYBRID_HPG` and added support for AMD PowerXpress systems
|
||||||
as a workaround for broken support in Unity, Fluxbox and Xfwm
|
- [Win32] Bugfix: `glfwGetVideoModes` included unusable modes on some systems
|
||||||
- [X11] Bugfix: Mouse button `GLFW_MOUSE_BUTTON_4` was never used
|
- [Win32] Bugfix: `glfwWaitEvents` would return directly for focused windows in
|
||||||
- [X11] Bugfix: `glfwTerminate` could close an unrelated file descriptor
|
disabled cursor mode
|
||||||
- [X11] Bugfix: Some WMs (KWM, Fluxbox) did not respect cursor redefinition
|
- [Cocoa] Bugfix: The cached `NSScreen` for a monitor could get out of sync
|
||||||
- [WGL] Bugfix: The context flags debug bit was not set for OpenGL ES
|
- [Cocoa] Bugfix: The `GLFW_AUTO_ICONIFY` window hint was ignored
|
||||||
- [GLX] Bugfix: The context flags debug bit was not set for OpenGL ES
|
- [Cocoa] Bugfix: Resizing a window to its minimum size would segfault
|
||||||
- [EGL] Bugfix: The context flags debug bit was not set for OpenGL ES
|
- [Cocoa] Bugfix: Creating or showing a window would make its context current
|
||||||
|
- [Cocoa] Bugfix: Joysticks connected after `glfwInit` were not detected
|
||||||
|
- [Cocoa] Bugfix: Cursor creation failed unless a window had been created.
|
||||||
|
- [Cocoa] Bugfix: Window refresh events were not generated by iconification or
|
||||||
|
restoration
|
||||||
|
- [Cocoa] Bugfix: The primary monitor would get reported as disconnected when
|
||||||
|
entering full screen on a dual-GPU machine with automatic
|
||||||
|
graphics switching
|
||||||
|
- [Cocoa] Bugfix: The original video modes were not restored when the
|
||||||
|
application was hidden
|
||||||
|
- [X11] Bugfix: `glfwInit` would segfault on systems without RandR
|
||||||
|
- [X11] Bugfix: The response to `_NET_WM_PING` was sent to the wrong window
|
||||||
|
- [X11] Bugfix: Character input via XIM did not work in many cases
|
||||||
|
- [X11] Bugfix: No fallback existed for missing `_NET_ACTIVE_WINDOW` support
|
||||||
|
- [X11] Bugfix: Some significant window focus events were ignored
|
||||||
|
- [X11] Bugfix: The `GLFW_AUTO_ICONIFY` window hint was ignored
|
||||||
|
- [X11] Bugfix: The original video mode was not restored on iconification of
|
||||||
|
full screen windows
|
||||||
|
- [X11] Bugfix: `GLFW_ARROW_CURSOR` selected the wrong cursor image
|
||||||
|
- [X11] Bugfix: The `GLFW_DECORATED` hint was not ignored for full screen
|
||||||
|
- [X11] Bugfix: `glfwWaitEvents` did not handle `EINTR` for `select`
|
||||||
|
- [X11] Bugfix: `glfwWaitEvents` could return when no events were available
|
||||||
|
- [X11] Bugfix: `XkbGetKeyboard` fails on XWayland
|
||||||
|
- [X11] Bugfix: Character input did not work correctly for non-UTF-8 locales
|
||||||
|
- [X11] Bugfix: Long input sequences generated by IMEs were discarded
|
||||||
|
- [WGL] Made all WGL functions dynamically loaded
|
||||||
|
- [WGL] Removed `GLFW_USE_DWM_SWAP_INTERVAL` compile-time option
|
||||||
|
- [WGL] Bugfix: Swap interval was ignored when DWM was enabled
|
||||||
|
- [WGL] Bugfix: Failure to find a pixel format was reported incorrectly
|
||||||
|
- [GLX] Added dependency on `libdl` on systems where it provides `dlopen`
|
||||||
|
- [GLX] Made all GLX functions dynamically loaded
|
||||||
|
- [GLX] Removed `_GLFW_HAS_GLXGETPROCADDRESS*` and `_GLFW_HAS_DLOPEN`
|
||||||
|
compile-time options
|
||||||
|
- [GLX] Bugfix: Failure to find a `GLXFBConfig` was reported incorrectly
|
||||||
|
- [EGL] Made all EGL functions dynamically loaded
|
||||||
|
- [EGL] Bugfix: `glfwGetProcAddress` did not return the addresses of core
|
||||||
|
functions
|
||||||
|
- [EGL] Bugfix: Failure to find an `EGLConfig` was reported incorrectly
|
||||||
|
- [NSGL] Bugfix: Failure to find a pixel format was reported incorrectly
|
||||||
|
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
@@ -100,9 +140,7 @@ request, please file it in the
|
|||||||
[issue tracker](https://github.com/glfw/glfw/issues) on GitHub.
|
[issue tracker](https://github.com/glfw/glfw/issues) on GitHub.
|
||||||
|
|
||||||
Finally, if you're interested in helping out with the development of GLFW or
|
Finally, if you're interested in helping out with the development of GLFW or
|
||||||
porting it to your favorite platform, we have an occasionally active
|
porting it to your favorite platform, join us on GitHub or IRC.
|
||||||
[developer's mailing list](https://lists.stacken.kth.se/mailman/listinfo/glfw-dev),
|
|
||||||
or you could join us on `#glfw`.
|
|
||||||
|
|
||||||
|
|
||||||
## Acknowledgements
|
## Acknowledgements
|
||||||
@@ -121,6 +159,7 @@ skills.
|
|||||||
- Doug Binks
|
- Doug Binks
|
||||||
- blanco
|
- blanco
|
||||||
- Martin Capitanio
|
- Martin Capitanio
|
||||||
|
- Chi-kwan Chan
|
||||||
- Lambert Clara
|
- Lambert Clara
|
||||||
- Andrew Corrigan
|
- Andrew Corrigan
|
||||||
- Noel Cower
|
- Noel Cower
|
||||||
@@ -142,14 +181,17 @@ skills.
|
|||||||
- heromyth
|
- heromyth
|
||||||
- Lucas Hinderberger
|
- Lucas Hinderberger
|
||||||
- Paul Holden
|
- Paul Holden
|
||||||
|
- Aaron Jacobs
|
||||||
- Toni Jovanoski
|
- Toni Jovanoski
|
||||||
- Arseny Kapoulkine
|
- Arseny Kapoulkine
|
||||||
- Osman Keskin
|
- Osman Keskin
|
||||||
- Cameron King
|
- Cameron King
|
||||||
- Peter Knut
|
- Peter Knut
|
||||||
|
- Eric Larson
|
||||||
- Robin Leffmann
|
- Robin Leffmann
|
||||||
- Glenn Lewis
|
- Glenn Lewis
|
||||||
- Shane Liesegang
|
- Shane Liesegang
|
||||||
|
- Eyal Lotem
|
||||||
- Дмитри Малышев
|
- Дмитри Малышев
|
||||||
- Martins Mozeiko
|
- Martins Mozeiko
|
||||||
- Tristam MacDonald
|
- Tristam MacDonald
|
||||||
@@ -173,6 +215,7 @@ skills.
|
|||||||
- Peoro
|
- Peoro
|
||||||
- Braden Pellett
|
- Braden Pellett
|
||||||
- Arturo J. Pérez
|
- Arturo J. Pérez
|
||||||
|
- Emmanuel Gil Peyrot
|
||||||
- Cyril Pichard
|
- Cyril Pichard
|
||||||
- Pieroman
|
- Pieroman
|
||||||
- Jorge Rodriguez
|
- Jorge Rodriguez
|
||||||
@@ -191,6 +234,7 @@ skills.
|
|||||||
- Julian Squires
|
- Julian Squires
|
||||||
- Johannes Stein
|
- Johannes Stein
|
||||||
- Justin Stoecker
|
- Justin Stoecker
|
||||||
|
- Elviss Strazdins
|
||||||
- Nathan Sweet
|
- Nathan Sweet
|
||||||
- TTK-Bandit
|
- TTK-Bandit
|
||||||
- Sergey Tikhomirov
|
- Sergey Tikhomirov
|
||||||
|
|||||||
Vendored
+571
@@ -0,0 +1,571 @@
|
|||||||
|
#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 sqrtf(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) {
|
||||||
|
vec3_norm(u, u);
|
||||||
|
mat4x4 T;
|
||||||
|
mat4x4_from_vec3_mul_outer(T, u, u);
|
||||||
|
|
||||||
|
mat4x4 S = {
|
||||||
|
{ 0, u[2], -u[1], 0},
|
||||||
|
{-u[2], 0, u[0], 0},
|
||||||
|
{ u[1], -u[0], 0, 0},
|
||||||
|
{ 0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
mat4x4_scale(S, S, s);
|
||||||
|
|
||||||
|
mat4x4 C;
|
||||||
|
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 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 */
|
||||||
|
float 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)
|
||||||
|
{
|
||||||
|
mat4x4_dup(R, M);
|
||||||
|
float s = 1.;
|
||||||
|
vec3 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[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_sub(f, center, eye);
|
||||||
|
vec3_norm(f, f);
|
||||||
|
|
||||||
|
vec3 s;
|
||||||
|
vec3_mul_cross(s, f, up);
|
||||||
|
vec3_norm(s, s);
|
||||||
|
|
||||||
|
vec3 t;
|
||||||
|
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) {
|
||||||
|
vec3 v;
|
||||||
|
vec3_scale(v, axis, sinf(angle / 2));
|
||||||
|
int i;
|
||||||
|
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 = sqrtf(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
|
||||||
Vendored
+3
-2
@@ -24,6 +24,7 @@ freely, subject to the following restrictions:
|
|||||||
/* 2013-01-06 Camilla Berglund <elmindreda@elmindreda.org>
|
/* 2013-01-06 Camilla Berglund <elmindreda@elmindreda.org>
|
||||||
*
|
*
|
||||||
* Added casts from time_t to DWORD to avoid warnings on VC++.
|
* Added casts from time_t to DWORD to avoid warnings on VC++.
|
||||||
|
* Fixed time retrieval on POSIX systems.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tinycthread.h"
|
#include "tinycthread.h"
|
||||||
@@ -294,7 +295,7 @@ int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
|
|||||||
{
|
{
|
||||||
#if defined(_TTHREAD_WIN32_)
|
#if defined(_TTHREAD_WIN32_)
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
if (clock_gettime(TIME_UTC, &now) == 0)
|
if (clock_gettime(CLOCK_REALTIME, &now) == 0)
|
||||||
{
|
{
|
||||||
DWORD delta = (DWORD) ((ts->tv_sec - now.tv_sec) * 1000 +
|
DWORD delta = (DWORD) ((ts->tv_sec - now.tv_sec) * 1000 +
|
||||||
(ts->tv_nsec - now.tv_nsec + 500000) / 1000000);
|
(ts->tv_nsec - now.tv_nsec + 500000) / 1000000);
|
||||||
@@ -471,7 +472,7 @@ int thrd_sleep(const struct timespec *time_point, struct timespec *remaining)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Get the current time */
|
/* Get the current time */
|
||||||
if (clock_gettime(TIME_UTC, &now) != 0)
|
if (clock_gettime(CLOCK_REALTIME, &now) != 0)
|
||||||
return -2; // FIXME: Some specific error code?
|
return -2; // FIXME: Some specific error code?
|
||||||
|
|
||||||
#if defined(_TTHREAD_WIN32_)
|
#if defined(_TTHREAD_WIN32_)
|
||||||
|
|||||||
+5
-4
@@ -96,8 +96,8 @@ to that header.
|
|||||||
|
|
||||||
`GLFW_INCLUDE_GLU` makes the header include the GLU header in addition to the
|
`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
|
header selected above. This should only be used with the standard OpenGL header
|
||||||
and only for legacy code. GLU has been deprecated and should not be used in new
|
and only for compatibility with legacy code. GLU has been deprecated and should
|
||||||
code.
|
not be used in new code.
|
||||||
|
|
||||||
@note GLFW does not provide any of the API headers mentioned above. They must
|
@note GLFW does not provide any of the API headers mentioned above. They must
|
||||||
be provided by your development environment or your OpenGL or OpenGL ES SDK.
|
be provided by your development environment or your OpenGL or OpenGL ES SDK.
|
||||||
@@ -254,7 +254,7 @@ You can also use the `glfw3.pc` file without installing it first, by using the
|
|||||||
env PKG_CONFIG_PATH=path/to/glfw/src cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --libs glfw3`
|
env PKG_CONFIG_PATH=path/to/glfw/src cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --libs glfw3`
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The dependencies do not include GLU, as GLFW does not need it. On OS X, GLU is
|
The dependencies do not include GLU, as GLFW does not use it. On OS X, GLU is
|
||||||
built into the OpenGL framework, so if you need GLU you don't need to do
|
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
|
anything extra. If you need GLU and are using Linux or BSD, you should add the
|
||||||
`glu` pkg-config module.
|
`glu` pkg-config module.
|
||||||
@@ -263,7 +263,8 @@ anything extra. If you need GLU and are using Linux or BSD, you should add the
|
|||||||
cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --libs glfw3 glu`
|
cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --libs glfw3 glu`
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
If you are using the static version of the GLFW library, make sure you don't link statically against GLU.
|
If you are using the static version of the GLFW library, make sure you don't
|
||||||
|
link statically against GLU.
|
||||||
|
|
||||||
@code{.sh}
|
@code{.sh}
|
||||||
cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --static --libs glfw3` `pkg-config --libs glu`
|
cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --static --libs glfw3` `pkg-config --libs glu`
|
||||||
|
|||||||
@@ -117,6 +117,11 @@ 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
|
extension is unavailable, the `GLFW_CONTEXT_RELEASE_BEHAVIOR` hint will have no
|
||||||
effect and the context will always be flushed when released.
|
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
|
@section compat_wgl WGL extensions
|
||||||
|
|
||||||
The WGL API is used to create OpenGL contexts on Microsoft Windows and other
|
The WGL API is used to create OpenGL contexts on Microsoft Windows and other
|
||||||
@@ -154,6 +159,11 @@ 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
|
extension is unavailable, the `GLFW_CONTEXT_RELEASE_BEHAVIOR` hint will have no
|
||||||
effect and the context will always be flushed when released.
|
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 OS X
|
@section compat_osx OpenGL 3.2 and later on OS X
|
||||||
|
|
||||||
Support for OpenGL 3.2 and above was introduced with OS X 10.7 and even then
|
Support for OpenGL 3.2 and above was introduced with OS X 10.7 and even then
|
||||||
|
|||||||
+22
-33
@@ -17,8 +17,9 @@ Homebrew, you can simply install its CMake package. If not, you can download
|
|||||||
installers for Windows and OS X from the [CMake website](http://www.cmake.org/).
|
installers for Windows and OS X from the [CMake website](http://www.cmake.org/).
|
||||||
|
|
||||||
@note CMake only generates project files or makefiles. It does not compile the
|
@note CMake only generates project files or makefiles. It does not compile the
|
||||||
actual GLFW library. To compile GLFW, first generate these files and then use
|
actual GLFW library. To compile GLFW, first generate these files for your
|
||||||
them in your chosen development environment to compile the actual GLFW library.
|
chosen development environment and then use them to compile the actual GLFW
|
||||||
|
library.
|
||||||
|
|
||||||
|
|
||||||
@subsection compile_deps Dependencies
|
@subsection compile_deps Dependencies
|
||||||
@@ -89,11 +90,10 @@ Once you have Xcode installed, move on to @ref compile_generate.
|
|||||||
To compile GLFW for X11, you need to have the X11 and OpenGL header packages
|
To compile GLFW for X11, you need to have the X11 and OpenGL header packages
|
||||||
installed, as well as the basic development tools like GCC and make. For
|
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
|
example, on Ubuntu and other distributions based on Debian GNU/Linux, you need
|
||||||
to install the `xorg-dev` and `libglu1-mesa-dev` packages. The former pulls in
|
to install the `xorg-dev` and `libgl1-mesa-dev` packages. The former pulls in
|
||||||
all X.org header packages and the latter pulls in the Mesa OpenGL and GLU
|
all X.org header packages and the latter pulls in the Mesa OpenGL development
|
||||||
packages. GLFW itself doesn't need or use GLU, but some of the examples do.
|
packages. Note that using header files and libraries from Mesa during
|
||||||
Note that using header files and libraries from Mesa during compilation
|
compilation _will not_ tie your binaries to the Mesa implementation of OpenGL.
|
||||||
_will not_ tie your binaries to the Mesa implementation of OpenGL.
|
|
||||||
|
|
||||||
Once you have installed the necessary packages, move on to @ref
|
Once you have installed the necessary packages, move on to @ref
|
||||||
compile_generate.
|
compile_generate.
|
||||||
@@ -127,15 +127,14 @@ cd <glfw-root-dir>
|
|||||||
cmake .
|
cmake .
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
To make an out-of-tree build, make another directory, enter it and run CMake
|
To make an out-of-tree build, make a directory outside of the source tree, enter
|
||||||
with the (relative or absolute) path to the root of the source tree as an
|
it and run CMake with the (relative or absolute) path to the root of the source
|
||||||
argument.
|
tree as an argument.
|
||||||
|
|
||||||
@code{.sh}
|
@code{.sh}
|
||||||
cd <glfw-root-dir>
|
mkdir glfw-build
|
||||||
mkdir build
|
cd glfw-build
|
||||||
cd build
|
cmake <glfw-root-dir>
|
||||||
cmake ..
|
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Once you have generated the project files or makefiles for your chosen
|
Once you have generated the project files or makefiles for your chosen
|
||||||
@@ -222,16 +221,11 @@ DLL version of the Visual C++ library is used. It is recommended to set this to
|
|||||||
`ON`, as this keeps the executable smaller and benefits from security and bug
|
`ON`, as this keeps the executable smaller and benefits from security and bug
|
||||||
fix updates of the Visual C++ runtime.
|
fix updates of the Visual C++ runtime.
|
||||||
|
|
||||||
`GLFW_USE_DWM_SWAP_INTERVAL` determines whether the swap interval is set even
|
`GLFW_USE_HYBRID_HPG` determines whether to export the `NvOptimusEnablement` and
|
||||||
when DWM compositing is enabled. If this is `ON`, the swap interval is set even
|
`AmdPowerXpressRequestHighPerformance` symbols, which force the use of the
|
||||||
if DWM is enabled. It is recommended to set this to `OFF`, as doing otherwise
|
high-performance GPU on Nvidia Optimus and AMD PowerXpress systems. These symbols
|
||||||
can lead to severe jitter.
|
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.
|
||||||
`GLFW_USE_OPTIMUS_HPG` determines whether to export the `NvOptimusEnablement`
|
|
||||||
symbol, which forces the use of the high-performance GPU on Nvidia Optimus
|
|
||||||
systems. This symbol needs 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. See _Enabling
|
|
||||||
High Performance Graphics Rendering on Optimus Systems_ for more details.
|
|
||||||
|
|
||||||
|
|
||||||
@subsubsection compile_options_egl EGL specific CMake options
|
@subsubsection compile_options_egl EGL specific CMake options
|
||||||
@@ -294,18 +288,13 @@ libraries.
|
|||||||
If you are building GLFW as a shared library / dynamic library / DLL then you
|
If you are building GLFW as a shared library / dynamic library / DLL then you
|
||||||
must also define `_GLFW_BUILD_DLL`. Otherwise, you may not define it.
|
must also define `_GLFW_BUILD_DLL`. Otherwise, you may not define it.
|
||||||
|
|
||||||
If you are using the X11 window creation API then you _must_ also select an entry
|
If you are using the X11 window creation API, support for the following X11
|
||||||
point retrieval mechanism.
|
extensions can be enabled:
|
||||||
|
|
||||||
- `_GLFW_HAS_GLXGETPROCADDRESS` to use `glXGetProcAddress` (recommended)
|
|
||||||
- `_GLFW_HAS_GLXGETPROCADDRESSARB` to use `glXGetProcAddressARB` (legacy)
|
|
||||||
- `_GLFW_HAS_GLXGETPROCADDRESSEXT` to use `glXGetProcAddressEXT` (legacy)
|
|
||||||
- `_GLFW_HAS_DLOPEN` to do manual retrieval with `dlopen` (fallback)
|
|
||||||
|
|
||||||
In addition, support for the following X11 extensions can be enabled:
|
|
||||||
|
|
||||||
- `_GLFW_HAS_XINPUT` to use XInput2 for high-resolution cursor motion
|
- `_GLFW_HAS_XINPUT` to use XInput2 for high-resolution cursor motion
|
||||||
(recommended)
|
(recommended)
|
||||||
|
- `_GLFW_HAS_XF86VM` to use Xxf86vm as a fallback when RandR gamma is broken
|
||||||
|
(recommended)
|
||||||
|
|
||||||
If you are using the Cocoa window creation API, the following options are
|
If you are using the Cocoa window creation API, the following options are
|
||||||
available:
|
available:
|
||||||
|
|||||||
+2
-5
@@ -307,13 +307,10 @@ void load_extensions(void)
|
|||||||
{
|
{
|
||||||
if (glfwExtensionSupported("GL_ARB_debug_output"))
|
if (glfwExtensionSupported("GL_ARB_debug_output"))
|
||||||
{
|
{
|
||||||
pfnGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGARBPROC) glfwGetProcAddress("glGetDebugMessageLogARB");
|
pfnGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGARBPROC)
|
||||||
if (pfnGetDebugMessageLog)
|
glfwGetProcAddress("glGetDebugMessageLogARB");
|
||||||
{
|
|
||||||
// Both the extension name and the function pointer are present
|
|
||||||
has_ARB_debug_output = 1;
|
has_ARB_debug_output = 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void some_function(void)
|
void some_function(void)
|
||||||
|
|||||||
+14
-11
@@ -104,15 +104,12 @@ void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod
|
|||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The action is one of `GLFW_PRESS`, `GLFW_REPEAT` or `GLFW_RELEASE`. The key
|
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. These keys still
|
will be `GLFW_KEY_UNKNOWN` if GLFW lacks a key token for it, for example
|
||||||
have unique, if platform-specific scancodes.
|
_E-mail_ and _Play_ keys.
|
||||||
|
|
||||||
The scancode is unique for every key but is platform-specific, so a scancode
|
The scancode is unique for every key, regardless of whether it has a key token.
|
||||||
will map to different keys on different platforms.
|
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.
|
||||||
The key will be `GLFW_KEY_UNKNOWN` for special keys like _E-mail_ or _Play_ that
|
|
||||||
don't have a key token. Those keys will still have unique, if platform-specific
|
|
||||||
scancodes.
|
|
||||||
|
|
||||||
Key states for [named keys](@ref keys) are also saved in per-window state arrays
|
Key states for [named keys](@ref keys) are also saved in per-window state arrays
|
||||||
that can be polled with @ref glfwGetKey.
|
that can be polled with @ref glfwGetKey.
|
||||||
@@ -299,8 +296,9 @@ GLFWcursor* cursor = glfwCreateCursor(&image, 0, 0);
|
|||||||
If cursor creation fails, `NULL` will be returned, so it is necessary to check
|
If cursor creation fails, `NULL` will be returned, so it is necessary to check
|
||||||
the return value.
|
the return value.
|
||||||
|
|
||||||
The image data is 32-bit RGBA, i.e. eight bits per channel. The pixels are
|
The image data is 32-bit, little-endian, non-premultiplied RGBA, i.e. eight bits
|
||||||
arranged canonically as sequential rows, starting from the top-left corner.
|
per channel. The pixels are arranged canonically as sequential rows, starting
|
||||||
|
from the top-left corner.
|
||||||
|
|
||||||
|
|
||||||
@subsubsection cursor_standard Standard cursor creation
|
@subsubsection cursor_standard Standard cursor creation
|
||||||
@@ -546,9 +544,14 @@ converted to one, you can retrieve it with @ref glfwGetClipboardString. See the
|
|||||||
reference documentation for the lifetime of the returned string.
|
reference documentation for the lifetime of the returned string.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
const char* clipboard = glfwGetClipboardString(window);
|
const char* text = glfwGetClipboardString(window);
|
||||||
|
if (text)
|
||||||
|
insert_text(text);
|
||||||
@endcode
|
@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
|
The contents of the system clipboard can be set to a UTF-8 encoded string with
|
||||||
@ref glfwSetClipboardString.
|
@ref glfwSetClipboardString.
|
||||||
|
|
||||||
|
|||||||
+3
-6
@@ -210,12 +210,9 @@ including functions that may called before initialization.
|
|||||||
The reference documentation for every GLFW function states whether it is limited
|
The reference documentation for every GLFW function states whether it is limited
|
||||||
to the main thread.
|
to the main thread.
|
||||||
|
|
||||||
The following categories of functions are and will remain limited to the main
|
Initialization and termination, event processing and the creation and
|
||||||
thread due to the limitations of one or several platforms:
|
destruction of windows, contexts and cursors are all limited to the main thread
|
||||||
|
due to limitations of one or several platforms.
|
||||||
- Initialization and termination
|
|
||||||
- Event processing
|
|
||||||
- Creation and destruction of window, context and cursor objects
|
|
||||||
|
|
||||||
Because event processing must be performed on the main thread, all callbacks
|
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
|
except for the error callback will only be called on that thread. The error
|
||||||
|
|||||||
+1
-1
@@ -429,7 +429,7 @@ invalidating any window handles you may still have.
|
|||||||
|
|
||||||
GLFW 3 does not by default include the GLU header and GLU itself has been
|
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
|
deprecated by [Khronos](https://en.wikipedia.org/wiki/Khronos_Group). __New
|
||||||
projects should avoid using GLU__, but if you need to compile legacy code that
|
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
|
has been moved to GLFW 3, you can request that the GLFW header includes it by
|
||||||
defining `GLFW_INCLUDE_GLU` before the inclusion of the GLFW header.
|
defining `GLFW_INCLUDE_GLU` before the inclusion of the GLFW header.
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -47,8 +47,9 @@ In other words:
|
|||||||
GLFW one and it will detect this
|
GLFW one and it will detect this
|
||||||
|
|
||||||
Starting with version 3.0, the GLU header `glu.h` is no longer included by
|
Starting with version 3.0, the GLU header `glu.h` is no longer included by
|
||||||
default. If you wish to include it, define `GLFW_INCLUDE_GLU` before the
|
default. GLU is deprecated and should not be used in new code. If you need to
|
||||||
inclusion of the GLFW header.
|
include it for legacy code, define `GLFW_INCLUDE_GLU` before the inclusion of
|
||||||
|
the GLFW header.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
#define GLFW_INCLUDE_GLU
|
#define GLFW_INCLUDE_GLU
|
||||||
|
|||||||
+48
-19
@@ -134,9 +134,7 @@ you wish to have the specified attributes.
|
|||||||
Some window hints are hard constraints. These must match the available
|
Some window hints are hard constraints. These must match the available
|
||||||
capabilities _exactly_ for window and context creation to succeed. Hints
|
capabilities _exactly_ for window and context creation to succeed. Hints
|
||||||
that are not hard constraints are matched as closely as possible, but the
|
that are not hard constraints are matched as closely as possible, but the
|
||||||
resulting window and context may differ from what these hints requested. To
|
resulting context and framebuffer may differ from what these hints requested.
|
||||||
find out the actual attributes of the created window and context, use the
|
|
||||||
@ref glfwGetWindowAttrib function.
|
|
||||||
|
|
||||||
The following hints are always hard constraints:
|
The following hints are always hard constraints:
|
||||||
- `GLFW_STEREO`
|
- `GLFW_STEREO`
|
||||||
@@ -151,30 +149,30 @@ context, but are ignored when requesting an OpenGL ES context:
|
|||||||
|
|
||||||
@subsubsection window_hints_wnd Window related hints
|
@subsubsection window_hints_wnd Window related hints
|
||||||
|
|
||||||
`GLFW_RESIZABLE` specifies whether the (windowed mode) window will be resizable
|
`GLFW_RESIZABLE` specifies whether the windowed mode window will be resizable
|
||||||
_by the user_. The window will still be resizable using the @ref
|
_by the user_. The window will still be resizable using the @ref
|
||||||
glfwSetWindowSize function. This hint is ignored for full screen windows.
|
glfwSetWindowSize function. This hint is ignored for full screen windows.
|
||||||
|
|
||||||
`GLFW_VISIBLE` specifies whether the (windowed mode) window will be initially
|
`GLFW_VISIBLE` specifies whether the windowed mode window will be initially
|
||||||
visible. This hint is ignored for full screen windows.
|
visible. This hint is ignored for full screen windows.
|
||||||
|
|
||||||
`GLFW_DECORATED` specifies whether the (windowed mode) window will have window
|
`GLFW_DECORATED` specifies whether the windowed mode window will have window
|
||||||
decorations such as a border, a close widget, etc. This hint is ignored for
|
decorations such as a border, a close widget, etc. An undecorated window may
|
||||||
full screen windows. Note that even though a window may lack a close widget, it
|
still allow the user to generate close events on some platforms. This hint is
|
||||||
is usually still possible for the user to generate close events.
|
ignored for full screen windows.
|
||||||
|
|
||||||
`GLFW_FOCUSED` specifies whether the (windowed mode) window will be given input
|
`GLFW_FOCUSED` specifies whether the windowed mode window will be given input
|
||||||
focus when created. This hint is ignored for full screen and initially hidden
|
focus when created. This hint is ignored for full screen and initially hidden
|
||||||
windows.
|
windows.
|
||||||
|
|
||||||
`GLFW_AUTO_ICONIFY` specifies whether the (full screen) window will
|
`GLFW_AUTO_ICONIFY` specifies whether the full screen window will
|
||||||
automatically iconify and restore the previous video mode on input focus loss.
|
automatically iconify and restore the previous video mode on input focus loss.
|
||||||
This hint is ignored for windowed mode windows.
|
This hint is ignored for windowed mode windows.
|
||||||
|
|
||||||
`GLFW_FLOATING` specifies whether the window will be floating above other
|
`GLFW_FLOATING` specifies whether the windowed mode window will be floating
|
||||||
regular windows, also called topmost or always-on-top. This is intended
|
above other regular windows, also called topmost or always-on-top. This is
|
||||||
primarily for debugging purposes and cannot be used to implement proper full
|
intended primarily for debugging purposes and cannot be used to implement proper
|
||||||
screen windows. This hint is ignored for full screen windows.
|
full screen windows. This hint is ignored for full screen windows.
|
||||||
|
|
||||||
|
|
||||||
@subsubsection window_hints_fb Framebuffer related hints
|
@subsubsection window_hints_fb Framebuffer related hints
|
||||||
@@ -208,6 +206,8 @@ Zero disables multisampling. `GLFW_DONT_CARE` means the application has no
|
|||||||
preference.
|
preference.
|
||||||
|
|
||||||
`GLFW_SRGB_CAPABLE` specifies whether the framebuffer should be sRGB capable.
|
`GLFW_SRGB_CAPABLE` specifies whether the framebuffer should be sRGB capable.
|
||||||
|
If supported, the created context will provide `GL_ARB_framebuffer_sRGB` or
|
||||||
|
`GL_EXT_framebuffer_sRGB`.
|
||||||
|
|
||||||
`GLFW_DOUBLEBUFFER` specifies whether the framebuffer should be double buffered.
|
`GLFW_DOUBLEBUFFER` specifies whether the framebuffer should be double buffered.
|
||||||
You nearly always want to use double buffering. This is a hard constraint.
|
You nearly always want to use double buffering. This is a hard constraint.
|
||||||
@@ -538,7 +538,7 @@ As long as your source file is encoded as UTF-8, you can use any Unicode
|
|||||||
characters directly in the source.
|
characters directly in the source.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
glfwSetWindowTitle(window, "おもひでぽろぽろ");
|
glfwSetWindowTitle(window, "プラネテス");
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
|
|
||||||
@@ -764,6 +764,37 @@ This is `GLFW_LOSE_CONTEXT_ON_RESET` or `GLFW_NO_RESET_NOTIFICATION` if the
|
|||||||
window's context supports robustness, or `GLFW_NO_ROBUSTNESS` otherwise.
|
window's context supports robustness, or `GLFW_NO_ROBUSTNESS` otherwise.
|
||||||
|
|
||||||
|
|
||||||
|
@subsubsection window_attribs_fb Framebuffer related attributes
|
||||||
|
|
||||||
|
The attributes of the default framebuffer (i.e. the framebuffer attached to the
|
||||||
|
window) are not provided by this function but can be queried with both OpenGL
|
||||||
|
and OpenGL ES.
|
||||||
|
|
||||||
|
If you are using version 3.0 or later of OpenGL or OpenGL ES, the
|
||||||
|
`glGetFramebufferAttachmentParameteriv` function can be used to retrieve the
|
||||||
|
number of bits for the red, green, blue, alpha, depth and stencil buffer
|
||||||
|
channels. Otherwise, the `glGetIntegerv` function can be used.
|
||||||
|
|
||||||
|
The number of MSAA samples are always retrieved with `glGetIntegerv`. For
|
||||||
|
contexts supporting framebuffer objects, the number of samples of the currently
|
||||||
|
bound framebuffer is returned.
|
||||||
|
|
||||||
|
Attribute | glGetIntegerv | glGetFramebufferAttachmentParameteriv
|
||||||
|
------------ | ----------------- | -------------------------------------
|
||||||
|
Red bits | `GL_RED_BITS` | `GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE`
|
||||||
|
Green bits | `GL_GREEN_BITS` | `GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE`
|
||||||
|
Blue bits | `GL_BLUE_BITS` | `GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE`
|
||||||
|
Alpha bits | `GL_ALPHA_BITS` | `GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE`
|
||||||
|
Depth bits | `GL_DEPTH_BITS` | `GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE`
|
||||||
|
Stencil bits | `GL_STENCIL_BITS` | `GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE`
|
||||||
|
MSAA samples | `GL_SAMPLES` | _Not provided by this function_
|
||||||
|
|
||||||
|
When calling `glGetFramebufferAttachmentParameteriv`, the red, green, blue and
|
||||||
|
alpha sizes can be queried from the `GL_BACK_LEFT`, while the depth and stencil
|
||||||
|
sizes can be queried from the `GL_DEPTH` and `GL_STENCIL` attachments,
|
||||||
|
respectively.
|
||||||
|
|
||||||
|
|
||||||
@section buffer_swap Buffer swapping
|
@section buffer_swap Buffer swapping
|
||||||
|
|
||||||
GLFW windows are by default double buffered. That means that you have two
|
GLFW windows are by default double buffered. That means that you have two
|
||||||
@@ -796,8 +827,6 @@ interval of one lets you avoid tearing.
|
|||||||
|
|
||||||
Note that this may not work on all machines, as some drivers have
|
Note that this may not work on all machines, as some drivers have
|
||||||
user-controlled settings that override any swap interval the application
|
user-controlled settings that override any swap interval the application
|
||||||
requests. It is also by default disabled on Windows Vista and later when using
|
requests.
|
||||||
DWM (Aero), as using it there sometimes leads to severe jitter. You can
|
|
||||||
forcibly enable it for machines using DWM using @ref compile_options_win32.
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|||||||
+21
-44
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
link_libraries(glfw "${OPENGL_glu_LIBRARY}")
|
link_libraries(glfw)
|
||||||
|
|
||||||
if (BUILD_SHARED_LIBS)
|
if (BUILD_SHARED_LIBS)
|
||||||
add_definitions(-DGLFW_DLL)
|
add_definitions(-DGLFW_DLL)
|
||||||
@@ -22,61 +22,38 @@ set(GETOPT "${GLFW_SOURCE_DIR}/deps/getopt.h"
|
|||||||
set(TINYCTHREAD "${GLFW_SOURCE_DIR}/deps/tinycthread.h"
|
set(TINYCTHREAD "${GLFW_SOURCE_DIR}/deps/tinycthread.h"
|
||||||
"${GLFW_SOURCE_DIR}/deps/tinycthread.c")
|
"${GLFW_SOURCE_DIR}/deps/tinycthread.c")
|
||||||
|
|
||||||
if (APPLE)
|
add_executable(boing WIN32 MACOSX_BUNDLE boing.c)
|
||||||
# Set fancy names for bundles
|
add_executable(gears WIN32 MACOSX_BUNDLE gears.c)
|
||||||
add_executable(Boing MACOSX_BUNDLE boing.c)
|
add_executable(heightmap WIN32 MACOSX_BUNDLE heightmap.c ${GLAD})
|
||||||
add_executable(Gears MACOSX_BUNDLE gears.c)
|
add_executable(particles WIN32 MACOSX_BUNDLE particles.c ${TINYCTHREAD} ${GETOPT})
|
||||||
add_executable(Heightmap MACOSX_BUNDLE heightmap.c ${GLAD})
|
add_executable(simple WIN32 MACOSX_BUNDLE simple.c)
|
||||||
add_executable(Particles MACOSX_BUNDLE particles.c ${TINYCTHREAD})
|
add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c)
|
||||||
add_executable(Simple MACOSX_BUNDLE simple.c)
|
add_executable(wave WIN32 MACOSX_BUNDLE wave.c)
|
||||||
add_executable(SplitView MACOSX_BUNDLE splitview.c)
|
|
||||||
add_executable(Wave MACOSX_BUNDLE wave.c)
|
|
||||||
|
|
||||||
set_target_properties(Boing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Boing")
|
target_link_libraries(particles "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
|
||||||
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 "Split View")
|
|
||||||
set_target_properties(Wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave")
|
|
||||||
|
|
||||||
set_target_properties(Boing Gears Heightmap Particles Simple SplitView Wave PROPERTIES
|
set(WINDOWS_BINARIES boing gears heightmap particles simple splitview wave)
|
||||||
FOLDER "GLFW3/Examples"
|
|
||||||
MACOSX_BUNDLE_INFO_PLIST "${GLFW_SOURCE_DIR}/CMake/AppleInfo.plist")
|
|
||||||
|
|
||||||
else()
|
set_target_properties(${WINDOWS_BINARIES} PROPERTIES FOLDER "GLFW3/Examples")
|
||||||
# Set boring names for executables
|
|
||||||
add_executable(boing WIN32 boing.c)
|
|
||||||
add_executable(gears WIN32 gears.c)
|
|
||||||
add_executable(heightmap WIN32 heightmap.c ${GLAD})
|
|
||||||
add_executable(particles WIN32 particles.c ${TINYCTHREAD} ${GETOPT})
|
|
||||||
add_executable(simple WIN32 simple.c)
|
|
||||||
add_executable(splitview WIN32 splitview.c)
|
|
||||||
add_executable(wave WIN32 wave.c)
|
|
||||||
|
|
||||||
set_target_properties(boing gears heightmap particles simple splitview wave PROPERTIES
|
|
||||||
FOLDER "GLFW3/Examples")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (APPLE)
|
|
||||||
target_link_libraries(Particles "${CMAKE_THREAD_LIBS_INIT}")
|
|
||||||
elseif (UNIX)
|
|
||||||
target_link_libraries(particles "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
set(WINDOWS_BINARIES boing gears heightmap particles simple splitview wave)
|
|
||||||
|
|
||||||
# Tell MSVC to use main instead of WinMain for Windows subsystem executables
|
# Tell MSVC to use main instead of WinMain for Windows subsystem executables
|
||||||
set_target_properties(${WINDOWS_BINARIES} PROPERTIES
|
set_target_properties(${WINDOWS_BINARIES} PROPERTIES
|
||||||
LINK_FLAGS "/ENTRY:mainCRTStartup")
|
LINK_FLAGS "/ENTRY:mainCRTStartup")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
set(BUNDLE_BINARIES Boing Gears Heightmap Particles Simple SplitView Wave)
|
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 "Split View")
|
||||||
|
set_target_properties(wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave")
|
||||||
|
|
||||||
set_target_properties(${BUNDLE_BINARIES} PROPERTIES
|
set_target_properties(${WINDOWS_BINARIES} PROPERTIES
|
||||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}
|
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}
|
||||||
MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION_FULL})
|
MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION_FULL}
|
||||||
|
MACOSX_BUNDLE_INFO_PLIST "${GLFW_SOURCE_DIR}/CMake/MacOSXBundleInfo.plist.in")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
+21
-39
@@ -27,13 +27,19 @@
|
|||||||
* a hidden computer or VCR.
|
* 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 <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#define GLFW_INCLUDE_GLU
|
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include <linmath.h>
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Various declarations and macros
|
* Various declarations and macros
|
||||||
@@ -102,11 +108,6 @@ double dt;
|
|||||||
#define RAND_MAX 4095
|
#define RAND_MAX 4095
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* PI */
|
|
||||||
#ifndef M_PI
|
|
||||||
#define M_PI 3.1415926535897932384626433832795
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Truncate a degree.
|
* Truncate a degree.
|
||||||
@@ -167,28 +168,6 @@ void CrossProduct( vertex_t a, vertex_t b, vertex_t c, vertex_t *n )
|
|||||||
n->z = u1 * v2 - v1 * u2;
|
n->z = u1 * v2 - v1 * u2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* Calculate the angle to be passed to gluPerspective() so that a scene
|
|
||||||
* is visible. This function originates from the OpenGL Red Book.
|
|
||||||
*
|
|
||||||
* Parms : size
|
|
||||||
* The size of the segment when the angle is intersected at "dist"
|
|
||||||
* (ie at the outermost edge of the angle of vision).
|
|
||||||
*
|
|
||||||
* dist
|
|
||||||
* Distance from viewpoint to scene.
|
|
||||||
*****************************************************************************/
|
|
||||||
GLfloat PerspectiveAngle( GLfloat size,
|
|
||||||
GLfloat dist )
|
|
||||||
{
|
|
||||||
GLfloat radTheta, degTheta;
|
|
||||||
|
|
||||||
radTheta = 2.f * (GLfloat) atan2( size / 2.f, dist );
|
|
||||||
degTheta = (180.f * radTheta) / (GLfloat) M_PI;
|
|
||||||
return degTheta;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define BOING_DEBUG 0
|
#define BOING_DEBUG 0
|
||||||
|
|
||||||
@@ -233,22 +212,25 @@ void display(void)
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
void reshape( GLFWwindow* window, int w, int h )
|
void reshape( GLFWwindow* window, int w, int h )
|
||||||
{
|
{
|
||||||
|
mat4x4 projection, view;
|
||||||
|
|
||||||
glViewport( 0, 0, (GLsizei)w, (GLsizei)h );
|
glViewport( 0, 0, (GLsizei)w, (GLsizei)h );
|
||||||
|
|
||||||
glMatrixMode( GL_PROJECTION );
|
glMatrixMode( GL_PROJECTION );
|
||||||
glLoadIdentity();
|
mat4x4_perspective( projection,
|
||||||
|
2.f * (float) atan2( RADIUS, 200.f ),
|
||||||
gluPerspective( PerspectiveAngle( RADIUS * 2, 200 ),
|
(float)w / (float)h,
|
||||||
(GLfloat)w / (GLfloat)h,
|
1.f, VIEW_SCENE_DIST );
|
||||||
1.0,
|
glLoadMatrixf((const GLfloat*) projection);
|
||||||
VIEW_SCENE_DIST );
|
|
||||||
|
|
||||||
glMatrixMode( GL_MODELVIEW );
|
glMatrixMode( GL_MODELVIEW );
|
||||||
glLoadIdentity();
|
{
|
||||||
|
vec3 eye = { 0.f, 0.f, VIEW_SCENE_DIST };
|
||||||
gluLookAt( 0.0, 0.0, VIEW_SCENE_DIST,/* eye */
|
vec3 center = { 0.f, 0.f, 0.f };
|
||||||
0.0, 0.0, 0.0, /* center of vision */
|
vec3 up = { 0.f, -1.f, 0.f };
|
||||||
0.0, -1.0, 0.0 ); /* up vector */
|
mat4x4_look_at( view, eye, center, up );
|
||||||
|
}
|
||||||
|
glLoadMatrixf((const GLfloat*) view);
|
||||||
}
|
}
|
||||||
|
|
||||||
void key_callback( GLFWwindow* window, int key, int scancode, int action, int mods )
|
void key_callback( GLFWwindow* window, int key, int scancode, int action, int mods )
|
||||||
|
|||||||
+6
-24
@@ -21,6 +21,10 @@
|
|||||||
* - Enabled vsync
|
* - Enabled vsync
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
// Make MS math.h define M_PI
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -28,14 +32,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
#ifndef M_PI
|
|
||||||
#define M_PI 3.141592654
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If non-zero, the program exits after that many seconds
|
|
||||||
*/
|
|
||||||
static int autoexit = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
Draw a gear wheel. You'll probably want to call this function when
|
Draw a gear wheel. You'll probably want to call this function when
|
||||||
@@ -264,13 +260,12 @@ void reshape( GLFWwindow* window, int width, int height )
|
|||||||
|
|
||||||
|
|
||||||
/* program & OpenGL initialization */
|
/* program & OpenGL initialization */
|
||||||
static void init(int argc, char *argv[])
|
static void init(void)
|
||||||
{
|
{
|
||||||
static GLfloat pos[4] = {5.f, 5.f, 10.f, 0.f};
|
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 red[4] = {0.8f, 0.1f, 0.f, 1.f};
|
||||||
static GLfloat green[4] = {0.f, 0.8f, 0.2f, 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};
|
static GLfloat blue[4] = {0.2f, 0.2f, 1.f, 1.f};
|
||||||
GLint i;
|
|
||||||
|
|
||||||
glLightfv(GL_LIGHT0, GL_POSITION, pos);
|
glLightfv(GL_LIGHT0, GL_POSITION, pos);
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
@@ -298,19 +293,6 @@ static void init(int argc, char *argv[])
|
|||||||
glEndList();
|
glEndList();
|
||||||
|
|
||||||
glEnable(GL_NORMALIZE);
|
glEnable(GL_NORMALIZE);
|
||||||
|
|
||||||
for ( i=1; i<argc; i++ ) {
|
|
||||||
if (strcmp(argv[i], "-info")==0) {
|
|
||||||
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
|
||||||
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
|
|
||||||
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
|
|
||||||
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
|
|
||||||
}
|
|
||||||
else if ( strcmp(argv[i], "-exit")==0) {
|
|
||||||
autoexit = 30;
|
|
||||||
printf("Auto Exit after %i seconds.\n", autoexit );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -347,7 +329,7 @@ int main(int argc, char *argv[])
|
|||||||
reshape(window, width, height);
|
reshape(window, width, height);
|
||||||
|
|
||||||
// Parse command-line options
|
// Parse command-line options
|
||||||
init(argc, argv);
|
init();
|
||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
while( !glfwWindowShouldClose(window) )
|
while( !glfwWindowShouldClose(window) )
|
||||||
|
|||||||
+15
-10
@@ -24,6 +24,11 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
// Make MS math.h define M_PI
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -32,8 +37,8 @@
|
|||||||
|
|
||||||
#include <tinycthread.h>
|
#include <tinycthread.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <linmath.h>
|
||||||
|
|
||||||
#define GLFW_INCLUDE_GLU
|
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
// Define tokens for GL_EXT_separate_specular_color if not already defined
|
// Define tokens for GL_EXT_separate_specular_color if not already defined
|
||||||
@@ -43,11 +48,6 @@
|
|||||||
#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA
|
#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA
|
||||||
#endif // GL_EXT_separate_specular_color
|
#endif // GL_EXT_separate_specular_color
|
||||||
|
|
||||||
// Some <math.h>'s do not define M_PI
|
|
||||||
#ifndef M_PI
|
|
||||||
#define M_PI 3.141592654
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//========================================================================
|
//========================================================================
|
||||||
// Type definitions
|
// Type definitions
|
||||||
@@ -785,17 +785,22 @@ static void draw_scene(GLFWwindow* window, double t)
|
|||||||
double xpos, ypos, zpos, angle_x, angle_y, angle_z;
|
double xpos, ypos, zpos, angle_x, angle_y, angle_z;
|
||||||
static double t_old = 0.0;
|
static double t_old = 0.0;
|
||||||
float dt;
|
float dt;
|
||||||
|
mat4x4 projection;
|
||||||
|
|
||||||
// Calculate frame-to-frame delta time
|
// Calculate frame-to-frame delta time
|
||||||
dt = (float) (t - t_old);
|
dt = (float) (t - t_old);
|
||||||
t_old = t;
|
t_old = t;
|
||||||
|
|
||||||
|
mat4x4_perspective(projection,
|
||||||
|
65.f * (float) M_PI / 180.f,
|
||||||
|
aspect_ratio,
|
||||||
|
1.0, 60.0);
|
||||||
|
|
||||||
glClearColor(0.1f, 0.1f, 0.1f, 1.f);
|
glClearColor(0.1f, 0.1f, 0.1f, 1.f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadMatrixf((const GLfloat*) projection);
|
||||||
gluPerspective(65.0, aspect_ratio, 1.0, 60.0);
|
|
||||||
|
|
||||||
// Setup camera
|
// Setup camera
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
@@ -986,11 +991,11 @@ int main(int argc, char** argv)
|
|||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
glfwSwapInterval(1);
|
glfwSwapInterval(1);
|
||||||
|
|
||||||
glfwSetWindowSizeCallback(window, resize_callback);
|
glfwSetFramebufferSizeCallback(window, resize_callback);
|
||||||
glfwSetKeyCallback(window, key_callback);
|
glfwSetKeyCallback(window, key_callback);
|
||||||
|
|
||||||
// Set initial aspect ratio
|
// Set initial aspect ratio
|
||||||
glfwGetWindowSize(window, &width, &height);
|
glfwGetFramebufferSize(window, &width, &height);
|
||||||
resize_callback(window, width, height);
|
resize_callback(window, width, height);
|
||||||
|
|
||||||
// Upload particle texture
|
// Upload particle texture
|
||||||
|
|||||||
+72
-29
@@ -10,16 +10,19 @@
|
|||||||
// because I am not a friend of orthogonal projections)
|
// because I am not a friend of orthogonal projections)
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#define GLFW_INCLUDE_GLU
|
#define GLFW_INCLUDE_GLEXT
|
||||||
#include <GLFW/glfw3.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 <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifndef M_PI
|
#include <linmath.h>
|
||||||
#define M_PI 3.14159265358979323846
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//========================================================================
|
//========================================================================
|
||||||
@@ -149,6 +152,7 @@ static void drawGrid(float scale, int steps)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
float x, y;
|
float x, y;
|
||||||
|
mat4x4 view;
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
|
||||||
@@ -157,10 +161,13 @@ static void drawGrid(float scale, int steps)
|
|||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
// Setup modelview matrix (flat XY view)
|
// Setup modelview matrix (flat XY view)
|
||||||
glLoadIdentity();
|
{
|
||||||
gluLookAt(0.0, 0.0, 1.0,
|
vec3 eye = { 0.f, 0.f, 1.f };
|
||||||
0.0, 0.0, 0.0,
|
vec3 center = { 0.f, 0.f, 0.f };
|
||||||
0.0, 1.0, 0.0);
|
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
|
// We don't want to update the Z-buffer
|
||||||
glDepthMask(GL_FALSE);
|
glDepthMask(GL_FALSE);
|
||||||
@@ -209,13 +216,14 @@ static void drawAllViews(void)
|
|||||||
const GLfloat light_diffuse[4] = {1.0f, 1.0f, 1.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_specular[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
const GLfloat light_ambient[4] = {0.2f, 0.2f, 0.3f, 1.0f};
|
const GLfloat light_ambient[4] = {0.2f, 0.2f, 0.3f, 1.0f};
|
||||||
double aspect;
|
float aspect;
|
||||||
|
mat4x4 view, projection;
|
||||||
|
|
||||||
// Calculate aspect of window
|
// Calculate aspect of window
|
||||||
if (height > 0)
|
if (height > 0)
|
||||||
aspect = (double) width / (double) height;
|
aspect = (float) width / (float) height;
|
||||||
else
|
else
|
||||||
aspect = 1.0;
|
aspect = 1.f;
|
||||||
|
|
||||||
// Clear screen
|
// Clear screen
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
@@ -247,10 +255,13 @@ static void drawAllViews(void)
|
|||||||
glViewport(0, height / 2, width / 2, height / 2);
|
glViewport(0, height / 2, width / 2, height / 2);
|
||||||
glScissor(0, height / 2, width / 2, height / 2);
|
glScissor(0, height / 2, width / 2, height / 2);
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
{
|
||||||
gluLookAt(0.0f, 10.0f, 1e-3f, // Eye-position (above)
|
vec3 eye = { 0.f, 10.f, 1e-3f };
|
||||||
0.0f, 0.0f, 0.0f, // View-point
|
vec3 center = { 0.f, 0.f, 0.f };
|
||||||
0.0f, 1.0f, 0.0f); // Up-vector
|
vec3 up = { 0.f, 1.f, 0.f };
|
||||||
|
mat4x4_look_at( view, eye, center, up );
|
||||||
|
}
|
||||||
|
glLoadMatrixf((const GLfloat*) view);
|
||||||
drawGrid(0.5, 12);
|
drawGrid(0.5, 12);
|
||||||
drawScene();
|
drawScene();
|
||||||
|
|
||||||
@@ -258,10 +269,13 @@ static void drawAllViews(void)
|
|||||||
glViewport(0, 0, width / 2, height / 2);
|
glViewport(0, 0, width / 2, height / 2);
|
||||||
glScissor(0, 0, width / 2, height / 2);
|
glScissor(0, 0, width / 2, height / 2);
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
{
|
||||||
gluLookAt(0.0f, 0.0f, 10.0f, // Eye-position (in front of)
|
vec3 eye = { 0.f, 0.f, 10.f };
|
||||||
0.0f, 0.0f, 0.0f, // View-point
|
vec3 center = { 0.f, 0.f, 0.f };
|
||||||
0.0f, 1.0f, 0.0f); // Up-vector
|
vec3 up = { 0.f, 1.f, 0.f };
|
||||||
|
mat4x4_look_at( view, eye, center, up );
|
||||||
|
}
|
||||||
|
glLoadMatrixf((const GLfloat*) view);
|
||||||
drawGrid(0.5, 12);
|
drawGrid(0.5, 12);
|
||||||
drawScene();
|
drawScene();
|
||||||
|
|
||||||
@@ -269,10 +283,13 @@ static void drawAllViews(void)
|
|||||||
glViewport(width / 2, 0, width / 2, height / 2);
|
glViewport(width / 2, 0, width / 2, height / 2);
|
||||||
glScissor(width / 2, 0, width / 2, height / 2);
|
glScissor(width / 2, 0, width / 2, height / 2);
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
{
|
||||||
gluLookAt(10.0f, 0.0f, 0.0f, // Eye-position (to the right)
|
vec3 eye = { 10.f, 0.f, 0.f };
|
||||||
0.0f, 0.0f, 0.0f, // View-point
|
vec3 center = { 0.f, 0.f, 0.f };
|
||||||
0.0f, 1.0f, 0.0f); // Up-vector
|
vec3 up = { 0.f, 1.f, 0.f };
|
||||||
|
mat4x4_look_at( view, eye, center, up );
|
||||||
|
}
|
||||||
|
glLoadMatrixf((const GLfloat*) view);
|
||||||
drawGrid(0.5, 12);
|
drawGrid(0.5, 12);
|
||||||
drawScene();
|
drawScene();
|
||||||
|
|
||||||
@@ -292,17 +309,23 @@ static void drawAllViews(void)
|
|||||||
|
|
||||||
// Setup perspective projection matrix
|
// Setup perspective projection matrix
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
mat4x4_perspective(projection,
|
||||||
gluPerspective(65.0f, aspect, 1.0f, 50.0f);
|
65.f * (float) M_PI / 180.f,
|
||||||
|
aspect,
|
||||||
|
1.f, 50.f);
|
||||||
|
glLoadMatrixf((const GLfloat*) projection);
|
||||||
|
|
||||||
// Upper right view (PERSPECTIVE VIEW)
|
// Upper right view (PERSPECTIVE VIEW)
|
||||||
glViewport(width / 2, height / 2, width / 2, height / 2);
|
glViewport(width / 2, height / 2, width / 2, height / 2);
|
||||||
glScissor(width / 2, height / 2, width / 2, height / 2);
|
glScissor(width / 2, height / 2, width / 2, height / 2);
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
{
|
||||||
gluLookAt(3.0f, 1.5f, 3.0f, // Eye-position
|
vec3 eye = { 3.f, 1.5f, 3.f };
|
||||||
0.0f, 0.0f, 0.0f, // View-point
|
vec3 center = { 0.f, 0.f, 0.f };
|
||||||
0.0f, 1.0f, 0.0f); // Up-vector
|
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
|
// Configure and enable light source 1
|
||||||
glLightfv(GL_LIGHT1, GL_POSITION, light_position);
|
glLightfv(GL_LIGHT1, GL_POSITION, light_position);
|
||||||
@@ -383,6 +406,17 @@ static void windowRefreshFun(GLFWwindow* window)
|
|||||||
|
|
||||||
static void cursorPosFun(GLFWwindow* window, double x, double y)
|
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
|
// Depending on which view was selected, rotate around different axes
|
||||||
switch (active_view)
|
switch (active_view)
|
||||||
{
|
{
|
||||||
@@ -458,6 +492,8 @@ int main(void)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glfwWindowHint(GLFW_SAMPLES, 4);
|
||||||
|
|
||||||
// Open OpenGL window
|
// Open OpenGL window
|
||||||
window = glfwCreateWindow(500, 500, "Split view demo", NULL, NULL);
|
window = glfwCreateWindow(500, 500, "Split view demo", NULL, NULL);
|
||||||
if (!window)
|
if (!window)
|
||||||
@@ -479,6 +515,13 @@ int main(void)
|
|||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
glfwSwapInterval(1);
|
glfwSwapInterval(1);
|
||||||
|
|
||||||
|
if (glfwExtensionSupported("GL_ARB_multisample") ||
|
||||||
|
glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR) >= 2 ||
|
||||||
|
glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR) >= 3)
|
||||||
|
{
|
||||||
|
glEnable(GL_MULTISAMPLE_ARB);
|
||||||
|
}
|
||||||
|
|
||||||
glfwGetFramebufferSize(window, &width, &height);
|
glfwGetFramebufferSize(window, &width, &height);
|
||||||
framebufferSizeFun(window, width, height);
|
framebufferSizeFun(window, width, height);
|
||||||
|
|
||||||
|
|||||||
+12
-6
@@ -8,16 +8,18 @@
|
|||||||
* 2010-10-24: Formatting and cleanup - Camilla Berglund
|
* 2010-10-24: Formatting and cleanup - Camilla Berglund
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
// Make MS math.h define M_PI
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#define GLFW_INCLUDE_GLU
|
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
#ifndef M_PI
|
#include <linmath.h>
|
||||||
#define M_PI 3.1415926535897932384626433832795
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Maximum delta T to allow for differential calculations
|
// Maximum delta T to allow for differential calculations
|
||||||
#define MAX_DELTA_T 0.01
|
#define MAX_DELTA_T 0.01
|
||||||
@@ -362,6 +364,7 @@ void scroll_callback(GLFWwindow* window, double x, double y)
|
|||||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
||||||
{
|
{
|
||||||
float ratio = 1.f;
|
float ratio = 1.f;
|
||||||
|
mat4x4 projection;
|
||||||
|
|
||||||
if (height > 0)
|
if (height > 0)
|
||||||
ratio = (float) width / (float) height;
|
ratio = (float) width / (float) height;
|
||||||
@@ -371,8 +374,11 @@ void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
|||||||
|
|
||||||
// Change to the projection matrix and set our viewing volume
|
// Change to the projection matrix and set our viewing volume
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
mat4x4_perspective(projection,
|
||||||
gluPerspective(60.0, ratio, 1.0, 1024.0);
|
60.f * (float) M_PI / 180.f,
|
||||||
|
ratio,
|
||||||
|
1.f, 1024.f);
|
||||||
|
glLoadMatrixf((const GLfloat*) projection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+46
-28
@@ -211,7 +211,7 @@ extern "C" {
|
|||||||
* API changes.
|
* API changes.
|
||||||
* @ingroup init
|
* @ingroup init
|
||||||
*/
|
*/
|
||||||
#define GLFW_VERSION_REVISION 1
|
#define GLFW_VERSION_REVISION 2
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
||||||
/*! @name Key and button actions
|
/*! @name Key and button actions
|
||||||
@@ -531,7 +531,7 @@ extern "C" {
|
|||||||
*
|
*
|
||||||
* @par
|
* @par
|
||||||
* Some pre-installed Windows graphics drivers do not support OpenGL. AMD only
|
* Some pre-installed Windows graphics drivers do not support OpenGL. AMD only
|
||||||
* supports OpenGL ES via EGL, while Nvidia and Intel only supports it via
|
* supports OpenGL ES via EGL, while Nvidia and Intel only support it via
|
||||||
* a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa
|
* a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa
|
||||||
* EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary
|
* EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary
|
||||||
* driver.
|
* driver.
|
||||||
@@ -1067,12 +1067,6 @@ typedef struct GLFWimage
|
|||||||
* bundle, if present. This can be disabled with a
|
* bundle, if present. This can be disabled with a
|
||||||
* [compile-time option](@ref compile_options_osx).
|
* [compile-time option](@ref compile_options_osx).
|
||||||
*
|
*
|
||||||
* @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to
|
|
||||||
* `"C"` then the environment's locale will be applied to that category. This
|
|
||||||
* is done because character input will not function when `LC_CTYPE` is set to
|
|
||||||
* `"C"`. If another locale was set before this function was called, it will
|
|
||||||
* be left untouched.
|
|
||||||
*
|
|
||||||
* @par Thread Safety
|
* @par Thread Safety
|
||||||
* This function may only be called from the main thread.
|
* This function may only be called from the main thread.
|
||||||
*
|
*
|
||||||
@@ -1212,12 +1206,13 @@ GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun);
|
|||||||
/*! @brief Returns the currently connected monitors.
|
/*! @brief Returns the currently connected monitors.
|
||||||
*
|
*
|
||||||
* This function returns an array of handles for all currently connected
|
* This function returns an array of handles for all currently connected
|
||||||
* monitors.
|
* monitors. The primary monitor is always first in the returned array. If no
|
||||||
|
* monitors were found, this function returns `NULL`.
|
||||||
*
|
*
|
||||||
* @param[out] count Where to store the number of monitors in the returned
|
* @param[out] count Where to store the number of monitors in the returned
|
||||||
* array. This is set to zero if an error occurred.
|
* array. This is set to zero if an error occurred.
|
||||||
* @return An array of monitor handles, or `NULL` if an
|
* @return An array of monitor handles, or `NULL` if no monitors were found or
|
||||||
* [error](@ref error_handling) occurred.
|
* if an [error](@ref error_handling) occurred.
|
||||||
*
|
*
|
||||||
* @par Pointer Lifetime
|
* @par Pointer Lifetime
|
||||||
* The returned array is allocated and freed by GLFW. You should not free it
|
* The returned array is allocated and freed by GLFW. You should not free it
|
||||||
@@ -1240,14 +1235,17 @@ GLFWAPI GLFWmonitor** glfwGetMonitors(int* count);
|
|||||||
/*! @brief Returns the primary monitor.
|
/*! @brief Returns the primary monitor.
|
||||||
*
|
*
|
||||||
* This function returns the primary monitor. This is usually the monitor
|
* This function returns the primary monitor. This is usually the monitor
|
||||||
* where elements like the Windows task bar or the OS X menu bar is located.
|
* where elements like the task bar or global menu bar are located.
|
||||||
*
|
*
|
||||||
* @return The primary monitor, or `NULL` if an [error](@ref error_handling)
|
* @return The primary monitor, or `NULL` if no monitors were found or if an
|
||||||
* occurred.
|
* [error](@ref error_handling) occurred.
|
||||||
*
|
*
|
||||||
* @par Thread Safety
|
* @par Thread Safety
|
||||||
* This function may only be called from the main thread.
|
* This function may only be called from the main thread.
|
||||||
*
|
*
|
||||||
|
* @remarks The primary monitor is always first in the array returned by @ref
|
||||||
|
* glfwGetMonitors.
|
||||||
|
*
|
||||||
* @sa @ref monitor_monitors
|
* @sa @ref monitor_monitors
|
||||||
* @sa glfwGetMonitors
|
* @sa glfwGetMonitors
|
||||||
*
|
*
|
||||||
@@ -1551,8 +1549,8 @@ GLFWAPI void glfwWindowHint(int target, int hint);
|
|||||||
* requested, as not all parameters and hints are
|
* requested, as not all parameters and hints are
|
||||||
* [hard constraints](@ref window_hints_hard). This includes the size of the
|
* [hard constraints](@ref window_hints_hard). This includes the size of the
|
||||||
* window, especially for full screen windows. To query the actual attributes
|
* window, especially for full screen windows. To query the actual attributes
|
||||||
* of the created window, framebuffer and context, use queries like @ref
|
* of the created window, framebuffer and context, see @ref
|
||||||
* glfwGetWindowAttrib and @ref glfwGetWindowSize.
|
* glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize.
|
||||||
*
|
*
|
||||||
* To create a full screen window, you need to specify the monitor the window
|
* To create a full screen window, you need to specify the monitor the window
|
||||||
* will cover. If no monitor is specified, windowed mode will be used. Unless
|
* will cover. If no monitor is specified, windowed mode will be used. Unless
|
||||||
@@ -1622,13 +1620,20 @@ GLFWAPI void glfwWindowHint(int target, int hint);
|
|||||||
* `NSHighResolutionCapable` key is enabled in the application bundle's
|
* `NSHighResolutionCapable` key is enabled in the application bundle's
|
||||||
* `Info.plist`. For more information, see
|
* `Info.plist`. For more information, see
|
||||||
* [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html)
|
* [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html)
|
||||||
* in the Mac Developer Library.
|
* in the Mac Developer Library. The GLFW test and example programs use
|
||||||
|
* a custom `Info.plist` template for this, which can be found as
|
||||||
|
* `CMake/MacOSXBundleInfo.plist.in` in the source tree.
|
||||||
*
|
*
|
||||||
* @remarks __X11:__ There is no mechanism for setting the window icon yet.
|
* @remarks __X11:__ There is no mechanism for setting the window icon yet.
|
||||||
*
|
*
|
||||||
* @remarks __X11:__ Some window managers will not respect the placement of
|
* @remarks __X11:__ Some window managers will not respect the placement of
|
||||||
* initially hidden windows.
|
* initially hidden windows.
|
||||||
*
|
*
|
||||||
|
* @remarks __X11:__ Due to the asynchronous nature of X11, it may take
|
||||||
|
* a moment for a window to reach its requested state. This means you may not
|
||||||
|
* be able to query the final size, position or other attributes directly after
|
||||||
|
* window creation.
|
||||||
|
*
|
||||||
* @par Reentrancy
|
* @par Reentrancy
|
||||||
* This function may not be called from a callback.
|
* This function may not be called from a callback.
|
||||||
*
|
*
|
||||||
@@ -1718,6 +1723,9 @@ GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value);
|
|||||||
* @param[in] window The window whose title to change.
|
* @param[in] window The window whose title to change.
|
||||||
* @param[in] title The UTF-8 encoded window title.
|
* @param[in] title The UTF-8 encoded window title.
|
||||||
*
|
*
|
||||||
|
* @remarks __OS X:__ The window title will not be updated until the next time
|
||||||
|
* you process events.
|
||||||
|
*
|
||||||
* @par Thread Safety
|
* @par Thread Safety
|
||||||
* This function may only be called from the main thread.
|
* This function may only be called from the main thread.
|
||||||
*
|
*
|
||||||
@@ -2035,6 +2043,14 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
|
|||||||
* @return The value of the attribute, or zero if an
|
* @return The value of the attribute, or zero if an
|
||||||
* [error](@ref error_handling) occurred.
|
* [error](@ref error_handling) occurred.
|
||||||
*
|
*
|
||||||
|
* @remarks Framebuffer related hints are not window attributes. See @ref
|
||||||
|
* window_attribs_fb for more information.
|
||||||
|
*
|
||||||
|
* @remarks Zero is a valid value for many window and context related
|
||||||
|
* attributes so you cannot use a return value of zero as an indication of
|
||||||
|
* errors. However, this function should not fail as long as it is passed
|
||||||
|
* valid arguments and the library has been [initialized](@ref intro_init).
|
||||||
|
*
|
||||||
* @par Thread Safety
|
* @par Thread Safety
|
||||||
* This function may only be called from the main thread.
|
* This function may only be called from the main thread.
|
||||||
*
|
*
|
||||||
@@ -2561,9 +2577,9 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
|
|||||||
* @param[in] ypos The desired y-coordinate, relative to the top edge of the
|
* @param[in] ypos The desired y-coordinate, relative to the top edge of the
|
||||||
* client area.
|
* client area.
|
||||||
*
|
*
|
||||||
* @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it
|
* @remarks __X11:__ Due to the asynchronous nature of X11, it may take
|
||||||
* may take a moment for the window focus event to arrive. This means you will
|
* a moment for the window focus event to arrive. This means you may not be
|
||||||
* not be able to set the cursor position directly after window creation.
|
* able to set the cursor position directly after window creation.
|
||||||
*
|
*
|
||||||
* @par Thread Safety
|
* @par Thread Safety
|
||||||
* This function may only be called from the main thread.
|
* This function may only be called from the main thread.
|
||||||
@@ -2583,9 +2599,9 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos);
|
|||||||
* glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor.
|
* glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor.
|
||||||
* Any remaining cursors are destroyed by @ref glfwTerminate.
|
* Any remaining cursors are destroyed by @ref glfwTerminate.
|
||||||
*
|
*
|
||||||
* The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They
|
* The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight
|
||||||
* are arranged canonically as packed sequential rows, starting from the
|
* bits per channel. They are arranged canonically as packed sequential rows,
|
||||||
* top-left corner.
|
* starting from the top-left corner.
|
||||||
*
|
*
|
||||||
* The cursor hotspot is specified in pixels, relative to the upper-left corner
|
* The cursor hotspot is specified in pixels, relative to the upper-left corner
|
||||||
* of the cursor image. Like all other coordinate systems in GLFW, the X-axis
|
* of the cursor image. Like all other coordinate systems in GLFW, the X-axis
|
||||||
@@ -3061,7 +3077,9 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
|
|||||||
/*! @brief Returns the contents of the clipboard as a string.
|
/*! @brief Returns the contents of the clipboard as a string.
|
||||||
*
|
*
|
||||||
* This function returns the contents of the system clipboard, if it contains
|
* This function returns the contents of the system clipboard, if it contains
|
||||||
* or is convertible to a UTF-8 encoded string.
|
* or is convertible to a UTF-8 encoded string. If the clipboard is empty or
|
||||||
|
* if its contents cannot be converted, `NULL` is returned and a @ref
|
||||||
|
* GLFW_FORMAT_UNAVAILABLE error is generated.
|
||||||
*
|
*
|
||||||
* @param[in] window The window that will request the clipboard contents.
|
* @param[in] window The window that will request the clipboard contents.
|
||||||
* @return The contents of the clipboard as a UTF-8 encoded string, or `NULL`
|
* @return The contents of the clipboard as a UTF-8 encoded string, or `NULL`
|
||||||
@@ -3286,15 +3304,15 @@ GLFWAPI int glfwExtensionSupported(const char* extension);
|
|||||||
* without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
|
* without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
|
||||||
*
|
*
|
||||||
* @param[in] procname The ASCII encoded name of the function.
|
* @param[in] procname The ASCII encoded name of the function.
|
||||||
* @return The address of the function, or `NULL` if the function is
|
* @return The address of the function, or `NULL` if an [error](@ref
|
||||||
* unavailable or an [error](@ref error_handling) occurred.
|
* error_handling) occurred.
|
||||||
*
|
*
|
||||||
* @remarks The addresses of a given function is not guaranteed to be the same
|
* @remarks The address of a given function is not guaranteed to be the same
|
||||||
* between contexts.
|
* between contexts.
|
||||||
*
|
*
|
||||||
* @remarks This function may return a non-`NULL` address despite the
|
* @remarks This function may return a non-`NULL` address despite the
|
||||||
* associated version or extension not being available. Always check the
|
* associated version or extension not being available. Always check the
|
||||||
* context version or extension string presence first.
|
* context version or extension string first.
|
||||||
*
|
*
|
||||||
* @par Pointer Lifetime
|
* @par Pointer Lifetime
|
||||||
* The returned function pointer is valid until the context is destroyed or the
|
* The returned function pointer is valid until the context is destroyed or the
|
||||||
|
|||||||
+1
-3
@@ -249,7 +249,7 @@ void _glfwPlatformTerminate(void)
|
|||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
{
|
{
|
||||||
const char* version = _GLFW_VERSION_NUMBER " Cocoa"
|
return _GLFW_VERSION_NUMBER " Cocoa"
|
||||||
#if defined(_GLFW_NSGL)
|
#if defined(_GLFW_NSGL)
|
||||||
" NSGL"
|
" NSGL"
|
||||||
#endif
|
#endif
|
||||||
@@ -266,7 +266,5 @@ const char* _glfwPlatformGetVersionString(void)
|
|||||||
" dynamic"
|
" dynamic"
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
|
||||||
return version;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+22
-44
@@ -252,50 +252,29 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
|||||||
*count = 0;
|
*count = 0;
|
||||||
|
|
||||||
CGGetOnlineDisplayList(0, NULL, &displayCount);
|
CGGetOnlineDisplayList(0, NULL, &displayCount);
|
||||||
|
|
||||||
displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
||||||
monitors = calloc(displayCount, sizeof(_GLFWmonitor*));
|
monitors = calloc(displayCount, sizeof(_GLFWmonitor*));
|
||||||
|
|
||||||
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
||||||
|
|
||||||
NSArray* screens = [NSScreen screens];
|
|
||||||
|
|
||||||
for (i = 0; i < displayCount; i++)
|
for (i = 0; i < displayCount; i++)
|
||||||
{
|
{
|
||||||
int j;
|
_GLFWmonitor* monitor;
|
||||||
|
|
||||||
CGDirectDisplayID screenDisplayID = CGDisplayMirrorsDisplay(displays[i]);
|
if (CGDisplayIsAsleep(displays[i]))
|
||||||
if (screenDisplayID == kCGNullDirectDisplay)
|
continue;
|
||||||
screenDisplayID = displays[i];
|
|
||||||
|
|
||||||
const CGSize size = CGDisplayScreenSize(displays[i]);
|
const CGSize size = CGDisplayScreenSize(displays[i]);
|
||||||
char* name = getDisplayName(displays[i]);
|
char* name = getDisplayName(displays[i]);
|
||||||
|
|
||||||
monitors[found] = _glfwAllocMonitor(name, size.width, size.height);
|
monitor = _glfwAllocMonitor(name, size.width, size.height);
|
||||||
monitors[found]->ns.displayID = displays[i];
|
monitor->ns.displayID = displays[i];
|
||||||
|
monitor->ns.unitNumber = CGDisplayUnitNumber(displays[i]);
|
||||||
|
|
||||||
free(name);
|
free(name);
|
||||||
|
|
||||||
for (j = 0; j < [screens count]; j++)
|
|
||||||
{
|
|
||||||
NSScreen* screen = [screens objectAtIndex:j];
|
|
||||||
NSDictionary* dictionary = [screen deviceDescription];
|
|
||||||
NSNumber* number = [dictionary objectForKey:@"NSScreenNumber"];
|
|
||||||
|
|
||||||
if ([number unsignedIntegerValue] == screenDisplayID)
|
|
||||||
{
|
|
||||||
monitors[found]->ns.screen = screen;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monitors[found]->ns.screen)
|
|
||||||
found++;
|
found++;
|
||||||
else
|
monitors[found - 1] = monitor;
|
||||||
{
|
|
||||||
_glfwFreeMonitor(monitors[found]);
|
|
||||||
monitors[found] = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(displays);
|
free(displays);
|
||||||
@@ -306,7 +285,9 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
|||||||
|
|
||||||
GLboolean _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
|
GLboolean _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
|
||||||
{
|
{
|
||||||
return first->ns.displayID == second->ns.displayID;
|
// HACK: Compare unit numbers instead of display IDs to work around display
|
||||||
|
// replacement on machines with automatic graphics switching
|
||||||
|
return first->ns.unitNumber == second->ns.unitNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||||
@@ -319,22 +300,22 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
|||||||
*ypos = (int) bounds.origin.y;
|
*ypos = (int) bounds.origin.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||||
{
|
{
|
||||||
CFArrayRef modes;
|
CFArrayRef modes;
|
||||||
CFIndex count, i, j;
|
CFIndex found, i, j;
|
||||||
GLFWvidmode* result;
|
GLFWvidmode* result;
|
||||||
CVDisplayLinkRef link;
|
CVDisplayLinkRef link;
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
|
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
|
||||||
|
|
||||||
modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
|
modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
|
||||||
count = CFArrayGetCount(modes);
|
found = CFArrayGetCount(modes);
|
||||||
|
result = calloc(found, sizeof(GLFWvidmode));
|
||||||
|
|
||||||
result = calloc(count, sizeof(GLFWvidmode));
|
for (i = 0; i < found; i++)
|
||||||
*found = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
|
CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
|
||||||
if (!modeIsGood(dm))
|
if (!modeIsGood(dm))
|
||||||
@@ -342,24 +323,21 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
|||||||
|
|
||||||
const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
|
const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
|
||||||
|
|
||||||
for (j = 0; j < *found; j++)
|
for (j = 0; j < *count; j++)
|
||||||
{
|
{
|
||||||
if (_glfwCompareVideoModes(result + j, &mode) == 0)
|
if (_glfwCompareVideoModes(result + j, &mode) == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < *found)
|
// Skip duplicate modes
|
||||||
{
|
if (i < *count)
|
||||||
// This is a duplicate, so skip it
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
result[*found] = mode;
|
(*count)++;
|
||||||
(*found)++;
|
result[*count - 1] = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFRelease(modes);
|
CFRelease(modes);
|
||||||
|
|
||||||
CVDisplayLinkRelease(link);
|
CVDisplayLinkRelease(link);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,9 +24,8 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _cocoa_platform_h_
|
#ifndef _glfw3_cocoa_platform_h_
|
||||||
#define _cocoa_platform_h_
|
#define _glfw3_cocoa_platform_h_
|
||||||
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -38,15 +37,14 @@ typedef void* id;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "posix_tls.h"
|
#include "posix_tls.h"
|
||||||
|
#include "iokit_joystick.h"
|
||||||
|
|
||||||
#if defined(_GLFW_NSGL)
|
#if defined(_GLFW_NSGL)
|
||||||
#include "nsgl_context.h"
|
#include "nsgl_context.h"
|
||||||
#else
|
#else
|
||||||
#error "No supported context creation API selected"
|
#error "The Cocoa backend depends on NSGL platform support"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "iokit_joystick.h"
|
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS ns
|
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS ns
|
||||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns
|
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns
|
||||||
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeNS ns_time
|
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeNS ns_time
|
||||||
@@ -92,7 +90,7 @@ typedef struct _GLFWmonitorNS
|
|||||||
{
|
{
|
||||||
CGDirectDisplayID displayID;
|
CGDirectDisplayID displayID;
|
||||||
CGDisplayModeRef previousMode;
|
CGDisplayModeRef previousMode;
|
||||||
id screen;
|
uint32_t unitNumber;
|
||||||
|
|
||||||
} _GLFWmonitorNS;
|
} _GLFWmonitorNS;
|
||||||
|
|
||||||
@@ -121,4 +119,4 @@ void _glfwInitTimer(void);
|
|||||||
GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||||
void _glfwRestoreVideoMode(_GLFWmonitor* monitor);
|
void _glfwRestoreVideoMode(_GLFWmonitor* monitor);
|
||||||
|
|
||||||
#endif // _cocoa_platform_h_
|
#endif // _glfw3_cocoa_platform_h_
|
||||||
|
|||||||
+96
-61
@@ -83,13 +83,16 @@ static void updateModeCursor(_GLFWwindow* window)
|
|||||||
//
|
//
|
||||||
static GLboolean enterFullscreenMode(_GLFWwindow* window)
|
static GLboolean enterFullscreenMode(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
|
GLFWvidmode mode;
|
||||||
GLboolean status;
|
GLboolean status;
|
||||||
|
int xpos, ypos;
|
||||||
|
|
||||||
status = _glfwSetVideoMode(window->monitor, &window->videoMode);
|
status = _glfwSetVideoMode(window->monitor, &window->videoMode);
|
||||||
|
|
||||||
// NOTE: The window is resized despite mode setting failure to make
|
_glfwPlatformGetVideoMode(window->monitor, &mode);
|
||||||
// glfwSetWindowSize more robust
|
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
|
||||||
[window->ns.object setFrame:[window->monitor->ns.screen frame]
|
|
||||||
|
[window->ns.object setFrame:NSMakeRect(xpos, ypos, mode.width, mode.height)
|
||||||
display:YES];
|
display:YES];
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -123,6 +126,34 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
|
|||||||
return contentRect;
|
return contentRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Translates OS X key modifiers into GLFW ones
|
||||||
|
//
|
||||||
|
static int translateFlags(NSUInteger flags)
|
||||||
|
{
|
||||||
|
int mods = 0;
|
||||||
|
|
||||||
|
if (flags & NSShiftKeyMask)
|
||||||
|
mods |= GLFW_MOD_SHIFT;
|
||||||
|
if (flags & NSControlKeyMask)
|
||||||
|
mods |= GLFW_MOD_CONTROL;
|
||||||
|
if (flags & NSAlternateKeyMask)
|
||||||
|
mods |= GLFW_MOD_ALT;
|
||||||
|
if (flags & NSCommandKeyMask)
|
||||||
|
mods |= GLFW_MOD_SUPER;
|
||||||
|
|
||||||
|
return mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Translates a OS X keycode to a GLFW keycode
|
||||||
|
//
|
||||||
|
static int translateKey(unsigned int key)
|
||||||
|
{
|
||||||
|
if (key >= sizeof(_glfw.ns.publicKeys) / sizeof(_glfw.ns.publicKeys[0]))
|
||||||
|
return GLFW_KEY_UNKNOWN;
|
||||||
|
|
||||||
|
return _glfw.ns.publicKeys[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Delegate for window related notifications
|
// Delegate for window related notifications
|
||||||
@@ -156,7 +187,9 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
|
|||||||
|
|
||||||
- (void)windowDidResize:(NSNotification *)notification
|
- (void)windowDidResize:(NSNotification *)notification
|
||||||
{
|
{
|
||||||
if (_glfw.focusedWindow == window &&
|
[window->nsgl.context update];
|
||||||
|
|
||||||
|
if (_glfw.cursorWindow == window &&
|
||||||
window->cursorMode == GLFW_CURSOR_DISABLED)
|
window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
{
|
{
|
||||||
centerCursor(window);
|
centerCursor(window);
|
||||||
@@ -167,12 +200,13 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
|
|||||||
|
|
||||||
_glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
|
_glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
|
||||||
_glfwInputWindowSize(window, contentRect.size.width, contentRect.size.height);
|
_glfwInputWindowSize(window, contentRect.size.width, contentRect.size.height);
|
||||||
_glfwInputWindowDamage(window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)windowDidMove:(NSNotification *)notification
|
- (void)windowDidMove:(NSNotification *)notification
|
||||||
{
|
{
|
||||||
if (_glfw.focusedWindow == window &&
|
[window->nsgl.context update];
|
||||||
|
|
||||||
|
if (_glfw.cursorWindow == window &&
|
||||||
window->cursorMode == GLFW_CURSOR_DISABLED)
|
window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
{
|
{
|
||||||
centerCursor(window);
|
centerCursor(window);
|
||||||
@@ -185,20 +219,23 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
|
|||||||
|
|
||||||
- (void)windowDidMiniaturize:(NSNotification *)notification
|
- (void)windowDidMiniaturize:(NSNotification *)notification
|
||||||
{
|
{
|
||||||
|
if (window->monitor)
|
||||||
|
leaveFullscreenMode(window);
|
||||||
|
|
||||||
_glfwInputWindowIconify(window, GL_TRUE);
|
_glfwInputWindowIconify(window, GL_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)windowDidDeminiaturize:(NSNotification *)notification
|
- (void)windowDidDeminiaturize:(NSNotification *)notification
|
||||||
{
|
{
|
||||||
|
if (window->monitor)
|
||||||
|
enterFullscreenMode(window);
|
||||||
|
|
||||||
_glfwInputWindowIconify(window, GL_FALSE);
|
_glfwInputWindowIconify(window, GL_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)windowDidBecomeKey:(NSNotification *)notification
|
- (void)windowDidBecomeKey:(NSNotification *)notification
|
||||||
{
|
{
|
||||||
if (window->monitor)
|
if (_glfw.cursorWindow == window &&
|
||||||
enterFullscreenMode(window);
|
|
||||||
|
|
||||||
if (_glfw.focusedWindow == window &&
|
|
||||||
window->cursorMode == GLFW_CURSOR_DISABLED)
|
window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
{
|
{
|
||||||
centerCursor(window);
|
centerCursor(window);
|
||||||
@@ -210,8 +247,8 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
|
|||||||
|
|
||||||
- (void)windowDidResignKey:(NSNotification *)notification
|
- (void)windowDidResignKey:(NSNotification *)notification
|
||||||
{
|
{
|
||||||
if (window->monitor)
|
if (window->monitor && window->autoIconify)
|
||||||
leaveFullscreenMode(window);
|
_glfwPlatformIconifyWindow(window);
|
||||||
|
|
||||||
_glfwInputWindowFocus(window, GL_FALSE);
|
_glfwInputWindowFocus(window, GL_FALSE);
|
||||||
}
|
}
|
||||||
@@ -250,42 +287,22 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
|
|||||||
_glfwPlatformPostEmptyEvent();
|
_glfwPlatformPostEmptyEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)applicationDidHide:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < _glfw.monitorCount; i++)
|
||||||
|
_glfwRestoreVideoMode(_glfw.monitors[i]);
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
// Translates OS X key modifiers into GLFW ones
|
|
||||||
//
|
|
||||||
static int translateFlags(NSUInteger flags)
|
|
||||||
{
|
|
||||||
int mods = 0;
|
|
||||||
|
|
||||||
if (flags & NSShiftKeyMask)
|
|
||||||
mods |= GLFW_MOD_SHIFT;
|
|
||||||
if (flags & NSControlKeyMask)
|
|
||||||
mods |= GLFW_MOD_CONTROL;
|
|
||||||
if (flags & NSAlternateKeyMask)
|
|
||||||
mods |= GLFW_MOD_ALT;
|
|
||||||
if (flags & NSCommandKeyMask)
|
|
||||||
mods |= GLFW_MOD_SUPER;
|
|
||||||
|
|
||||||
return mods;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Translates a OS X keycode to a GLFW keycode
|
|
||||||
//
|
|
||||||
static int translateKey(unsigned int key)
|
|
||||||
{
|
|
||||||
if (key >= sizeof(_glfw.ns.publicKeys) / sizeof(_glfw.ns.publicKeys[0]))
|
|
||||||
return GLFW_KEY_UNKNOWN;
|
|
||||||
|
|
||||||
return _glfw.ns.publicKeys[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Content view class for the GLFW window
|
// Content view class for the GLFW window
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
|
|
||||||
@interface GLFWContentView : NSOpenGLView
|
@interface GLFWContentView : NSView
|
||||||
{
|
{
|
||||||
_GLFWwindow* window;
|
_GLFWwindow* window;
|
||||||
NSTrackingArea* trackingArea;
|
NSTrackingArea* trackingArea;
|
||||||
@@ -313,8 +330,7 @@ static int translateKey(unsigned int key)
|
|||||||
|
|
||||||
- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow
|
- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:NSMakeRect(0, 0, 1, 1)
|
self = [super init];
|
||||||
pixelFormat:nil];
|
|
||||||
if (self != nil)
|
if (self != nil)
|
||||||
{
|
{
|
||||||
window = initWindow;
|
window = initWindow;
|
||||||
@@ -453,6 +469,10 @@ static int translateKey(unsigned int key)
|
|||||||
const NSRect fbRect = convertRectToBacking(window, contentRect);
|
const NSRect fbRect = convertRectToBacking(window, contentRect);
|
||||||
|
|
||||||
_glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
|
_glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)drawRect:(NSRect)rect
|
||||||
|
{
|
||||||
_glfwInputWindowDamage(window);
|
_glfwInputWindowDamage(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -719,6 +739,7 @@ static void createMenuBar(void)
|
|||||||
[[appMenu addItemWithTitle:@"Services"
|
[[appMenu addItemWithTitle:@"Services"
|
||||||
action:NULL
|
action:NULL
|
||||||
keyEquivalent:@""] setSubmenu:servicesMenu];
|
keyEquivalent:@""] setSubmenu:servicesMenu];
|
||||||
|
[servicesMenu release];
|
||||||
[appMenu addItem:[NSMenuItem separatorItem]];
|
[appMenu addItem:[NSMenuItem separatorItem]];
|
||||||
[appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName]
|
[appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName]
|
||||||
action:@selector(hide:)
|
action:@selector(hide:)
|
||||||
@@ -737,6 +758,7 @@ static void createMenuBar(void)
|
|||||||
|
|
||||||
NSMenuItem* windowMenuItem =
|
NSMenuItem* windowMenuItem =
|
||||||
[bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
|
[bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
|
||||||
|
[bar release];
|
||||||
NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
|
NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
|
||||||
[NSApp setWindowsMenu:windowMenu];
|
[NSApp setWindowsMenu:windowMenu];
|
||||||
[windowMenuItem setSubmenu:windowMenu];
|
[windowMenuItem setSubmenu:windowMenu];
|
||||||
@@ -838,7 +860,15 @@ static GLboolean createWindow(_GLFWwindow* window,
|
|||||||
NSRect contentRect;
|
NSRect contentRect;
|
||||||
|
|
||||||
if (wndconfig->monitor)
|
if (wndconfig->monitor)
|
||||||
contentRect = [wndconfig->monitor->ns.screen frame];
|
{
|
||||||
|
GLFWvidmode mode;
|
||||||
|
int xpos, ypos;
|
||||||
|
|
||||||
|
_glfwPlatformGetVideoMode(window->monitor, &mode);
|
||||||
|
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
|
||||||
|
|
||||||
|
contentRect = NSMakeRect(xpos, ypos, mode.width, mode.height);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height);
|
contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height);
|
||||||
|
|
||||||
@@ -865,7 +895,6 @@ static GLboolean createWindow(_GLFWwindow* window,
|
|||||||
if (wndconfig->monitor)
|
if (wndconfig->monitor)
|
||||||
{
|
{
|
||||||
[window->ns.object setLevel:NSMainMenuWindowLevel + 1];
|
[window->ns.object setLevel:NSMainMenuWindowLevel + 1];
|
||||||
[window->ns.object setHidesOnDeactivate:YES];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -875,9 +904,19 @@ static GLboolean createWindow(_GLFWwindow* window,
|
|||||||
[window->ns.object setLevel:NSFloatingWindowLevel];
|
[window->ns.object setLevel:NSFloatingWindowLevel];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
|
||||||
|
|
||||||
|
#if defined(_GLFW_USE_RETINA)
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
|
||||||
|
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
|
||||||
|
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
|
||||||
|
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
||||||
|
#endif /*_GLFW_USE_RETINA*/
|
||||||
|
|
||||||
[window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]];
|
[window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]];
|
||||||
[window->ns.object setDelegate:window->ns.delegate];
|
[window->ns.object setDelegate:window->ns.delegate];
|
||||||
[window->ns.object setAcceptsMouseMovedEvents:YES];
|
[window->ns.object setAcceptsMouseMovedEvents:YES];
|
||||||
|
[window->ns.object setContentView:window->ns.view];
|
||||||
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
|
||||||
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
|
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
|
||||||
@@ -906,22 +945,6 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
if (!_glfwCreateContext(window, ctxconfig, fbconfig))
|
if (!_glfwCreateContext(window, ctxconfig, fbconfig))
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
|
|
||||||
window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
|
|
||||||
|
|
||||||
#if defined(_GLFW_USE_RETINA)
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
|
|
||||||
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
|
|
||||||
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
|
|
||||||
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
|
||||||
#endif /*_GLFW_USE_RETINA*/
|
|
||||||
|
|
||||||
[window->ns.object setContentView:window->ns.view];
|
|
||||||
// NOTE: If you set the pixel format before the context it creates another
|
|
||||||
// context, only to have it destroyed by the next line
|
|
||||||
// We cannot use the view to create the context because that interface
|
|
||||||
// does not support context resource sharing
|
|
||||||
[window->ns.view setOpenGLContext:window->nsgl.context];
|
|
||||||
[window->ns.view setPixelFormat:window->nsgl.pixelFormat];
|
|
||||||
[window->nsgl.context setView:window->ns.view];
|
[window->nsgl.context setView:window->ns.view];
|
||||||
|
|
||||||
if (wndconfig->monitor)
|
if (wndconfig->monitor)
|
||||||
@@ -1148,8 +1171,14 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
|
||||||
|
const NSRect localRect = NSMakeRect(x, contentRect.size.height - y - 1, 0, 0);
|
||||||
|
const NSRect globalRect = [window->ns.object convertRectToScreen:localRect];
|
||||||
|
const NSPoint globalPoint = globalRect.origin;
|
||||||
|
#else
|
||||||
const NSPoint localPoint = NSMakePoint(x, contentRect.size.height - y - 1);
|
const NSPoint localPoint = NSMakePoint(x, contentRect.size.height - y - 1);
|
||||||
const NSPoint globalPoint = [window->ns.object convertBaseToScreen:localPoint];
|
const NSPoint globalPoint = [window->ns.object convertBaseToScreen:localPoint];
|
||||||
|
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
||||||
|
|
||||||
CGWarpMouseCursorPosition(CGPointMake(globalPoint.x,
|
CGWarpMouseCursorPosition(CGPointMake(globalPoint.x,
|
||||||
transformY(globalPoint.y)));
|
transformY(globalPoint.y)));
|
||||||
@@ -1173,6 +1202,9 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
|||||||
NSImage* native;
|
NSImage* native;
|
||||||
NSBitmapImageRep* rep;
|
NSBitmapImageRep* rep;
|
||||||
|
|
||||||
|
if (!initializeAppKit())
|
||||||
|
return GL_FALSE;
|
||||||
|
|
||||||
rep = [[NSBitmapImageRep alloc]
|
rep = [[NSBitmapImageRep alloc]
|
||||||
initWithBitmapDataPlanes:NULL
|
initWithBitmapDataPlanes:NULL
|
||||||
pixelsWide:image->width
|
pixelsWide:image->width
|
||||||
@@ -1208,6 +1240,9 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
|||||||
|
|
||||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||||
{
|
{
|
||||||
|
if (!initializeAppKit())
|
||||||
|
return GL_FALSE;
|
||||||
|
|
||||||
cursor->ns.object = getStandardCursor(shape);
|
cursor->ns.object = getStandardCursor(shape);
|
||||||
if (!cursor->ns.object)
|
if (!cursor->ns.object)
|
||||||
{
|
{
|
||||||
|
|||||||
+21
-22
@@ -38,6 +38,7 @@
|
|||||||
static GLboolean parseVersionString(int* api, int* major, int* minor, int* rev)
|
static GLboolean parseVersionString(int* api, int* major, int* minor, int* rev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
_GLFWwindow* window;
|
||||||
const char* version;
|
const char* version;
|
||||||
const char* prefixes[] =
|
const char* prefixes[] =
|
||||||
{
|
{
|
||||||
@@ -49,7 +50,9 @@ static GLboolean parseVersionString(int* api, int* major, int* minor, int* rev)
|
|||||||
|
|
||||||
*api = GLFW_OPENGL_API;
|
*api = GLFW_OPENGL_API;
|
||||||
|
|
||||||
version = (const char*) glGetString(GL_VERSION);
|
window = _glfwPlatformGetCurrentContext();
|
||||||
|
|
||||||
|
version = (const char*) window->GetString(GL_VERSION);
|
||||||
if (!version)
|
if (!version)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
@@ -352,6 +355,10 @@ GLboolean _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
|||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||||
|
|
||||||
|
window->GetIntegerv = (PFNGLGETINTEGERVPROC) glfwGetProcAddress("glGetIntegerv");
|
||||||
|
window->GetString = (PFNGLGETSTRINGPROC) glfwGetProcAddress("glGetString");
|
||||||
|
window->Clear = (PFNGLCLEARPROC) glfwGetProcAddress("glClear");
|
||||||
|
|
||||||
if (!parseVersionString(&window->context.api,
|
if (!parseVersionString(&window->context.api,
|
||||||
&window->context.major,
|
&window->context.major,
|
||||||
&window->context.minor,
|
&window->context.minor,
|
||||||
@@ -382,7 +389,7 @@ GLboolean _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
|||||||
if (window->context.major >= 3)
|
if (window->context.major >= 3)
|
||||||
{
|
{
|
||||||
GLint flags;
|
GLint flags;
|
||||||
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
|
window->GetIntegerv(GL_CONTEXT_FLAGS, &flags);
|
||||||
|
|
||||||
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
|
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
|
||||||
window->context.forward = GL_TRUE;
|
window->context.forward = GL_TRUE;
|
||||||
@@ -404,7 +411,7 @@ GLboolean _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
|||||||
(window->context.major == 3 && window->context.minor >= 2))
|
(window->context.major == 3 && window->context.minor >= 2))
|
||||||
{
|
{
|
||||||
GLint mask;
|
GLint mask;
|
||||||
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
|
window->GetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
|
||||||
|
|
||||||
if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
|
if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
|
||||||
window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
|
window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
|
||||||
@@ -427,7 +434,7 @@ GLboolean _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
|||||||
// only present from 3.0 while the extension applies from 1.1
|
// only present from 3.0 while the extension applies from 1.1
|
||||||
|
|
||||||
GLint strategy;
|
GLint strategy;
|
||||||
glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
|
window->GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
|
||||||
|
|
||||||
if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
|
if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
|
||||||
window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
|
window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
|
||||||
@@ -444,7 +451,7 @@ GLboolean _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
|||||||
// one, so we can reuse them here
|
// one, so we can reuse them here
|
||||||
|
|
||||||
GLint strategy;
|
GLint strategy;
|
||||||
glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
|
window->GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
|
||||||
|
|
||||||
if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
|
if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
|
||||||
window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
|
window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
|
||||||
@@ -456,7 +463,7 @@ GLboolean _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
|||||||
if (glfwExtensionSupported("GL_KHR_context_flush_control"))
|
if (glfwExtensionSupported("GL_KHR_context_flush_control"))
|
||||||
{
|
{
|
||||||
GLint behavior;
|
GLint behavior;
|
||||||
glGetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior);
|
window->GetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior);
|
||||||
|
|
||||||
if (behavior == GL_NONE)
|
if (behavior == GL_NONE)
|
||||||
window->context.release = GLFW_RELEASE_BEHAVIOR_NONE;
|
window->context.release = GLFW_RELEASE_BEHAVIOR_NONE;
|
||||||
@@ -490,19 +497,16 @@ GLboolean _glfwIsValidContext(const _GLFWctxconfig* ctxconfig)
|
|||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwStringInExtensionString(const char* string, const GLubyte* extensions)
|
int _glfwStringInExtensionString(const char* string, const char* extensions)
|
||||||
{
|
{
|
||||||
const GLubyte* start;
|
const char* start = extensions;
|
||||||
GLubyte* where;
|
|
||||||
GLubyte* terminator;
|
|
||||||
|
|
||||||
// It takes a bit of care to be fool-proof about parsing the
|
|
||||||
// OpenGL extensions string. Don't be fooled by sub-strings,
|
|
||||||
// etc.
|
|
||||||
start = extensions;
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
where = (GLubyte*) strstr((const char*) start, string);
|
const char* where;
|
||||||
|
const char* terminator;
|
||||||
|
|
||||||
|
where = strstr(start, string);
|
||||||
if (!where)
|
if (!where)
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
|
|
||||||
@@ -527,12 +531,7 @@ int _glfwStringInExtensionString(const char* string, const GLubyte* extensions)
|
|||||||
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
|
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
if (_glfwPlatformGetCurrentContext() == window)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_glfwPlatformMakeContextCurrent(window);
|
_glfwPlatformMakeContextCurrent(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,7 +588,7 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
|
|||||||
|
|
||||||
// Check if extension is in the modern OpenGL extensions string list
|
// Check if extension is in the modern OpenGL extensions string list
|
||||||
|
|
||||||
glGetIntegerv(GL_NUM_EXTENSIONS, &count);
|
window->GetIntegerv(GL_NUM_EXTENSIONS, &count);
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
@@ -610,7 +609,7 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
|
|||||||
{
|
{
|
||||||
// Check if extension is in the old style OpenGL extensions string
|
// Check if extension is in the old style OpenGL extensions string
|
||||||
|
|
||||||
const GLubyte* extensions = glGetString(GL_EXTENSIONS);
|
const char* extensions = (const char*) window->GetString(GL_EXTENSIONS);
|
||||||
if (!extensions)
|
if (!extensions)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
|||||||
+216
-62
@@ -78,7 +78,7 @@ static const char* getErrorString(EGLint error)
|
|||||||
static int getConfigAttrib(EGLConfig config, int attrib)
|
static int getConfigAttrib(EGLConfig config, int attrib)
|
||||||
{
|
{
|
||||||
int value;
|
int value;
|
||||||
eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
|
_glfw_eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ static GLboolean chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
|
|||||||
const _GLFWfbconfig* closest;
|
const _GLFWfbconfig* closest;
|
||||||
int i, nativeCount, usableCount;
|
int i, nativeCount, usableCount;
|
||||||
|
|
||||||
eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
|
_glfw_eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
|
||||||
if (!nativeCount)
|
if (!nativeCount)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
|
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
|
||||||
@@ -101,7 +101,8 @@ static GLboolean chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nativeConfigs = calloc(nativeCount, sizeof(EGLConfig));
|
nativeConfigs = calloc(nativeCount, sizeof(EGLConfig));
|
||||||
eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount);
|
_glfw_eglGetConfigs(_glfw.egl.display, nativeConfigs,
|
||||||
|
nativeCount, &nativeCount);
|
||||||
|
|
||||||
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
||||||
usableCount = 0;
|
usableCount = 0;
|
||||||
@@ -112,24 +113,18 @@ static GLboolean chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
|
|||||||
_GLFWfbconfig* u = usableConfigs + usableCount;
|
_GLFWfbconfig* u = usableConfigs + usableCount;
|
||||||
|
|
||||||
#if defined(_GLFW_X11)
|
#if defined(_GLFW_X11)
|
||||||
if (!getConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
|
|
||||||
{
|
|
||||||
// Only consider EGLConfigs with associated visuals
|
// Only consider EGLConfigs with associated visuals
|
||||||
|
if (!getConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
#endif // _GLFW_X11
|
#endif // _GLFW_X11
|
||||||
|
|
||||||
if (!(getConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) & EGL_RGB_BUFFER))
|
|
||||||
{
|
|
||||||
// Only consider RGB(A) EGLConfigs
|
// Only consider RGB(A) EGLConfigs
|
||||||
|
if (!(getConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) & EGL_RGB_BUFFER))
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (!(getConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
|
|
||||||
{
|
|
||||||
// Only consider window EGLConfigs
|
// Only consider window EGLConfigs
|
||||||
|
if (!(getConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->api == GLFW_OPENGL_ES_API)
|
if (ctxconfig->api == GLFW_OPENGL_ES_API)
|
||||||
{
|
{
|
||||||
@@ -184,30 +179,91 @@ static GLboolean chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
|
|||||||
//
|
//
|
||||||
int _glfwInitContextAPI(void)
|
int _glfwInitContextAPI(void)
|
||||||
{
|
{
|
||||||
if (!_glfwInitTLS())
|
int i;
|
||||||
|
const char* sonames[] =
|
||||||
|
{
|
||||||
|
#if defined(_GLFW_WIN32)
|
||||||
|
"libEGL.dll",
|
||||||
|
"EGL.dll",
|
||||||
|
#elif defined(_GLFW_COCOA)
|
||||||
|
"libEGL.dylib",
|
||||||
|
#else
|
||||||
|
"libEGL.so.1",
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!_glfwCreateContextTLS())
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
|
|
||||||
_glfw.egl.display = eglGetDisplay((EGLNativeDisplayType)_GLFW_EGL_NATIVE_DISPLAY);
|
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: Failed to load EGL");
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.egl.GetConfigAttrib =
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
|
||||||
|
_glfw.egl.GetConfigs =
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
|
||||||
|
_glfw.egl.GetDisplay =
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
|
||||||
|
_glfw.egl.GetError =
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglGetError");
|
||||||
|
_glfw.egl.Initialize =
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglInitialize");
|
||||||
|
_glfw.egl.Terminate =
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglTerminate");
|
||||||
|
_glfw.egl.BindAPI =
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
|
||||||
|
_glfw.egl.CreateContext =
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
|
||||||
|
_glfw.egl.DestroySurface =
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
|
||||||
|
_glfw.egl.DestroyContext =
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
|
||||||
|
_glfw.egl.CreateWindowSurface =
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
|
||||||
|
_glfw.egl.MakeCurrent =
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
|
||||||
|
_glfw.egl.SwapBuffers =
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
|
||||||
|
_glfw.egl.SwapInterval =
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
|
||||||
|
_glfw.egl.QueryString =
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglQueryString");
|
||||||
|
_glfw.egl.GetProcAddress =
|
||||||
|
_glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");
|
||||||
|
|
||||||
|
_glfw.egl.display =
|
||||||
|
_glfw_eglGetDisplay((EGLNativeDisplayType)_GLFW_EGL_NATIVE_DISPLAY);
|
||||||
if (_glfw.egl.display == EGL_NO_DISPLAY)
|
if (_glfw.egl.display == EGL_NO_DISPLAY)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"EGL: Failed to get EGL display: %s",
|
"EGL: Failed to get EGL display: %s",
|
||||||
getErrorString(eglGetError()));
|
getErrorString(_glfw_eglGetError()));
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!eglInitialize(_glfw.egl.display,
|
if (!_glfw_eglInitialize(_glfw.egl.display,
|
||||||
&_glfw.egl.versionMajor,
|
&_glfw.egl.major,
|
||||||
&_glfw.egl.versionMinor))
|
&_glfw.egl.minor))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"EGL: Failed to initialize EGL: %s",
|
"EGL: Failed to initialize EGL: %s",
|
||||||
getErrorString(eglGetError()));
|
getErrorString(_glfw_eglGetError()));
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfwPlatformExtensionSupported("EGL_KHR_create_context"))
|
_glfw.egl.KHR_create_context =
|
||||||
_glfw.egl.KHR_create_context = GL_TRUE;
|
_glfwPlatformExtensionSupported("EGL_KHR_create_context");
|
||||||
|
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
@@ -216,9 +272,16 @@ int _glfwInitContextAPI(void)
|
|||||||
//
|
//
|
||||||
void _glfwTerminateContextAPI(void)
|
void _glfwTerminateContextAPI(void)
|
||||||
{
|
{
|
||||||
eglTerminate(_glfw.egl.display);
|
if (_glfw_eglTerminate)
|
||||||
|
_glfw_eglTerminate(_glfw.egl.display);
|
||||||
|
|
||||||
_glfwTerminateTLS();
|
if (_glfw.egl.handle)
|
||||||
|
{
|
||||||
|
_glfw_dlclose(_glfw.egl.handle);
|
||||||
|
_glfw.egl.handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwDestroyContextTLS();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define setEGLattrib(attribName, attribValue) \
|
#define setEGLattrib(attribName, attribValue) \
|
||||||
@@ -243,7 +306,7 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (!chooseFBConfigs(ctxconfig, fbconfig, &config))
|
if (!chooseFBConfigs(ctxconfig, fbconfig, &config))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
"EGL: Failed to find a suitable EGLConfig");
|
"EGL: Failed to find a suitable EGLConfig");
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
@@ -256,7 +319,7 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
EGLint redBits, greenBits, blueBits, alphaBits, visualID = 0;
|
EGLint redBits, greenBits, blueBits, alphaBits, visualID = 0;
|
||||||
XVisualInfo info;
|
XVisualInfo info;
|
||||||
|
|
||||||
eglGetConfigAttrib(_glfw.egl.display, config,
|
_glfw_eglGetConfigAttrib(_glfw.egl.display, config,
|
||||||
EGL_NATIVE_VISUAL_ID, &visualID);
|
EGL_NATIVE_VISUAL_ID, &visualID);
|
||||||
|
|
||||||
info.screen = _glfw.x11.screen;
|
info.screen = _glfw.x11.screen;
|
||||||
@@ -270,16 +333,16 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// some EGL drivers don't implement the EGL_NATIVE_VISUAL_ID
|
// Some EGL drivers do not implement the EGL_NATIVE_VISUAL_ID
|
||||||
// attribute, so attempt to find the closest match.
|
// attribute, so attempt to find the closest match
|
||||||
|
|
||||||
eglGetConfigAttrib(_glfw.egl.display, config,
|
_glfw_eglGetConfigAttrib(_glfw.egl.display, config,
|
||||||
EGL_RED_SIZE, &redBits);
|
EGL_RED_SIZE, &redBits);
|
||||||
eglGetConfigAttrib(_glfw.egl.display, config,
|
_glfw_eglGetConfigAttrib(_glfw.egl.display, config,
|
||||||
EGL_GREEN_SIZE, &greenBits);
|
EGL_GREEN_SIZE, &greenBits);
|
||||||
eglGetConfigAttrib(_glfw.egl.display, config,
|
_glfw_eglGetConfigAttrib(_glfw.egl.display, config,
|
||||||
EGL_BLUE_SIZE, &blueBits);
|
EGL_BLUE_SIZE, &blueBits);
|
||||||
eglGetConfigAttrib(_glfw.egl.display, config,
|
_glfw_eglGetConfigAttrib(_glfw.egl.display, config,
|
||||||
EGL_ALPHA_SIZE, &alphaBits);
|
EGL_ALPHA_SIZE, &alphaBits);
|
||||||
|
|
||||||
info.depth = redBits + greenBits + blueBits + alphaBits;
|
info.depth = redBits + greenBits + blueBits + alphaBits;
|
||||||
@@ -299,38 +362,38 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (ctxconfig->api == GLFW_OPENGL_ES_API)
|
if (ctxconfig->api == GLFW_OPENGL_ES_API)
|
||||||
{
|
{
|
||||||
if (!eglBindAPI(EGL_OPENGL_ES_API))
|
if (!_glfw_eglBindAPI(EGL_OPENGL_ES_API))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"EGL: Failed to bind OpenGL ES: %s",
|
"EGL: Failed to bind OpenGL ES: %s",
|
||||||
getErrorString(eglGetError()));
|
getErrorString(_glfw_eglGetError()));
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!eglBindAPI(EGL_OPENGL_API))
|
if (!_glfw_eglBindAPI(EGL_OPENGL_API))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"EGL: Failed to bind OpenGL: %s",
|
"EGL: Failed to bind OpenGL: %s",
|
||||||
getErrorString(eglGetError()));
|
getErrorString(_glfw_eglGetError()));
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfw.egl.KHR_create_context)
|
if (_glfw.egl.KHR_create_context)
|
||||||
{
|
{
|
||||||
int index = 0, mask = 0, flags = 0, strategy = 0;
|
int index = 0, mask = 0, flags = 0;
|
||||||
|
|
||||||
if (ctxconfig->api == GLFW_OPENGL_API)
|
if (ctxconfig->api == GLFW_OPENGL_API)
|
||||||
{
|
{
|
||||||
|
if (ctxconfig->forward)
|
||||||
|
flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
|
||||||
|
|
||||||
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
||||||
mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
|
mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
|
||||||
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
||||||
mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
|
mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
|
||||||
|
|
||||||
if (ctxconfig->forward)
|
|
||||||
flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->debug)
|
if (ctxconfig->debug)
|
||||||
@@ -339,9 +402,15 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
if (ctxconfig->robustness)
|
if (ctxconfig->robustness)
|
||||||
{
|
{
|
||||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||||
strategy = EGL_NO_RESET_NOTIFICATION_KHR;
|
{
|
||||||
|
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||||
|
EGL_NO_RESET_NOTIFICATION_KHR);
|
||||||
|
}
|
||||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||||
strategy = EGL_LOSE_CONTEXT_ON_RESET_KHR;
|
{
|
||||||
|
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||||
|
EGL_LOSE_CONTEXT_ON_RESET_KHR);
|
||||||
|
}
|
||||||
|
|
||||||
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
|
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
|
||||||
}
|
}
|
||||||
@@ -358,9 +427,6 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
if (flags)
|
if (flags)
|
||||||
setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags);
|
setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags);
|
||||||
|
|
||||||
if (strategy)
|
|
||||||
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, strategy);
|
|
||||||
|
|
||||||
setEGLattrib(EGL_NONE, EGL_NONE);
|
setEGLattrib(EGL_NONE, EGL_NONE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -376,19 +442,83 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
// Context release behaviors (GL_KHR_context_flush_control) are not yet
|
// Context release behaviors (GL_KHR_context_flush_control) are not yet
|
||||||
// supported on EGL but are not a hard constraint, so ignore and continue
|
// supported on EGL but are not a hard constraint, so ignore and continue
|
||||||
|
|
||||||
window->egl.context = eglCreateContext(_glfw.egl.display,
|
window->egl.context = _glfw_eglCreateContext(_glfw.egl.display,
|
||||||
config, share, attribs);
|
config, share, attribs);
|
||||||
|
|
||||||
if (window->egl.context == EGL_NO_CONTEXT)
|
if (window->egl.context == EGL_NO_CONTEXT)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
"EGL: Failed to create context: %s",
|
"EGL: Failed to create context: %s",
|
||||||
getErrorString(eglGetError()));
|
getErrorString(_glfw_eglGetError()));
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
window->egl.config = config;
|
window->egl.config = config;
|
||||||
|
|
||||||
|
// Load the appropriate client library
|
||||||
|
{
|
||||||
|
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",
|
||||||
|
#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->api == GLFW_OPENGL_ES_API)
|
||||||
|
{
|
||||||
|
if (ctxconfig->major == 1)
|
||||||
|
sonames = es1sonames;
|
||||||
|
else
|
||||||
|
sonames = es2sonames;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sonames = glsonames;
|
||||||
|
|
||||||
|
for (i = 0; sonames[i]; i++)
|
||||||
|
{
|
||||||
|
window->egl.client = _glfw_dlopen(sonames[i]);
|
||||||
|
if (window->egl.client)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window->egl.client)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
|
"EGL: Failed to load client library");
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,6 +528,19 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
//
|
//
|
||||||
void _glfwDestroyContext(_GLFWwindow* window)
|
void _glfwDestroyContext(_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.api != GLFW_OPENGL_API)
|
||||||
|
#endif // _GLFW_X11
|
||||||
|
{
|
||||||
|
if (window->egl.client)
|
||||||
|
{
|
||||||
|
_glfw_dlclose(window->egl.client);
|
||||||
|
window->egl.client = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(_GLFW_X11)
|
#if defined(_GLFW_X11)
|
||||||
if (window->egl.visual)
|
if (window->egl.visual)
|
||||||
{
|
{
|
||||||
@@ -408,13 +551,13 @@ void _glfwDestroyContext(_GLFWwindow* window)
|
|||||||
|
|
||||||
if (window->egl.surface)
|
if (window->egl.surface)
|
||||||
{
|
{
|
||||||
eglDestroySurface(_glfw.egl.display, window->egl.surface);
|
_glfw_eglDestroySurface(_glfw.egl.display, window->egl.surface);
|
||||||
window->egl.surface = EGL_NO_SURFACE;
|
window->egl.surface = EGL_NO_SURFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->egl.context)
|
if (window->egl.context)
|
||||||
{
|
{
|
||||||
eglDestroyContext(_glfw.egl.display, window->egl.context);
|
_glfw_eglDestroyContext(_glfw.egl.display, window->egl.context);
|
||||||
window->egl.context = EGL_NO_CONTEXT;
|
window->egl.context = EGL_NO_CONTEXT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -443,7 +586,8 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
if (window->egl.surface == EGL_NO_SURFACE)
|
if (window->egl.surface == EGL_NO_SURFACE)
|
||||||
{
|
{
|
||||||
window->egl.surface = eglCreateWindowSurface(_glfw.egl.display,
|
window->egl.surface =
|
||||||
|
_glfw_eglCreateWindowSurface(_glfw.egl.display,
|
||||||
window->egl.config,
|
window->egl.config,
|
||||||
(EGLNativeWindowType)_GLFW_EGL_NATIVE_WINDOW,
|
(EGLNativeWindowType)_GLFW_EGL_NATIVE_WINDOW,
|
||||||
NULL);
|
NULL);
|
||||||
@@ -451,42 +595,43 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"EGL: Failed to create window surface: %s",
|
"EGL: Failed to create window surface: %s",
|
||||||
getErrorString(eglGetError()));
|
getErrorString(_glfw_eglGetError()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eglMakeCurrent(_glfw.egl.display,
|
_glfw_eglMakeCurrent(_glfw.egl.display,
|
||||||
window->egl.surface,
|
window->egl.surface,
|
||||||
window->egl.surface,
|
window->egl.surface,
|
||||||
window->egl.context);
|
window->egl.context);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
eglMakeCurrent(_glfw.egl.display,
|
_glfw_eglMakeCurrent(_glfw.egl.display,
|
||||||
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
EGL_NO_SURFACE,
|
||||||
|
EGL_NO_SURFACE,
|
||||||
|
EGL_NO_CONTEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwSetCurrentContext(window);
|
_glfwSetContextTLS(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
|
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
eglSwapBuffers(_glfw.egl.display, window->egl.surface);
|
_glfw_eglSwapBuffers(_glfw.egl.display, window->egl.surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSwapInterval(int interval)
|
void _glfwPlatformSwapInterval(int interval)
|
||||||
{
|
{
|
||||||
eglSwapInterval(_glfw.egl.display, interval);
|
_glfw_eglSwapInterval(_glfw.egl.display, interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformExtensionSupported(const char* extension)
|
int _glfwPlatformExtensionSupported(const char* extension)
|
||||||
{
|
{
|
||||||
const char* extensions;
|
const char* extensions = _glfw_eglQueryString(_glfw.egl.display,
|
||||||
|
EGL_EXTENSIONS);
|
||||||
extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
|
if (extensions)
|
||||||
if (extensions != NULL)
|
|
||||||
{
|
{
|
||||||
if (_glfwStringInExtensionString(extension, (unsigned char*) extensions))
|
if (_glfwStringInExtensionString(extension, extensions))
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,7 +640,16 @@ int _glfwPlatformExtensionSupported(const char* extension)
|
|||||||
|
|
||||||
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
|
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
|
||||||
{
|
{
|
||||||
return eglGetProcAddress(procname);
|
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||||
|
|
||||||
|
if (window->egl.client)
|
||||||
|
{
|
||||||
|
GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->egl.client, procname);
|
||||||
|
if (proc)
|
||||||
|
return proc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _glfw_eglGetProcAddress(procname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+69
-8
@@ -25,8 +25,19 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _egl_context_h_
|
#ifndef _glfw3_egl_context_h_
|
||||||
#define _egl_context_h_
|
#define _glfw3_egl_context_h_
|
||||||
|
|
||||||
|
#if defined(_GLFW_WIN32)
|
||||||
|
#define _glfw_dlopen(name) LoadLibraryA(name)
|
||||||
|
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
|
||||||
|
#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
|
||||||
|
#else
|
||||||
|
#include <dlfcn.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)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
|
|
||||||
@@ -35,10 +46,39 @@
|
|||||||
// extensions and not all operating systems come with an up-to-date version
|
// extensions and not all operating systems come with an up-to-date version
|
||||||
#include "../deps/EGL/eglext.h"
|
#include "../deps/EGL/eglext.h"
|
||||||
|
|
||||||
// Do we have support for dlopen/dlsym?
|
// EGL function pointer typedefs
|
||||||
#if defined(_GLFW_HAS_DLOPEN)
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGATTRIBPROC)(EGLDisplay,EGLConfig,EGLint,EGLint*);
|
||||||
#include <dlfcn.h>
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGSPROC)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
|
||||||
#endif
|
typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType);
|
||||||
|
typedef EGLint (EGLAPIENTRY * PFNEGLGETERRORPROC)(void);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLINITIALIZEPROC)(EGLDisplay,EGLint*,EGLint*);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLTERMINATEPROC)(EGLDisplay);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLBINDAPIPROC)(EGLenum);
|
||||||
|
typedef EGLContext (EGLAPIENTRY * PFNEGLCREATECONTEXTPROC)(EGLDisplay,EGLConfig,EGLContext,const EGLint*);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYSURFACEPROC)(EGLDisplay,EGLSurface);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYCONTEXTPROC)(EGLDisplay,EGLContext);
|
||||||
|
typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLMAKECURRENTPROC)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPBUFFERSPROC)(EGLDisplay,EGLSurface);
|
||||||
|
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPINTERVALPROC)(EGLDisplay,EGLint);
|
||||||
|
typedef const char* (EGLAPIENTRY * PFNEGLQUERYSTRINGPROC)(EGLDisplay,EGLint);
|
||||||
|
typedef GLFWglproc (EGLAPIENTRY * PFNEGLGETPROCADDRESSPROC)(const char*);
|
||||||
|
#define _glfw_eglGetConfigAttrib _glfw.egl.GetConfigAttrib
|
||||||
|
#define _glfw_eglGetConfigs _glfw.egl.GetConfigs
|
||||||
|
#define _glfw_eglGetDisplay _glfw.egl.GetDisplay
|
||||||
|
#define _glfw_eglGetError _glfw.egl.GetError
|
||||||
|
#define _glfw_eglInitialize _glfw.egl.Initialize
|
||||||
|
#define _glfw_eglTerminate _glfw.egl.Terminate
|
||||||
|
#define _glfw_eglBindAPI _glfw.egl.BindAPI
|
||||||
|
#define _glfw_eglCreateContext _glfw.egl.CreateContext
|
||||||
|
#define _glfw_eglDestroySurface _glfw.egl.DestroySurface
|
||||||
|
#define _glfw_eglDestroyContext _glfw.egl.DestroyContext
|
||||||
|
#define _glfw_eglCreateWindowSurface _glfw.egl.CreateWindowSurface
|
||||||
|
#define _glfw_eglMakeCurrent _glfw.egl.MakeCurrent
|
||||||
|
#define _glfw_eglSwapBuffers _glfw.egl.SwapBuffers
|
||||||
|
#define _glfw_eglSwapInterval _glfw.egl.SwapInterval
|
||||||
|
#define _glfw_eglQueryString _glfw.egl.QueryString
|
||||||
|
#define _glfw_eglGetProcAddress _glfw.egl.GetProcAddress
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_FBCONFIG EGLConfig egl
|
#define _GLFW_PLATFORM_FBCONFIG EGLConfig egl
|
||||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextEGL egl
|
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextEGL egl
|
||||||
@@ -57,6 +97,8 @@ typedef struct _GLFWcontextEGL
|
|||||||
XVisualInfo* visual;
|
XVisualInfo* visual;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void* client;
|
||||||
|
|
||||||
} _GLFWcontextEGL;
|
} _GLFWcontextEGL;
|
||||||
|
|
||||||
|
|
||||||
@@ -65,10 +107,29 @@ typedef struct _GLFWcontextEGL
|
|||||||
typedef struct _GLFWlibraryEGL
|
typedef struct _GLFWlibraryEGL
|
||||||
{
|
{
|
||||||
EGLDisplay display;
|
EGLDisplay display;
|
||||||
EGLint versionMajor, versionMinor;
|
EGLint major, minor;
|
||||||
|
|
||||||
GLboolean KHR_create_context;
|
GLboolean KHR_create_context;
|
||||||
|
|
||||||
|
void* handle;
|
||||||
|
|
||||||
|
PFNEGLGETCONFIGATTRIBPROC GetConfigAttrib;
|
||||||
|
PFNEGLGETCONFIGSPROC GetConfigs;
|
||||||
|
PFNEGLGETDISPLAYPROC GetDisplay;
|
||||||
|
PFNEGLGETERRORPROC GetError;
|
||||||
|
PFNEGLINITIALIZEPROC Initialize;
|
||||||
|
PFNEGLTERMINATEPROC Terminate;
|
||||||
|
PFNEGLBINDAPIPROC BindAPI;
|
||||||
|
PFNEGLCREATECONTEXTPROC CreateContext;
|
||||||
|
PFNEGLDESTROYSURFACEPROC DestroySurface;
|
||||||
|
PFNEGLDESTROYCONTEXTPROC DestroyContext;
|
||||||
|
PFNEGLCREATEWINDOWSURFACEPROC CreateWindowSurface;
|
||||||
|
PFNEGLMAKECURRENTPROC MakeCurrent;
|
||||||
|
PFNEGLSWAPBUFFERSPROC SwapBuffers;
|
||||||
|
PFNEGLSWAPINTERVALPROC SwapInterval;
|
||||||
|
PFNEGLQUERYSTRINGPROC QueryString;
|
||||||
|
PFNEGLGETPROCADDRESSPROC GetProcAddress;
|
||||||
|
|
||||||
} _GLFWlibraryEGL;
|
} _GLFWlibraryEGL;
|
||||||
|
|
||||||
|
|
||||||
@@ -82,4 +143,4 @@ int _glfwAnalyzeContext(const _GLFWwindow* window,
|
|||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
|
|
||||||
#endif // _egl_context_h_
|
#endif // _glfw3_egl_context_h_
|
||||||
|
|||||||
+2
-12
@@ -57,23 +57,13 @@
|
|||||||
// Define this to 1 if building as a shared library / dynamic library / DLL
|
// Define this to 1 if building as a shared library / dynamic library / DLL
|
||||||
#cmakedefine _GLFW_BUILD_DLL
|
#cmakedefine _GLFW_BUILD_DLL
|
||||||
|
|
||||||
// Define this to 1 if glfwSwapInterval should ignore DWM compositing status
|
// Define this to 1 to force use of high-performance GPU on hybrid systems
|
||||||
#cmakedefine _GLFW_USE_DWM_SWAP_INTERVAL
|
#cmakedefine _GLFW_USE_HYBRID_HPG
|
||||||
// Define this to 1 to force use of high-performance GPU on Optimus systems
|
|
||||||
#cmakedefine _GLFW_USE_OPTIMUS_HPG
|
|
||||||
|
|
||||||
// Define this to 1 if the XInput X11 extension is available
|
// Define this to 1 if the XInput X11 extension is available
|
||||||
#cmakedefine _GLFW_HAS_XINPUT
|
#cmakedefine _GLFW_HAS_XINPUT
|
||||||
// Define this to 1 if the Xxf86vm X11 extension is available
|
// Define this to 1 if the Xxf86vm X11 extension is available
|
||||||
#cmakedefine _GLFW_HAS_XF86VM
|
#cmakedefine _GLFW_HAS_XF86VM
|
||||||
// Define this to 1 if glXGetProcAddress is available
|
|
||||||
#cmakedefine _GLFW_HAS_GLXGETPROCADDRESS
|
|
||||||
// Define this to 1 if glXGetProcAddressARB is available
|
|
||||||
#cmakedefine _GLFW_HAS_GLXGETPROCADDRESSARB
|
|
||||||
// Define this to 1 if glXGetProcAddressEXT is available
|
|
||||||
#cmakedefine _GLFW_HAS_GLXGETPROCADDRESSEXT
|
|
||||||
// Define this to 1 if dlopen is available
|
|
||||||
#cmakedefine _GLFW_HAS_DLOPEN
|
|
||||||
|
|
||||||
// Define this to 1 if glfwInit should change the current directory
|
// Define this to 1 if glfwInit should change the current directory
|
||||||
#cmakedefine _GLFW_USE_CHDIR
|
#cmakedefine _GLFW_USE_CHDIR
|
||||||
|
|||||||
+102
-79
@@ -30,11 +30,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
// This is the only glXGetProcAddress variant not declared by glxext.h
|
|
||||||
void (*glXGetProcAddressEXT(const GLubyte* procName))();
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef GLXBadProfileARB
|
#ifndef GLXBadProfileARB
|
||||||
#define GLXBadProfileARB 13
|
#define GLXBadProfileARB 13
|
||||||
@@ -46,7 +42,7 @@ void (*glXGetProcAddressEXT(const GLubyte* procName))();
|
|||||||
static int getFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
|
static int getFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
|
||||||
{
|
{
|
||||||
int value;
|
int value;
|
||||||
glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value);
|
_glfw_glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,15 +57,13 @@ static GLboolean chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* resul
|
|||||||
const char* vendor;
|
const char* vendor;
|
||||||
GLboolean trustWindowBit = GL_TRUE;
|
GLboolean trustWindowBit = GL_TRUE;
|
||||||
|
|
||||||
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
|
|
||||||
if (strcmp(vendor, "Chromium") == 0)
|
|
||||||
{
|
|
||||||
// HACK: This is a (hopefully temporary) workaround for Chromium
|
// HACK: This is a (hopefully temporary) workaround for Chromium
|
||||||
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
|
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
|
||||||
|
vendor = _glfw_glXGetClientString(_glfw.x11.display, GLX_VENDOR);
|
||||||
|
if (strcmp(vendor, "Chromium") == 0)
|
||||||
trustWindowBit = GL_FALSE;
|
trustWindowBit = GL_FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
nativeConfigs = glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen,
|
nativeConfigs = _glfw_glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen,
|
||||||
&nativeCount);
|
&nativeCount);
|
||||||
if (!nativeCount)
|
if (!nativeCount)
|
||||||
{
|
{
|
||||||
@@ -85,26 +79,20 @@ static GLboolean chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* resul
|
|||||||
const GLXFBConfig n = nativeConfigs[i];
|
const GLXFBConfig n = nativeConfigs[i];
|
||||||
_GLFWfbconfig* u = usableConfigs + usableCount;
|
_GLFWfbconfig* u = usableConfigs + usableCount;
|
||||||
|
|
||||||
if (!getFBConfigAttrib(n, GLX_VISUAL_ID))
|
|
||||||
{
|
|
||||||
// Only consider GLXFBConfigs with associated visuals
|
// Only consider GLXFBConfigs with associated visuals
|
||||||
|
if (!getFBConfigAttrib(n, GLX_VISUAL_ID))
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (!(getFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))
|
|
||||||
{
|
|
||||||
// Only consider RGBA GLXFBConfigs
|
// Only consider RGBA GLXFBConfigs
|
||||||
|
if (!(getFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
|
// Only consider window GLXFBConfigs
|
||||||
if (!(getFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT))
|
if (!(getFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT))
|
||||||
{
|
{
|
||||||
if (trustWindowBit)
|
if (trustWindowBit)
|
||||||
{
|
|
||||||
// Only consider window GLXFBConfigs
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
u->redBits = getFBConfigAttrib(n, GLX_RED_SIZE);
|
u->redBits = getFBConfigAttrib(n, GLX_RED_SIZE);
|
||||||
u->greenBits = getFBConfigAttrib(n, GLX_GREEN_SIZE);
|
u->greenBits = getFBConfigAttrib(n, GLX_GREEN_SIZE);
|
||||||
@@ -129,7 +117,7 @@ static GLboolean chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* resul
|
|||||||
if (_glfw.glx.ARB_multisample)
|
if (_glfw.glx.ARB_multisample)
|
||||||
u->samples = getFBConfigAttrib(n, GLX_SAMPLES);
|
u->samples = getFBConfigAttrib(n, GLX_SAMPLES);
|
||||||
|
|
||||||
if (_glfw.glx.ARB_framebuffer_sRGB)
|
if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB)
|
||||||
u->sRGB = getFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
|
u->sRGB = getFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
|
||||||
|
|
||||||
u->glx = n;
|
u->glx = n;
|
||||||
@@ -152,7 +140,7 @@ static GLXContext createLegacyContext(_GLFWwindow* window,
|
|||||||
GLXFBConfig fbconfig,
|
GLXFBConfig fbconfig,
|
||||||
GLXContext share)
|
GLXContext share)
|
||||||
{
|
{
|
||||||
return glXCreateNewContext(_glfw.x11.display,
|
return _glfw_glXCreateNewContext(_glfw.x11.display,
|
||||||
fbconfig,
|
fbconfig,
|
||||||
GLX_RGBA_TYPE,
|
GLX_RGBA_TYPE,
|
||||||
share,
|
share,
|
||||||
@@ -168,19 +156,50 @@ static GLXContext createLegacyContext(_GLFWwindow* window,
|
|||||||
//
|
//
|
||||||
int _glfwInitContextAPI(void)
|
int _glfwInitContextAPI(void)
|
||||||
{
|
{
|
||||||
if (!_glfwInitTLS())
|
#if defined(__CYGWIN__)
|
||||||
return GL_FALSE;
|
const char* soname = "libGL-1.so";
|
||||||
|
#else
|
||||||
#ifdef _GLFW_DLOPEN_LIBGL
|
const char* soname = "libGL.so.1";
|
||||||
_glfw.glx.libGL = dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL);
|
|
||||||
if (!_glfw.glx.libGL)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to find libGL");
|
|
||||||
return GL_FALSE;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!glXQueryExtension(_glfw.x11.display,
|
if (!_glfwCreateContextTLS())
|
||||||
|
return GL_FALSE;
|
||||||
|
|
||||||
|
_glfw.glx.handle = dlopen(soname, RTLD_LAZY | RTLD_GLOBAL);
|
||||||
|
if (!_glfw.glx.handle)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: %s", dlerror());
|
||||||
|
return GL_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.GetVisualFromFBConfig =
|
||||||
|
dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
|
||||||
|
_glfw.glx.GetProcAddress =
|
||||||
|
dlsym(_glfw.glx.handle, "glXGetProcAddress");
|
||||||
|
_glfw.glx.GetProcAddressARB =
|
||||||
|
dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
|
||||||
|
|
||||||
|
if (!_glfw_glXQueryExtension(_glfw.x11.display,
|
||||||
&_glfw.glx.errorBase,
|
&_glfw.glx.errorBase,
|
||||||
&_glfw.glx.eventBase))
|
&_glfw.glx.eventBase))
|
||||||
{
|
{
|
||||||
@@ -188,16 +207,16 @@ int _glfwInitContextAPI(void)
|
|||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!glXQueryVersion(_glfw.x11.display,
|
if (!_glfw_glXQueryVersion(_glfw.x11.display,
|
||||||
&_glfw.glx.versionMajor,
|
&_glfw.glx.major,
|
||||||
&_glfw.glx.versionMinor))
|
&_glfw.glx.minor))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"GLX: Failed to query GLX version");
|
"GLX: Failed to query GLX version");
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfw.glx.versionMajor == 1 && _glfw.glx.versionMinor < 3)
|
if (_glfw.glx.major == 1 && _glfw.glx.minor < 3)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"GLX: GLX version 1.3 is required");
|
"GLX: GLX version 1.3 is required");
|
||||||
@@ -237,6 +256,9 @@ int _glfwInitContextAPI(void)
|
|||||||
if (_glfwPlatformExtensionSupported("GLX_ARB_framebuffer_sRGB"))
|
if (_glfwPlatformExtensionSupported("GLX_ARB_framebuffer_sRGB"))
|
||||||
_glfw.glx.ARB_framebuffer_sRGB = GL_TRUE;
|
_glfw.glx.ARB_framebuffer_sRGB = GL_TRUE;
|
||||||
|
|
||||||
|
if (_glfwPlatformExtensionSupported("GLX_EXT_framebuffer_sRGB"))
|
||||||
|
_glfw.glx.EXT_framebuffer_sRGB = GL_TRUE;
|
||||||
|
|
||||||
if (_glfwPlatformExtensionSupported("GLX_ARB_create_context"))
|
if (_glfwPlatformExtensionSupported("GLX_ARB_create_context"))
|
||||||
{
|
{
|
||||||
_glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
|
_glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
|
||||||
@@ -265,16 +287,16 @@ int _glfwInitContextAPI(void)
|
|||||||
//
|
//
|
||||||
void _glfwTerminateContextAPI(void)
|
void _glfwTerminateContextAPI(void)
|
||||||
{
|
{
|
||||||
// Unload libGL.so if necessary
|
// NOTE: This function may not call any X11 functions, as it is called after
|
||||||
#ifdef _GLFW_DLOPEN_LIBGL
|
// XCloseDisplay (see _glfwPlatformTerminate for details)
|
||||||
if (_glfw.glx.libGL != NULL)
|
|
||||||
{
|
|
||||||
dlclose(_glfw.glx.libGL);
|
|
||||||
_glfw.glx.libGL = NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_glfwTerminateTLS();
|
if (_glfw.glx.handle)
|
||||||
|
{
|
||||||
|
dlclose(_glfw.glx.handle);
|
||||||
|
_glfw.glx.handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwDestroyContextTLS();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define setGLXattrib(attribName, attribValue) \
|
#define setGLXattrib(attribName, attribValue) \
|
||||||
@@ -291,7 +313,7 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
const _GLFWfbconfig* fbconfig)
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
int attribs[40];
|
int attribs[40];
|
||||||
GLXFBConfig native;
|
GLXFBConfig native = NULL;
|
||||||
GLXContext share = NULL;
|
GLXContext share = NULL;
|
||||||
|
|
||||||
if (ctxconfig->share)
|
if (ctxconfig->share)
|
||||||
@@ -299,13 +321,13 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (!chooseFBConfig(fbconfig, &native))
|
if (!chooseFBConfig(fbconfig, &native))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
"GLX: Failed to find a suitable GLXFBConfig");
|
"GLX: Failed to find a suitable GLXFBConfig");
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the corresponding visual
|
window->glx.visual = _glfw_glXGetVisualFromFBConfig(_glfw.x11.display,
|
||||||
window->glx.visual = glXGetVisualFromFBConfig(_glfw.x11.display, native);
|
native);
|
||||||
if (!window->glx.visual)
|
if (!window->glx.visual)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
@@ -350,21 +372,18 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (_glfw.glx.ARB_create_context)
|
if (_glfw.glx.ARB_create_context)
|
||||||
{
|
{
|
||||||
int index = 0, mask = 0, flags = 0, strategy = 0;
|
int index = 0, mask = 0, flags = 0;
|
||||||
|
|
||||||
if (ctxconfig->api == GLFW_OPENGL_API)
|
if (ctxconfig->api == GLFW_OPENGL_API)
|
||||||
{
|
{
|
||||||
if (ctxconfig->forward)
|
if (ctxconfig->forward)
|
||||||
flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
|
flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
|
||||||
|
|
||||||
if (ctxconfig->profile)
|
|
||||||
{
|
|
||||||
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
||||||
mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
|
mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||||
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
||||||
mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
mask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
|
mask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
|
||||||
|
|
||||||
@@ -376,9 +395,15 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
if (_glfw.glx.ARB_create_context_robustness)
|
if (_glfw.glx.ARB_create_context_robustness)
|
||||||
{
|
{
|
||||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||||
strategy = GLX_NO_RESET_NOTIFICATION_ARB;
|
{
|
||||||
|
setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||||
|
GLX_NO_RESET_NOTIFICATION_ARB);
|
||||||
|
}
|
||||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||||
strategy = GLX_LOSE_CONTEXT_ON_RESET_ARB;
|
{
|
||||||
|
setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||||
|
GLX_LOSE_CONTEXT_ON_RESET_ARB);
|
||||||
|
}
|
||||||
|
|
||||||
flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
|
flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
|
||||||
}
|
}
|
||||||
@@ -401,12 +426,11 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)
|
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||||
{
|
{
|
||||||
// NOTE: Only request an explicitly versioned context when
|
|
||||||
// necessary, as explicitly requesting version 1.0 does not
|
|
||||||
// always return the highest available version
|
|
||||||
|
|
||||||
setGLXattrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
setGLXattrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||||
setGLXattrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
setGLXattrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||||
}
|
}
|
||||||
@@ -417,9 +441,6 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
if (flags)
|
if (flags)
|
||||||
setGLXattrib(GLX_CONTEXT_FLAGS_ARB, flags);
|
setGLXattrib(GLX_CONTEXT_FLAGS_ARB, flags);
|
||||||
|
|
||||||
if (strategy)
|
|
||||||
setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, strategy);
|
|
||||||
|
|
||||||
setGLXattrib(None, None);
|
setGLXattrib(None, None);
|
||||||
|
|
||||||
window->glx.context =
|
window->glx.context =
|
||||||
@@ -429,12 +450,12 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
True,
|
True,
|
||||||
attribs);
|
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->glx.context)
|
if (!window->glx.context)
|
||||||
{
|
{
|
||||||
// HACK: This is a fallback for the broken Mesa implementation of
|
|
||||||
// GLX_ARB_create_context_profile, which fails default 1.0
|
|
||||||
// context creation with a GLXBadProfileARB error in violation
|
|
||||||
// of the extension spec
|
|
||||||
if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&
|
if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&
|
||||||
ctxconfig->api == GLFW_OPENGL_API &&
|
ctxconfig->api == GLFW_OPENGL_API &&
|
||||||
ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&
|
ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&
|
||||||
@@ -472,7 +493,7 @@ void _glfwDestroyContext(_GLFWwindow* window)
|
|||||||
|
|
||||||
if (window->glx.context)
|
if (window->glx.context)
|
||||||
{
|
{
|
||||||
glXDestroyContext(_glfw.x11.display, window->glx.context);
|
_glfw_glXDestroyContext(_glfw.x11.display, window->glx.context);
|
||||||
window->glx.context = NULL;
|
window->glx.context = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -486,19 +507,19 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
if (window)
|
if (window)
|
||||||
{
|
{
|
||||||
glXMakeCurrent(_glfw.x11.display,
|
_glfw_glXMakeCurrent(_glfw.x11.display,
|
||||||
window->x11.handle,
|
window->x11.handle,
|
||||||
window->glx.context);
|
window->glx.context);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
glXMakeCurrent(_glfw.x11.display, None, NULL);
|
_glfw_glXMakeCurrent(_glfw.x11.display, None, NULL);
|
||||||
|
|
||||||
_glfwSetCurrentContext(window);
|
_glfwSetContextTLS(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
|
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
glXSwapBuffers(_glfw.x11.display, window->x11.handle);
|
_glfw_glXSwapBuffers(_glfw.x11.display, window->x11.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSwapInterval(int interval)
|
void _glfwPlatformSwapInterval(int interval)
|
||||||
@@ -522,12 +543,9 @@ void _glfwPlatformSwapInterval(int interval)
|
|||||||
|
|
||||||
int _glfwPlatformExtensionSupported(const char* extension)
|
int _glfwPlatformExtensionSupported(const char* extension)
|
||||||
{
|
{
|
||||||
const GLubyte* extensions;
|
const char* extensions =
|
||||||
|
_glfw_glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen);
|
||||||
// Get list of GLX extensions
|
if (extensions)
|
||||||
extensions = (const GLubyte*) glXQueryExtensionsString(_glfw.x11.display,
|
|
||||||
_glfw.x11.screen);
|
|
||||||
if (extensions != NULL)
|
|
||||||
{
|
{
|
||||||
if (_glfwStringInExtensionString(extension, extensions))
|
if (_glfwStringInExtensionString(extension, extensions))
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
@@ -538,7 +556,12 @@ int _glfwPlatformExtensionSupported(const char* extension)
|
|||||||
|
|
||||||
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
|
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
|
||||||
{
|
{
|
||||||
return _glfw_glXGetProcAddress((const GLubyte*) 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+45
-30
@@ -25,8 +25,8 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _glx_context_h_
|
#ifndef _glfw3_glx_context_h_
|
||||||
#define _glx_context_h_
|
#define _glfw3_glx_context_h_
|
||||||
|
|
||||||
#define GLX_GLXEXT_LEGACY
|
#define GLX_GLXEXT_LEGACY
|
||||||
#include <GL/glx.h>
|
#include <GL/glx.h>
|
||||||
@@ -34,28 +34,29 @@
|
|||||||
// This path may need to be changed if you build GLFW using your own setup
|
// This path may need to be changed if you build GLFW using your own setup
|
||||||
// We ship and use our own copy of glxext.h since GLFW uses fairly new
|
// We ship and use our own copy of glxext.h since GLFW uses fairly new
|
||||||
// extensions and not all operating systems come with an up-to-date version
|
// extensions and not all operating systems come with an up-to-date version
|
||||||
|
#define GLX_GLXEXT_PROTOTYPES
|
||||||
#include "../deps/GL/glxext.h"
|
#include "../deps/GL/glxext.h"
|
||||||
|
|
||||||
// Do we have support for dlopen/dlsym?
|
// libGL.so function pointer typedefs
|
||||||
#if defined(_GLFW_HAS_DLOPEN)
|
typedef int (*PFNGLXGETFBCONFIGATTRIBPROC)(Display*,GLXFBConfig,int,int*);
|
||||||
#include <dlfcn.h>
|
typedef const char* (*PFNGLXGETCLIENTSTRINGPROC)(Display*,int);
|
||||||
#endif
|
typedef Bool (*PFNGLXQUERYEXTENSIONPROC)(Display*,int*,int*);
|
||||||
|
typedef Bool (*PFNGLXQUERYVERSIONPROC)(Display*,int*,int*);
|
||||||
// We support four different ways for getting addresses for GL/GLX
|
typedef void (*PFNGLXDESTROYCONTEXTPROC)(Display*,GLXContext);
|
||||||
// extension functions: glXGetProcAddress, glXGetProcAddressARB,
|
typedef Bool (*PFNGLXMAKECURRENTPROC)(Display*,GLXDrawable,GLXContext);
|
||||||
// glXGetProcAddressEXT, and dlsym
|
typedef void (*PFNGLXSWAPBUFFERSPROC)(Display*,GLXDrawable);
|
||||||
#if defined(_GLFW_HAS_GLXGETPROCADDRESSARB)
|
typedef const char* (*PFNGLXQUERYEXTENSIONSSTRINGPROC)(Display*,int);
|
||||||
#define _glfw_glXGetProcAddress(x) glXGetProcAddressARB(x)
|
#define _glfw_glXGetFBConfigs _glfw.glx.GetFBConfigs
|
||||||
#elif defined(_GLFW_HAS_GLXGETPROCADDRESS)
|
#define _glfw_glXGetFBConfigAttrib _glfw.glx.GetFBConfigAttrib
|
||||||
#define _glfw_glXGetProcAddress(x) glXGetProcAddress(x)
|
#define _glfw_glXGetClientString _glfw.glx.GetClientString
|
||||||
#elif defined(_GLFW_HAS_GLXGETPROCADDRESSEXT)
|
#define _glfw_glXQueryExtension _glfw.glx.QueryExtension
|
||||||
#define _glfw_glXGetProcAddress(x) glXGetProcAddressEXT(x)
|
#define _glfw_glXQueryVersion _glfw.glx.QueryVersion
|
||||||
#elif defined(_GLFW_HAS_DLOPEN)
|
#define _glfw_glXDestroyContext _glfw.glx.DestroyContext
|
||||||
#define _glfw_glXGetProcAddress(x) dlsym(_glfw.glx.libGL, x)
|
#define _glfw_glXMakeCurrent _glfw.glx.MakeCurrent
|
||||||
#define _GLFW_DLOPEN_LIBGL
|
#define _glfw_glXSwapBuffers _glfw.glx.SwapBuffers
|
||||||
#else
|
#define _glfw_glXQueryExtensionsString _glfw.glx.QueryExtensionsString
|
||||||
#error "No OpenGL entry point retrieval mechanism was enabled"
|
#define _glfw_glXCreateNewContext _glfw.glx.CreateNewContext
|
||||||
#endif
|
#define _glfw_glXGetVisualFromFBConfig _glfw.glx.GetVisualFromFBConfig
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_FBCONFIG GLXFBConfig glx
|
#define _GLFW_PLATFORM_FBCONFIG GLXFBConfig glx
|
||||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX glx
|
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX glx
|
||||||
@@ -82,11 +83,29 @@ typedef struct _GLFWcontextGLX
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWlibraryGLX
|
typedef struct _GLFWlibraryGLX
|
||||||
{
|
{
|
||||||
int versionMajor, versionMinor;
|
int major, minor;
|
||||||
int eventBase;
|
int eventBase;
|
||||||
int errorBase;
|
int errorBase;
|
||||||
|
|
||||||
// GLX extensions
|
// 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;
|
||||||
|
|
||||||
|
// GLX 1.4 and extension functions
|
||||||
|
PFNGLXGETPROCADDRESSPROC GetProcAddress;
|
||||||
|
PFNGLXGETPROCADDRESSPROC GetProcAddressARB;
|
||||||
PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI;
|
PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI;
|
||||||
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
|
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
|
||||||
PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
|
PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
|
||||||
@@ -96,17 +115,13 @@ typedef struct _GLFWlibraryGLX
|
|||||||
GLboolean MESA_swap_control;
|
GLboolean MESA_swap_control;
|
||||||
GLboolean ARB_multisample;
|
GLboolean ARB_multisample;
|
||||||
GLboolean ARB_framebuffer_sRGB;
|
GLboolean ARB_framebuffer_sRGB;
|
||||||
|
GLboolean EXT_framebuffer_sRGB;
|
||||||
GLboolean ARB_create_context;
|
GLboolean ARB_create_context;
|
||||||
GLboolean ARB_create_context_profile;
|
GLboolean ARB_create_context_profile;
|
||||||
GLboolean ARB_create_context_robustness;
|
GLboolean ARB_create_context_robustness;
|
||||||
GLboolean EXT_create_context_es2_profile;
|
GLboolean EXT_create_context_es2_profile;
|
||||||
GLboolean ARB_context_flush_control;
|
GLboolean ARB_context_flush_control;
|
||||||
|
|
||||||
#if defined(_GLFW_DLOPEN_LIBGL)
|
|
||||||
// dlopen handle for libGL.so (for glfwGetProcAddress)
|
|
||||||
void* libGL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} _GLFWlibraryGLX;
|
} _GLFWlibraryGLX;
|
||||||
|
|
||||||
|
|
||||||
@@ -117,4 +132,4 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
void _glfwDestroyContext(_GLFWwindow* window);
|
void _glfwDestroyContext(_GLFWwindow* window);
|
||||||
|
|
||||||
#endif // _glx_context_h_
|
#endif // _glfw3_glx_context_h_
|
||||||
|
|||||||
+3
-10
@@ -33,8 +33,8 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|
||||||
// The three global variables below comprise all global data in GLFW, except for
|
// The three global variables below comprise all global data in GLFW.
|
||||||
// various static const translation tables. Any other global variable is a bug.
|
// Any other global variable is a bug.
|
||||||
|
|
||||||
// Global state shared between compilation units of GLFW
|
// Global state shared between compilation units of GLFW
|
||||||
// These are documented in internal.h
|
// These are documented in internal.h
|
||||||
@@ -86,7 +86,7 @@ void _glfwInputError(int error, const char* format, ...)
|
|||||||
{
|
{
|
||||||
if (_glfwErrorCallback)
|
if (_glfwErrorCallback)
|
||||||
{
|
{
|
||||||
char buffer[16384];
|
char buffer[8192];
|
||||||
const char* description;
|
const char* description;
|
||||||
|
|
||||||
if (format)
|
if (format)
|
||||||
@@ -129,13 +129,6 @@ GLFWAPI int glfwInit(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
|
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
|
||||||
if (!_glfw.monitorCount)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "No monitors found");
|
|
||||||
_glfwPlatformTerminate();
|
|
||||||
return GL_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwInitialized = GL_TRUE;
|
_glfwInitialized = GL_TRUE;
|
||||||
|
|
||||||
// Not all window hints have zero as their default value
|
// Not all window hints have zero as their default value
|
||||||
|
|||||||
+2
-2
@@ -55,7 +55,7 @@ static void setCursorMode(_GLFWwindow* window, int newMode)
|
|||||||
|
|
||||||
window->cursorMode = newMode;
|
window->cursorMode = newMode;
|
||||||
|
|
||||||
if (_glfw.focusedWindow == window)
|
if (_glfw.cursorWindow == window)
|
||||||
{
|
{
|
||||||
if (oldMode == GLFW_CURSOR_DISABLED)
|
if (oldMode == GLFW_CURSOR_DISABLED)
|
||||||
{
|
{
|
||||||
@@ -343,7 +343,7 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
|
|||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
if (_glfw.focusedWindow != window)
|
if (_glfw.cursorWindow != window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
|
|||||||
+16
-35
@@ -25,15 +25,15 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _internal_h_
|
#ifndef _glfw3_internal_h_
|
||||||
#define _internal_h_
|
#define _glfw3_internal_h_
|
||||||
|
|
||||||
|
|
||||||
#if defined(_GLFW_USE_CONFIG_H)
|
#if defined(_GLFW_USE_CONFIG_H)
|
||||||
#include "glfw_config.h"
|
#include "glfw_config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define _GLFW_VERSION_NUMBER "3.1.1"
|
#define _GLFW_VERSION_NUMBER "3.1.2"
|
||||||
|
|
||||||
#if defined(GLFW_INCLUDE_GLCOREARB) || \
|
#if defined(GLFW_INCLUDE_GLCOREARB) || \
|
||||||
defined(GLFW_INCLUDE_ES1) || \
|
defined(GLFW_INCLUDE_ES1) || \
|
||||||
@@ -69,6 +69,10 @@
|
|||||||
#include "../deps/GL/glext.h"
|
#include "../deps/GL/glext.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef void (APIENTRY * PFNGLCLEARPROC)(GLbitfield);
|
||||||
|
typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGPROC)(GLenum);
|
||||||
|
typedef void (APIENTRY * PFNGLGETINTEGERVPROC)(GLenum,GLint*);
|
||||||
|
|
||||||
typedef struct _GLFWwndconfig _GLFWwndconfig;
|
typedef struct _GLFWwndconfig _GLFWwndconfig;
|
||||||
typedef struct _GLFWctxconfig _GLFWctxconfig;
|
typedef struct _GLFWctxconfig _GLFWctxconfig;
|
||||||
typedef struct _GLFWfbconfig _GLFWfbconfig;
|
typedef struct _GLFWfbconfig _GLFWfbconfig;
|
||||||
@@ -261,6 +265,9 @@ struct _GLFWwindow
|
|||||||
#if defined(_GLFW_USE_OPENGL)
|
#if defined(_GLFW_USE_OPENGL)
|
||||||
PFNGLGETSTRINGIPROC GetStringi;
|
PFNGLGETSTRINGIPROC GetStringi;
|
||||||
#endif
|
#endif
|
||||||
|
PFNGLGETINTEGERVPROC GetIntegerv;
|
||||||
|
PFNGLGETSTRINGPROC GetString;
|
||||||
|
PFNGLCLEARPROC Clear;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
GLFWwindowposfun pos;
|
GLFWwindowposfun pos;
|
||||||
@@ -323,36 +330,10 @@ struct _GLFWcursor
|
|||||||
struct _GLFWlibrary
|
struct _GLFWlibrary
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
int redBits;
|
_GLFWfbconfig framebuffer;
|
||||||
int greenBits;
|
_GLFWwndconfig window;
|
||||||
int blueBits;
|
_GLFWctxconfig context;
|
||||||
int alphaBits;
|
|
||||||
int depthBits;
|
|
||||||
int stencilBits;
|
|
||||||
int accumRedBits;
|
|
||||||
int accumGreenBits;
|
|
||||||
int accumBlueBits;
|
|
||||||
int accumAlphaBits;
|
|
||||||
int auxBuffers;
|
|
||||||
int stereo;
|
|
||||||
int resizable;
|
|
||||||
int visible;
|
|
||||||
int decorated;
|
|
||||||
int focused;
|
|
||||||
int autoIconify;
|
|
||||||
int floating;
|
|
||||||
int samples;
|
|
||||||
int sRGB;
|
|
||||||
int refreshRate;
|
int refreshRate;
|
||||||
int doublebuffer;
|
|
||||||
int api;
|
|
||||||
int major;
|
|
||||||
int minor;
|
|
||||||
int forward;
|
|
||||||
int debug;
|
|
||||||
int profile;
|
|
||||||
int robustness;
|
|
||||||
int release;
|
|
||||||
} hints;
|
} hints;
|
||||||
|
|
||||||
double cursorPosX, cursorPosY;
|
double cursorPosX, cursorPosY;
|
||||||
@@ -360,7 +341,7 @@ struct _GLFWlibrary
|
|||||||
_GLFWcursor* cursorListHead;
|
_GLFWcursor* cursorListHead;
|
||||||
|
|
||||||
_GLFWwindow* windowListHead;
|
_GLFWwindow* windowListHead;
|
||||||
_GLFWwindow* focusedWindow;
|
_GLFWwindow* cursorWindow;
|
||||||
|
|
||||||
_GLFWmonitor** monitors;
|
_GLFWmonitor** monitors;
|
||||||
int monitorCount;
|
int monitorCount;
|
||||||
@@ -825,7 +806,7 @@ void _glfwSplitBPP(int bpp, int* red, int* green, int* blue);
|
|||||||
* @return `GL_TRUE` if the extension was found, or `GL_FALSE` otherwise.
|
* @return `GL_TRUE` if the extension was found, or `GL_FALSE` otherwise.
|
||||||
* @ingroup utility
|
* @ingroup utility
|
||||||
*/
|
*/
|
||||||
int _glfwStringInExtensionString(const char* string, const GLubyte* extensions);
|
int _glfwStringInExtensionString(const char* string, const char* extensions);
|
||||||
|
|
||||||
/*! @brief Chooses the framebuffer config that best matches the desired one.
|
/*! @brief Chooses the framebuffer config that best matches the desired one.
|
||||||
* @param[in] desired The desired framebuffer config.
|
* @param[in] desired The desired framebuffer config.
|
||||||
@@ -894,4 +875,4 @@ void _glfwFreeMonitor(_GLFWmonitor* monitor);
|
|||||||
*/
|
*/
|
||||||
void _glfwFreeMonitors(_GLFWmonitor** monitors, int count);
|
void _glfwFreeMonitors(_GLFWmonitor** monitors, int count);
|
||||||
|
|
||||||
#endif // _internal_h_
|
#endif // _glfw3_internal_h_
|
||||||
|
|||||||
+14
-7
@@ -24,8 +24,8 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _iokit_joystick_h_
|
#ifndef _glfw3_iokit_joystick_h_
|
||||||
#define _iokit_joystick_h_
|
#define _glfw3_iokit_joystick_h_
|
||||||
|
|
||||||
#include <IOKit/IOKitLib.h>
|
#include <IOKit/IOKitLib.h>
|
||||||
#include <IOKit/IOCFPlugIn.h>
|
#include <IOKit/IOCFPlugIn.h>
|
||||||
@@ -33,17 +33,17 @@
|
|||||||
#include <IOKit/hid/IOHIDKeys.h>
|
#include <IOKit/hid/IOHIDKeys.h>
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
|
||||||
_GLFWjoystickIOKit iokit_js[GLFW_JOYSTICK_LAST + 1]
|
_GLFWjoystickIOKit iokit_js
|
||||||
|
|
||||||
|
|
||||||
// IOKit-specific per-joystick data
|
// IOKit-specific per-joystick data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWjoystickIOKit
|
typedef struct _GLFWjoydevice
|
||||||
{
|
{
|
||||||
int present;
|
int present;
|
||||||
char name[256];
|
char name[256];
|
||||||
|
|
||||||
IOHIDDeviceInterface** interface;
|
IOHIDDeviceRef deviceRef;
|
||||||
|
|
||||||
CFMutableArrayRef axisElements;
|
CFMutableArrayRef axisElements;
|
||||||
CFMutableArrayRef buttonElements;
|
CFMutableArrayRef buttonElements;
|
||||||
@@ -51,11 +51,18 @@ typedef struct _GLFWjoystickIOKit
|
|||||||
|
|
||||||
float* axes;
|
float* axes;
|
||||||
unsigned char* buttons;
|
unsigned char* buttons;
|
||||||
|
} _GLFWjoydevice;
|
||||||
|
|
||||||
|
// IOKit-specific joystick API data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWjoystickIOKit
|
||||||
|
{
|
||||||
|
_GLFWjoydevice devices[GLFW_JOYSTICK_LAST + 1];
|
||||||
|
|
||||||
|
IOHIDManagerRef managerRef;
|
||||||
} _GLFWjoystickIOKit;
|
} _GLFWjoystickIOKit;
|
||||||
|
|
||||||
|
|
||||||
void _glfwInitJoysticks(void);
|
void _glfwInitJoysticks(void);
|
||||||
void _glfwTerminateJoysticks(void);
|
void _glfwTerminateJoysticks(void);
|
||||||
|
|
||||||
#endif // _iokit_joystick_h_
|
#endif // _glfw3_iokit_joystick_h_
|
||||||
|
|||||||
+222
-221
@@ -42,7 +42,7 @@
|
|||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
IOHIDElementCookie cookie;
|
IOHIDElementRef elementRef;
|
||||||
|
|
||||||
long min;
|
long min;
|
||||||
long max;
|
long max;
|
||||||
@@ -55,25 +55,26 @@ typedef struct
|
|||||||
|
|
||||||
static void getElementsCFArrayHandler(const void* value, void* parameter);
|
static void getElementsCFArrayHandler(const void* value, void* parameter);
|
||||||
|
|
||||||
|
|
||||||
// Adds an element to the specified joystick
|
// Adds an element to the specified joystick
|
||||||
//
|
//
|
||||||
static void addJoystickElement(_GLFWjoystickIOKit* joystick, CFTypeRef elementRef)
|
static void addJoystickElement(_GLFWjoydevice* joystick,
|
||||||
|
IOHIDElementRef elementRef)
|
||||||
{
|
{
|
||||||
long elementType, usagePage, usage;
|
IOHIDElementType elementType;
|
||||||
|
long usagePage, usage;
|
||||||
CFMutableArrayRef elementsArray = NULL;
|
CFMutableArrayRef elementsArray = NULL;
|
||||||
|
|
||||||
CFNumberGetValue(CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementTypeKey)),
|
elementType = IOHIDElementGetType(elementRef);
|
||||||
kCFNumberLongType, &elementType);
|
usagePage = IOHIDElementGetUsagePage(elementRef);
|
||||||
CFNumberGetValue(CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementUsagePageKey)),
|
usage = IOHIDElementGetUsage(elementRef);
|
||||||
kCFNumberLongType, &usagePage);
|
|
||||||
CFNumberGetValue(CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementUsageKey)),
|
|
||||||
kCFNumberLongType, &usage);
|
|
||||||
|
|
||||||
if ((elementType == kIOHIDElementTypeInput_Axis) ||
|
if ((elementType != kIOHIDElementTypeInput_Axis) &&
|
||||||
(elementType == kIOHIDElementTypeInput_Button) ||
|
(elementType != kIOHIDElementTypeInput_Button) &&
|
||||||
(elementType == kIOHIDElementTypeInput_Misc))
|
(elementType != kIOHIDElementTypeInput_Misc))
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (usagePage)
|
switch (usagePage)
|
||||||
{
|
{
|
||||||
case kHIDPage_GenericDesktop:
|
case kHIDPage_GenericDesktop:
|
||||||
@@ -108,36 +109,14 @@ static void addJoystickElement(_GLFWjoystickIOKit* joystick, CFTypeRef elementRe
|
|||||||
|
|
||||||
if (elementsArray)
|
if (elementsArray)
|
||||||
{
|
{
|
||||||
long number;
|
|
||||||
CFTypeRef numberRef;
|
|
||||||
_GLFWjoyelement* element = calloc(1, sizeof(_GLFWjoyelement));
|
_GLFWjoyelement* element = calloc(1, sizeof(_GLFWjoyelement));
|
||||||
|
|
||||||
CFArrayAppendValue(elementsArray, element);
|
CFArrayAppendValue(elementsArray, element);
|
||||||
|
|
||||||
numberRef = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementCookieKey));
|
element->elementRef = elementRef;
|
||||||
if (numberRef && CFNumberGetValue(numberRef, kCFNumberLongType, &number))
|
|
||||||
element->cookie = (IOHIDElementCookie) number;
|
|
||||||
|
|
||||||
numberRef = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementMinKey));
|
element->minReport = IOHIDElementGetLogicalMin(elementRef);
|
||||||
if (numberRef && CFNumberGetValue(numberRef, kCFNumberLongType, &number))
|
element->maxReport = IOHIDElementGetLogicalMax(elementRef);
|
||||||
element->minReport = element->min = number;
|
|
||||||
|
|
||||||
numberRef = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementMaxKey));
|
|
||||||
if (numberRef && CFNumberGetValue(numberRef, kCFNumberLongType, &number))
|
|
||||||
element->maxReport = element->max = number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CFTypeRef array = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementKey));
|
|
||||||
if (array)
|
|
||||||
{
|
|
||||||
if (CFGetTypeID(array) == CFArrayGetTypeID())
|
|
||||||
{
|
|
||||||
CFRange range = { 0, CFArrayGetCount(array) };
|
|
||||||
CFArrayApplyFunction(array, range, getElementsCFArrayHandler, joystick);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,40 +124,46 @@ static void addJoystickElement(_GLFWjoystickIOKit* joystick, CFTypeRef elementRe
|
|||||||
//
|
//
|
||||||
static void getElementsCFArrayHandler(const void* value, void* parameter)
|
static void getElementsCFArrayHandler(const void* value, void* parameter)
|
||||||
{
|
{
|
||||||
if (CFGetTypeID(value) == CFDictionaryGetTypeID())
|
if (CFGetTypeID(value) == IOHIDElementGetTypeID())
|
||||||
addJoystickElement((_GLFWjoystickIOKit*) parameter, (CFTypeRef) value);
|
{
|
||||||
|
addJoystickElement((_GLFWjoydevice*) parameter,
|
||||||
|
(IOHIDElementRef) value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the value of the specified element of the specified joystick
|
// Returns the value of the specified element of the specified joystick
|
||||||
//
|
//
|
||||||
static long getElementValue(_GLFWjoystickIOKit* joystick, _GLFWjoyelement* element)
|
static long getElementValue(_GLFWjoydevice* joystick, _GLFWjoyelement* element)
|
||||||
{
|
{
|
||||||
IOReturn result = kIOReturnSuccess;
|
IOReturn result = kIOReturnSuccess;
|
||||||
IOHIDEventStruct hidEvent;
|
IOHIDValueRef valueRef;
|
||||||
hidEvent.value = 0;
|
long value = 0;
|
||||||
|
|
||||||
if (joystick && element && joystick->interface)
|
if (joystick && element && joystick->deviceRef)
|
||||||
{
|
{
|
||||||
result = (*(joystick->interface))->getElementValue(joystick->interface,
|
result = IOHIDDeviceGetValue(joystick->deviceRef,
|
||||||
element->cookie,
|
element->elementRef,
|
||||||
&hidEvent);
|
&valueRef);
|
||||||
|
|
||||||
if (kIOReturnSuccess == result)
|
if (kIOReturnSuccess == result)
|
||||||
{
|
{
|
||||||
|
value = IOHIDValueGetIntegerValue(valueRef);
|
||||||
|
|
||||||
// Record min and max for auto calibration
|
// Record min and max for auto calibration
|
||||||
if (hidEvent.value < element->minReport)
|
if (value < element->minReport)
|
||||||
element->minReport = hidEvent.value;
|
element->minReport = value;
|
||||||
if (hidEvent.value > element->maxReport)
|
if (value > element->maxReport)
|
||||||
element->maxReport = hidEvent.value;
|
element->maxReport = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auto user scale
|
// Auto user scale
|
||||||
return (long) hidEvent.value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes the specified joystick
|
// Removes the specified joystick
|
||||||
//
|
//
|
||||||
static void removeJoystick(_GLFWjoystickIOKit* joystick)
|
static void removeJoystick(_GLFWjoydevice* joystick)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -188,29 +173,22 @@ static void removeJoystick(_GLFWjoystickIOKit* joystick)
|
|||||||
for (i = 0; i < CFArrayGetCount(joystick->axisElements); i++)
|
for (i = 0; i < CFArrayGetCount(joystick->axisElements); i++)
|
||||||
free((void*) CFArrayGetValueAtIndex(joystick->axisElements, i));
|
free((void*) CFArrayGetValueAtIndex(joystick->axisElements, i));
|
||||||
CFArrayRemoveAllValues(joystick->axisElements);
|
CFArrayRemoveAllValues(joystick->axisElements);
|
||||||
|
CFRelease(joystick->axisElements);
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(joystick->buttonElements); i++)
|
for (i = 0; i < CFArrayGetCount(joystick->buttonElements); i++)
|
||||||
free((void*) CFArrayGetValueAtIndex(joystick->buttonElements, i));
|
free((void*) CFArrayGetValueAtIndex(joystick->buttonElements, i));
|
||||||
CFArrayRemoveAllValues(joystick->buttonElements);
|
CFArrayRemoveAllValues(joystick->buttonElements);
|
||||||
|
CFRelease(joystick->buttonElements);
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(joystick->hatElements); i++)
|
for (i = 0; i < CFArrayGetCount(joystick->hatElements); i++)
|
||||||
free((void*) CFArrayGetValueAtIndex(joystick->hatElements, i));
|
free((void*) CFArrayGetValueAtIndex(joystick->hatElements, i));
|
||||||
CFArrayRemoveAllValues(joystick->hatElements);
|
CFArrayRemoveAllValues(joystick->hatElements);
|
||||||
|
CFRelease(joystick->hatElements);
|
||||||
|
|
||||||
free(joystick->axes);
|
free(joystick->axes);
|
||||||
free(joystick->buttons);
|
free(joystick->buttons);
|
||||||
|
|
||||||
(*(joystick->interface))->close(joystick->interface);
|
memset(joystick, 0, sizeof(_GLFWjoydevice));
|
||||||
(*(joystick->interface))->Release(joystick->interface);
|
|
||||||
|
|
||||||
memset(joystick, 0, sizeof(_GLFWjoystickIOKit));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Callback for user-initiated joystick removal
|
|
||||||
//
|
|
||||||
static void removalCallback(void* target, IOReturn result, void* refcon, void* sender)
|
|
||||||
{
|
|
||||||
removeJoystick((_GLFWjoystickIOKit*) refcon);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Polls for joystick events and updates GLFW state
|
// Polls for joystick events and updates GLFW state
|
||||||
@@ -223,15 +201,15 @@ static void pollJoystickEvents(void)
|
|||||||
{
|
{
|
||||||
CFIndex i;
|
CFIndex i;
|
||||||
int buttonIndex = 0;
|
int buttonIndex = 0;
|
||||||
_GLFWjoystickIOKit* joystick = _glfw.iokit_js + joy;
|
_GLFWjoydevice* joystick = _glfw.iokit_js.devices + joy;
|
||||||
|
|
||||||
if (!joystick->present)
|
if (!joystick->present)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(joystick->buttonElements); i++)
|
for (i = 0; i < CFArrayGetCount(joystick->buttonElements); i++)
|
||||||
{
|
{
|
||||||
_GLFWjoyelement* button =
|
_GLFWjoyelement* button = (_GLFWjoyelement*)
|
||||||
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->buttonElements, i);
|
CFArrayGetValueAtIndex(joystick->buttonElements, i);
|
||||||
|
|
||||||
if (getElementValue(joystick, button))
|
if (getElementValue(joystick, button))
|
||||||
joystick->buttons[buttonIndex++] = GLFW_PRESS;
|
joystick->buttons[buttonIndex++] = GLFW_PRESS;
|
||||||
@@ -241,8 +219,8 @@ static void pollJoystickEvents(void)
|
|||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(joystick->axisElements); i++)
|
for (i = 0; i < CFArrayGetCount(joystick->axisElements); i++)
|
||||||
{
|
{
|
||||||
_GLFWjoyelement* axis =
|
_GLFWjoyelement* axis = (_GLFWjoyelement*)
|
||||||
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->axisElements, i);
|
CFArrayGetValueAtIndex(joystick->axisElements, i);
|
||||||
|
|
||||||
long value = getElementValue(joystick, axis);
|
long value = getElementValue(joystick, axis);
|
||||||
long readScale = axis->maxReport - axis->minReport;
|
long readScale = axis->maxReport - axis->minReport;
|
||||||
@@ -255,8 +233,8 @@ static void pollJoystickEvents(void)
|
|||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(joystick->hatElements); i++)
|
for (i = 0; i < CFArrayGetCount(joystick->hatElements); i++)
|
||||||
{
|
{
|
||||||
_GLFWjoyelement* hat =
|
_GLFWjoyelement* hat = (_GLFWjoyelement*)
|
||||||
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->hatElements, i);
|
CFArrayGetValueAtIndex(joystick->hatElements, i);
|
||||||
|
|
||||||
// Bit fields of button presses for each direction, including nil
|
// Bit fields of button presses for each direction, including nil
|
||||||
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
||||||
@@ -276,6 +254,129 @@ static void pollJoystickEvents(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Callback for user-initiated joystick addition
|
||||||
|
//
|
||||||
|
static void matchCallback(void* context,
|
||||||
|
IOReturn result,
|
||||||
|
void* sender,
|
||||||
|
IOHIDDeviceRef deviceRef)
|
||||||
|
{
|
||||||
|
_GLFWjoydevice* joystick;
|
||||||
|
int joy;
|
||||||
|
|
||||||
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
|
{
|
||||||
|
joystick = _glfw.iokit_js.devices + joy;
|
||||||
|
|
||||||
|
if (!joystick->present)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (joystick->deviceRef == deviceRef)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
|
{
|
||||||
|
joystick = _glfw.iokit_js.devices + joy;
|
||||||
|
|
||||||
|
if (!joystick->present)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (joy > GLFW_JOYSTICK_LAST)
|
||||||
|
return;
|
||||||
|
|
||||||
|
joystick->present = GL_TRUE;
|
||||||
|
joystick->deviceRef = deviceRef;
|
||||||
|
|
||||||
|
CFStringRef name = IOHIDDeviceGetProperty(deviceRef,
|
||||||
|
CFSTR(kIOHIDProductKey));
|
||||||
|
CFStringGetCString(name,
|
||||||
|
joystick->name,
|
||||||
|
sizeof(joystick->name),
|
||||||
|
kCFStringEncodingUTF8);
|
||||||
|
|
||||||
|
joystick->axisElements = CFArrayCreateMutable(NULL, 0, NULL);
|
||||||
|
joystick->buttonElements = CFArrayCreateMutable(NULL, 0, NULL);
|
||||||
|
joystick->hatElements = CFArrayCreateMutable(NULL, 0, NULL);
|
||||||
|
|
||||||
|
CFArrayRef arrayRef = IOHIDDeviceCopyMatchingElements(deviceRef,
|
||||||
|
NULL,
|
||||||
|
kIOHIDOptionsTypeNone);
|
||||||
|
CFRange range = { 0, CFArrayGetCount(arrayRef) };
|
||||||
|
CFArrayApplyFunction(arrayRef,
|
||||||
|
range,
|
||||||
|
getElementsCFArrayHandler,
|
||||||
|
(void*) joystick);
|
||||||
|
|
||||||
|
CFRelease(arrayRef);
|
||||||
|
|
||||||
|
joystick->axes = calloc(CFArrayGetCount(joystick->axisElements),
|
||||||
|
sizeof(float));
|
||||||
|
joystick->buttons = calloc(CFArrayGetCount(joystick->buttonElements) +
|
||||||
|
CFArrayGetCount(joystick->hatElements) * 4, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback for user-initiated joystick removal
|
||||||
|
//
|
||||||
|
static void removeCallback(void* context,
|
||||||
|
IOReturn result,
|
||||||
|
void* sender,
|
||||||
|
IOHIDDeviceRef deviceRef)
|
||||||
|
{
|
||||||
|
int joy;
|
||||||
|
|
||||||
|
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
|
{
|
||||||
|
_GLFWjoydevice* joystick = _glfw.iokit_js.devices + joy;
|
||||||
|
if (joystick->deviceRef == deviceRef)
|
||||||
|
{
|
||||||
|
removeJoystick(joystick);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a dictionary to match against devices with the specified usage page
|
||||||
|
// and usage
|
||||||
|
//
|
||||||
|
static CFMutableDictionaryRef createMatchingDictionary(long usagePage,
|
||||||
|
long usage)
|
||||||
|
{
|
||||||
|
CFMutableDictionaryRef result =
|
||||||
|
CFDictionaryCreateMutable(kCFAllocatorDefault,
|
||||||
|
0,
|
||||||
|
&kCFTypeDictionaryKeyCallBacks,
|
||||||
|
&kCFTypeDictionaryValueCallBacks);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
CFNumberRef pageRef = CFNumberCreate(kCFAllocatorDefault,
|
||||||
|
kCFNumberLongType,
|
||||||
|
&usagePage);
|
||||||
|
if (pageRef)
|
||||||
|
{
|
||||||
|
CFDictionarySetValue(result,
|
||||||
|
CFSTR(kIOHIDDeviceUsagePageKey),
|
||||||
|
pageRef);
|
||||||
|
CFRelease(pageRef);
|
||||||
|
|
||||||
|
CFNumberRef usageRef = CFNumberCreate(kCFAllocatorDefault,
|
||||||
|
kCFNumberLongType,
|
||||||
|
&usage);
|
||||||
|
if (usageRef)
|
||||||
|
{
|
||||||
|
CFDictionarySetValue(result,
|
||||||
|
CFSTR(kIOHIDDeviceUsageKey),
|
||||||
|
usageRef);
|
||||||
|
CFRelease(usageRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
@@ -285,177 +386,77 @@ static void pollJoystickEvents(void)
|
|||||||
//
|
//
|
||||||
void _glfwInitJoysticks(void)
|
void _glfwInitJoysticks(void)
|
||||||
{
|
{
|
||||||
int joy = 0;
|
CFMutableArrayRef matchingCFArrayRef;
|
||||||
IOReturn result = kIOReturnSuccess;
|
|
||||||
mach_port_t masterPort = 0;
|
|
||||||
io_iterator_t objectIterator = 0;
|
|
||||||
CFMutableDictionaryRef hidMatchDictionary = NULL;
|
|
||||||
io_object_t ioHIDDeviceObject = 0;
|
|
||||||
|
|
||||||
result = IOMasterPort(bootstrap_port, &masterPort);
|
_glfw.iokit_js.managerRef = IOHIDManagerCreate(kCFAllocatorDefault,
|
||||||
hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey);
|
kIOHIDOptionsTypeNone);
|
||||||
if (kIOReturnSuccess != result || !hidMatchDictionary)
|
|
||||||
|
matchingCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault,
|
||||||
|
0,
|
||||||
|
&kCFTypeArrayCallBacks);
|
||||||
|
if (matchingCFArrayRef)
|
||||||
{
|
{
|
||||||
if (hidMatchDictionary)
|
CFDictionaryRef matchingCFDictRef =
|
||||||
CFRelease(hidMatchDictionary);
|
createMatchingDictionary(kHIDPage_GenericDesktop,
|
||||||
|
kHIDUsage_GD_Joystick);
|
||||||
return;
|
if (matchingCFDictRef)
|
||||||
|
{
|
||||||
|
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
|
||||||
|
CFRelease(matchingCFDictRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = IOServiceGetMatchingServices(masterPort,
|
matchingCFDictRef = createMatchingDictionary(kHIDPage_GenericDesktop,
|
||||||
hidMatchDictionary,
|
kHIDUsage_GD_GamePad);
|
||||||
&objectIterator);
|
if (matchingCFDictRef)
|
||||||
if (result != kIOReturnSuccess)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!objectIterator)
|
|
||||||
{
|
{
|
||||||
// There are no joysticks
|
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
|
||||||
return;
|
CFRelease(matchingCFDictRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((ioHIDDeviceObject = IOIteratorNext(objectIterator)))
|
matchingCFDictRef =
|
||||||
|
createMatchingDictionary(kHIDPage_GenericDesktop,
|
||||||
|
kHIDUsage_GD_MultiAxisController);
|
||||||
|
if (matchingCFDictRef)
|
||||||
{
|
{
|
||||||
CFMutableDictionaryRef propsRef = NULL;
|
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
|
||||||
CFTypeRef valueRef = NULL;
|
CFRelease(matchingCFDictRef);
|
||||||
kern_return_t result;
|
|
||||||
|
|
||||||
IOCFPlugInInterface** ppPlugInInterface = NULL;
|
|
||||||
HRESULT plugInResult = S_OK;
|
|
||||||
SInt32 score = 0;
|
|
||||||
|
|
||||||
long usagePage = 0;
|
|
||||||
long usage = 0;
|
|
||||||
|
|
||||||
valueRef = IORegistryEntryCreateCFProperty(ioHIDDeviceObject,
|
|
||||||
CFSTR(kIOHIDPrimaryUsagePageKey),
|
|
||||||
kCFAllocatorDefault, kNilOptions);
|
|
||||||
if (valueRef)
|
|
||||||
{
|
|
||||||
CFNumberGetValue(valueRef, kCFNumberLongType, &usagePage);
|
|
||||||
CFRelease(valueRef);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
valueRef = IORegistryEntryCreateCFProperty(ioHIDDeviceObject,
|
IOHIDManagerSetDeviceMatchingMultiple(_glfw.iokit_js.managerRef,
|
||||||
CFSTR(kIOHIDPrimaryUsageKey),
|
matchingCFArrayRef);
|
||||||
kCFAllocatorDefault, kNilOptions);
|
CFRelease(matchingCFArrayRef);
|
||||||
if (valueRef)
|
|
||||||
{
|
|
||||||
CFNumberGetValue(valueRef, kCFNumberLongType, &usage);
|
|
||||||
CFRelease(valueRef);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usagePage != kHIDPage_GenericDesktop)
|
IOHIDManagerRegisterDeviceMatchingCallback(_glfw.iokit_js.managerRef,
|
||||||
{
|
&matchCallback, NULL);
|
||||||
// This device is not relevant to GLFW
|
IOHIDManagerRegisterDeviceRemovalCallback(_glfw.iokit_js.managerRef,
|
||||||
continue;
|
&removeCallback, NULL);
|
||||||
}
|
|
||||||
|
|
||||||
if ((usage != kHIDUsage_GD_Joystick &&
|
IOHIDManagerScheduleWithRunLoop(_glfw.iokit_js.managerRef,
|
||||||
usage != kHIDUsage_GD_GamePad &&
|
CFRunLoopGetMain(),
|
||||||
usage != kHIDUsage_GD_MultiAxisController))
|
kCFRunLoopDefaultMode);
|
||||||
{
|
|
||||||
// This device is not relevant to GLFW
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = IORegistryEntryCreateCFProperties(ioHIDDeviceObject,
|
IOHIDManagerOpen(_glfw.iokit_js.managerRef, kIOHIDOptionsTypeNone);
|
||||||
&propsRef,
|
|
||||||
kCFAllocatorDefault,
|
|
||||||
kNilOptions);
|
|
||||||
|
|
||||||
if (result != kIOReturnSuccess)
|
// Execute the run loop once in order to register any initially-attached
|
||||||
continue;
|
// joysticks
|
||||||
|
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false);
|
||||||
_GLFWjoystickIOKit* joystick = _glfw.iokit_js + joy;
|
|
||||||
joystick->present = GL_TRUE;
|
|
||||||
|
|
||||||
result = IOCreatePlugInInterfaceForService(ioHIDDeviceObject,
|
|
||||||
kIOHIDDeviceUserClientTypeID,
|
|
||||||
kIOCFPlugInInterfaceID,
|
|
||||||
&ppPlugInInterface,
|
|
||||||
&score);
|
|
||||||
|
|
||||||
if (kIOReturnSuccess != result)
|
|
||||||
{
|
|
||||||
CFRelease(propsRef);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
plugInResult = (*ppPlugInInterface)->QueryInterface(
|
|
||||||
ppPlugInInterface,
|
|
||||||
CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID),
|
|
||||||
(void *) &(joystick->interface));
|
|
||||||
|
|
||||||
if (plugInResult != S_OK)
|
|
||||||
{
|
|
||||||
CFRelease(propsRef);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*ppPlugInInterface)->Release(ppPlugInInterface);
|
|
||||||
|
|
||||||
(*(joystick->interface))->open(joystick->interface, 0);
|
|
||||||
(*(joystick->interface))->setRemovalCallback(joystick->interface,
|
|
||||||
removalCallback,
|
|
||||||
joystick,
|
|
||||||
joystick);
|
|
||||||
|
|
||||||
// Get product string
|
|
||||||
valueRef = CFDictionaryGetValue(propsRef, CFSTR(kIOHIDProductKey));
|
|
||||||
if (valueRef)
|
|
||||||
{
|
|
||||||
CFStringGetCString(valueRef,
|
|
||||||
joystick->name,
|
|
||||||
sizeof(joystick->name),
|
|
||||||
kCFStringEncodingUTF8);
|
|
||||||
}
|
|
||||||
|
|
||||||
joystick->axisElements = CFArrayCreateMutable(NULL, 0, NULL);
|
|
||||||
joystick->buttonElements = CFArrayCreateMutable(NULL, 0, NULL);
|
|
||||||
joystick->hatElements = CFArrayCreateMutable(NULL, 0, NULL);
|
|
||||||
|
|
||||||
valueRef = CFDictionaryGetValue(propsRef, CFSTR(kIOHIDElementKey));
|
|
||||||
if (CFGetTypeID(valueRef) == CFArrayGetTypeID())
|
|
||||||
{
|
|
||||||
CFRange range = { 0, CFArrayGetCount(valueRef) };
|
|
||||||
CFArrayApplyFunction(valueRef,
|
|
||||||
range,
|
|
||||||
getElementsCFArrayHandler,
|
|
||||||
(void*) joystick);
|
|
||||||
}
|
|
||||||
|
|
||||||
CFRelease(propsRef);
|
|
||||||
|
|
||||||
joystick->axes = calloc(CFArrayGetCount(joystick->axisElements),
|
|
||||||
sizeof(float));
|
|
||||||
joystick->buttons = calloc(CFArrayGetCount(joystick->buttonElements) +
|
|
||||||
CFArrayGetCount(joystick->hatElements) * 4, 1);
|
|
||||||
|
|
||||||
joy++;
|
|
||||||
if (joy > GLFW_JOYSTICK_LAST)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close all opened joystick handles
|
// Close all opened joystick handles
|
||||||
//
|
//
|
||||||
void _glfwTerminateJoysticks(void)
|
void _glfwTerminateJoysticks(void)
|
||||||
{
|
{
|
||||||
int i;
|
int joy;
|
||||||
|
|
||||||
for (i = 0; i < GLFW_JOYSTICK_LAST + 1; i++)
|
for (joy = 0; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||||
{
|
{
|
||||||
_GLFWjoystickIOKit* joystick = &_glfw.iokit_js[i];
|
_GLFWjoydevice* joystick = _glfw.iokit_js.devices + joy;
|
||||||
removeJoystick(joystick);
|
removeJoystick(joystick);
|
||||||
|
|
||||||
if (joystick->axisElements)
|
|
||||||
CFRelease(joystick->axisElements);
|
|
||||||
if (joystick->buttonElements)
|
|
||||||
CFRelease(joystick->buttonElements);
|
|
||||||
if (joystick->hatElements)
|
|
||||||
CFRelease(joystick->hatElements);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CFRelease(_glfw.iokit_js.managerRef);
|
||||||
|
_glfw.iokit_js.managerRef = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -467,12 +468,12 @@ int _glfwPlatformJoystickPresent(int joy)
|
|||||||
{
|
{
|
||||||
pollJoystickEvents();
|
pollJoystickEvents();
|
||||||
|
|
||||||
return _glfw.iokit_js[joy].present;
|
return _glfw.iokit_js.devices[joy].present;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||||
{
|
{
|
||||||
_GLFWjoystickIOKit* joystick = _glfw.iokit_js + joy;
|
_GLFWjoydevice* joystick = _glfw.iokit_js.devices + joy;
|
||||||
|
|
||||||
pollJoystickEvents();
|
pollJoystickEvents();
|
||||||
|
|
||||||
@@ -485,7 +486,7 @@ const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
|||||||
|
|
||||||
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||||
{
|
{
|
||||||
_GLFWjoystickIOKit* joystick = _glfw.iokit_js + joy;
|
_GLFWjoydevice* joystick = _glfw.iokit_js.devices + joy;
|
||||||
|
|
||||||
pollJoystickEvents();
|
pollJoystickEvents();
|
||||||
|
|
||||||
@@ -501,6 +502,6 @@ const char* _glfwPlatformGetJoystickName(int joy)
|
|||||||
{
|
{
|
||||||
pollJoystickEvents();
|
pollJoystickEvents();
|
||||||
|
|
||||||
return _glfw.iokit_js[joy].name;
|
return _glfw.iokit_js.devices[joy].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _linux_joystick_h_
|
#ifndef _glfw3_linux_joystick_h_
|
||||||
#define _linux_joystick_h_
|
#define _glfw3_linux_joystick_h_
|
||||||
|
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
|
|
||||||
@@ -60,4 +60,4 @@ typedef struct _GLFWjoystickLinux
|
|||||||
int _glfwInitJoysticks(void);
|
int _glfwInitJoysticks(void);
|
||||||
void _glfwTerminateJoysticks(void);
|
void _glfwTerminateJoysticks(void);
|
||||||
|
|
||||||
#endif // _linux_joystick_h_
|
#endif // _glfw3_linux_joystick_h_
|
||||||
|
|||||||
+10
-4
@@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.1 Mir - www.glfw.org
|
// GLFW 3.1 Mir - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
|
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -55,6 +55,9 @@ int _glfwPlatformInit(void)
|
|||||||
if (!_glfwInitContextAPI())
|
if (!_glfwInitContextAPI())
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
|
|
||||||
|
// Need the default conf for when we set a NULL cursor
|
||||||
|
_glfw.mir.default_conf = mir_cursor_configuration_from_name(mir_arrow_cursor_name);
|
||||||
|
|
||||||
_glfwInitTimer();
|
_glfwInitTimer();
|
||||||
_glfwInitJoysticks();
|
_glfwInitJoysticks();
|
||||||
|
|
||||||
@@ -87,15 +90,18 @@ void _glfwPlatformTerminate(void)
|
|||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
{
|
{
|
||||||
const char* version = _GLFW_VERSION_NUMBER " Mir EGL"
|
return _GLFW_VERSION_NUMBER " Mir EGL"
|
||||||
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
|
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
|
||||||
" clock_gettime"
|
" clock_gettime"
|
||||||
|
#else
|
||||||
|
" gettimeofday"
|
||||||
|
#endif
|
||||||
|
#if defined(__linux__)
|
||||||
|
" /dev/js"
|
||||||
#endif
|
#endif
|
||||||
#if defined(_GLFW_BUILD_DLL)
|
#if defined(_GLFW_BUILD_DLL)
|
||||||
" shared"
|
" shared"
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
|
||||||
return version;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+36
-4
@@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.1 Mir - www.glfw.org
|
// GLFW 3.1 Mir - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
|
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -86,6 +86,39 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
|||||||
*ypos = monitor->mir.y;
|
*ypos = monitor->mir.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -106,9 +139,8 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
|||||||
modes[*found].width = out->modes[*found].horizontal_resolution;
|
modes[*found].width = out->modes[*found].horizontal_resolution;
|
||||||
modes[*found].height = out->modes[*found].vertical_resolution;
|
modes[*found].height = out->modes[*found].vertical_resolution;
|
||||||
modes[*found].refreshRate = out->modes[*found].refresh_rate;
|
modes[*found].refreshRate = out->modes[*found].refresh_rate;
|
||||||
modes[*found].redBits = 8;
|
|
||||||
modes[*found].greenBits = 8;
|
FillInRGBBitsFromPixelFormat(&modes[*found], out->output_formats[*found]);
|
||||||
modes[*found].blueBits = 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
+12
-8
@@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.1 Mir - www.glfw.org
|
// GLFW 3.1 Mir - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
|
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,18 +24,18 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _mir_platform_h_
|
#ifndef _glfw3_mir_platform_h_
|
||||||
#define _mir_platform_h_
|
#define _glfw3_mir_platform_h_
|
||||||
|
|
||||||
|
#include <sys/queue.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#include <mir_toolkit/mir_client_library.h>
|
#include <mir_toolkit/mir_client_library.h>
|
||||||
|
|
||||||
#include "posix_tls.h"
|
#include "posix_tls.h"
|
||||||
#include "posix_time.h"
|
#include "posix_time.h"
|
||||||
#include "linux_joystick.h"
|
#include "linux_joystick.h"
|
||||||
|
#include "xkb_unicode.h"
|
||||||
#include <sys/queue.h>
|
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#if defined(_GLFW_EGL)
|
#if defined(_GLFW_EGL)
|
||||||
#include "egl_context.h"
|
#include "egl_context.h"
|
||||||
@@ -51,6 +51,7 @@
|
|||||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir
|
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir
|
||||||
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir
|
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir
|
||||||
|
|
||||||
|
|
||||||
// Mir-specific Event Queue
|
// Mir-specific Event Queue
|
||||||
//
|
//
|
||||||
typedef struct EventQueue
|
typedef struct EventQueue
|
||||||
@@ -88,6 +89,7 @@ typedef struct _GLFWlibraryMir
|
|||||||
{
|
{
|
||||||
MirConnection* connection;
|
MirConnection* connection;
|
||||||
MirEGLNativeDisplayType display;
|
MirEGLNativeDisplayType display;
|
||||||
|
MirCursorConfiguration* default_conf;
|
||||||
EventQueue* event_queue;
|
EventQueue* event_queue;
|
||||||
|
|
||||||
pthread_mutex_t event_mutex;
|
pthread_mutex_t event_mutex;
|
||||||
@@ -101,10 +103,12 @@ typedef struct _GLFWlibraryMir
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWcursorMir
|
typedef struct _GLFWcursorMir
|
||||||
{
|
{
|
||||||
|
MirCursorConfiguration* conf;
|
||||||
|
MirBufferStream* custom_cursor;
|
||||||
} _GLFWcursorMir;
|
} _GLFWcursorMir;
|
||||||
|
|
||||||
|
|
||||||
extern void _glfwInitEventQueue(EventQueue* queue);
|
extern void _glfwInitEventQueue(EventQueue* queue);
|
||||||
extern void _glfwDeleteEventQueue(EventQueue* queue);
|
extern void _glfwDeleteEventQueue(EventQueue* queue);
|
||||||
|
|
||||||
#endif // _mir_platform_h_
|
#endif // _glfw3_mir_platform_h_
|
||||||
|
|||||||
+232
-118
@@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.1 Mir - www.glfw.org
|
// GLFW 3.1 Mir - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
|
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -25,7 +25,6 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "xkb_unicode.h"
|
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -35,13 +34,13 @@
|
|||||||
typedef struct EventNode
|
typedef struct EventNode
|
||||||
{
|
{
|
||||||
TAILQ_ENTRY(EventNode) entries;
|
TAILQ_ENTRY(EventNode) entries;
|
||||||
MirEvent* event;
|
const MirEvent* event;
|
||||||
_GLFWwindow* window;
|
_GLFWwindow* window;
|
||||||
} EventNode;
|
} EventNode;
|
||||||
|
|
||||||
static void deleteNode(EventQueue* queue, EventNode* node)
|
static void deleteNode(EventQueue* queue, EventNode* node)
|
||||||
{
|
{
|
||||||
free(node->event);
|
mir_event_unref(node->event);
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,17 +49,19 @@ static int emptyEventQueue(EventQueue* queue)
|
|||||||
return queue->head.tqh_first == NULL ? GL_TRUE : GL_FALSE;
|
return queue->head.tqh_first == NULL ? GL_TRUE : GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EventNode* newEventNode(MirEvent const* event, _GLFWwindow* context)
|
// 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* new_node = calloc(1, sizeof(EventNode));
|
EventNode* new_node = calloc(1, sizeof(EventNode));
|
||||||
new_node->event = calloc(1, sizeof(MirEvent));
|
new_node->event = mir_event_ref(event);
|
||||||
new_node->window = context;
|
new_node->window = context;
|
||||||
|
|
||||||
memcpy(new_node->event, event, sizeof(MirEvent));
|
|
||||||
return new_node;
|
return new_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void enqueueEvent(MirEvent const* event, _GLFWwindow* context)
|
static void enqueueEvent(const MirEvent* event, _GLFWwindow* context)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&_glfw.mir.event_mutex);
|
pthread_mutex_lock(&_glfw.mir.event_mutex);
|
||||||
|
|
||||||
@@ -88,6 +89,9 @@ static EventNode* dequeueEvent(EventQueue* queue)
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME Soon to be changed upstream mir! So we can use an egl config to figure out
|
||||||
|
the best pixel format!
|
||||||
|
*/
|
||||||
static MirPixelFormat findValidPixelFormat(void)
|
static MirPixelFormat findValidPixelFormat(void)
|
||||||
{
|
{
|
||||||
unsigned int i, validFormats, mirPixelFormats = 32;
|
unsigned int i, validFormats, mirPixelFormats = 32;
|
||||||
@@ -114,13 +118,13 @@ static int mirModToGLFWMod(uint32_t mods)
|
|||||||
{
|
{
|
||||||
int publicMods = 0x0;
|
int publicMods = 0x0;
|
||||||
|
|
||||||
if (mods & mir_key_modifier_alt)
|
if (mods & mir_input_event_modifier_alt)
|
||||||
publicMods |= GLFW_MOD_ALT;
|
publicMods |= GLFW_MOD_ALT;
|
||||||
else if (mods & mir_key_modifier_shift)
|
else if (mods & mir_input_event_modifier_shift)
|
||||||
publicMods |= GLFW_MOD_SHIFT;
|
publicMods |= GLFW_MOD_SHIFT;
|
||||||
else if (mods & mir_key_modifier_ctrl)
|
else if (mods & mir_input_event_modifier_ctrl)
|
||||||
publicMods |= GLFW_MOD_CONTROL;
|
publicMods |= GLFW_MOD_CONTROL;
|
||||||
else if (mods & mir_key_modifier_meta)
|
else if (mods & mir_input_event_modifier_meta)
|
||||||
publicMods |= GLFW_MOD_SUPER;
|
publicMods |= GLFW_MOD_SUPER;
|
||||||
|
|
||||||
return publicMods;
|
return publicMods;
|
||||||
@@ -251,97 +255,93 @@ static int toGLFWKeyCode(uint32_t key)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleKeyEvent(const MirKeyEvent key, _GLFWwindow* window)
|
static void handleKeyEvent(const MirKeyboardEvent* key_event, _GLFWwindow* window)
|
||||||
{
|
{
|
||||||
const int pressed = key.action == mir_key_action_up ? GLFW_RELEASE : GLFW_PRESS;
|
const int action = mir_keyboard_event_action (key_event);
|
||||||
const int mods = mirModToGLFWMod(key.modifiers);
|
const int scan_code = mir_keyboard_event_scan_code(key_event);
|
||||||
const long text = _glfwKeySym2Unicode(key.key_code);
|
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));
|
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
||||||
|
|
||||||
_glfwInputKey(window, toGLFWKeyCode(key.scan_code), key.scan_code, pressed, mods);
|
_glfwInputKey(window, toGLFWKeyCode(scan_code), scan_code, pressed, mods);
|
||||||
|
|
||||||
if (text != -1)
|
if (text != -1)
|
||||||
_glfwInputChar(window, text, mods, plain);
|
_glfwInputChar(window, text, mods, plain);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleMouseButton(_GLFWwindow* window,
|
static void handlePointerButton(_GLFWwindow* window,
|
||||||
int pressed, int mods, MirMotionButton button)
|
int pressed,
|
||||||
|
const MirPointerEvent* pointer_event)
|
||||||
{
|
{
|
||||||
static int lastButton;
|
MirPointerButton button = mir_pointer_event_buttons (pointer_event);
|
||||||
int publicButton;
|
int mods = mir_pointer_event_modifiers(pointer_event);
|
||||||
const int publicMods = mirModToGLFWMod(mods);
|
const int publicMods = mirModToGLFWMod(mods);
|
||||||
|
int publicButton;
|
||||||
|
|
||||||
switch (button)
|
switch (button)
|
||||||
{
|
{
|
||||||
case mir_motion_button_primary:
|
case mir_pointer_button_primary:
|
||||||
publicButton = GLFW_MOUSE_BUTTON_LEFT;
|
publicButton = GLFW_MOUSE_BUTTON_LEFT;
|
||||||
break;
|
break;
|
||||||
case mir_motion_button_secondary:
|
case mir_pointer_button_secondary:
|
||||||
publicButton = GLFW_MOUSE_BUTTON_RIGHT;
|
publicButton = GLFW_MOUSE_BUTTON_RIGHT;
|
||||||
break;
|
break;
|
||||||
case mir_motion_button_tertiary:
|
case mir_pointer_button_tertiary:
|
||||||
publicButton = GLFW_MOUSE_BUTTON_MIDDLE;
|
publicButton = GLFW_MOUSE_BUTTON_MIDDLE;
|
||||||
break;
|
break;
|
||||||
case mir_motion_button_forward:
|
case mir_pointer_button_forward:
|
||||||
// FIXME What is the forward button?
|
// FIXME What is the forward button?
|
||||||
publicButton = GLFW_MOUSE_BUTTON_4;
|
publicButton = GLFW_MOUSE_BUTTON_4;
|
||||||
break;
|
break;
|
||||||
case mir_motion_button_back:
|
case mir_pointer_button_back:
|
||||||
// FIXME What is the back button?
|
// FIXME What is the back button?
|
||||||
publicButton = GLFW_MOUSE_BUTTON_5;
|
publicButton = GLFW_MOUSE_BUTTON_5;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
publicButton = lastButton;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastButton = publicButton;
|
|
||||||
|
|
||||||
_glfwInputMouseClick(window, publicButton, pressed, publicMods);
|
_glfwInputMouseClick(window, publicButton, pressed, publicMods);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleMouseMotion(_GLFWwindow* window, int x, int y)
|
static void handlePointerMotion(_GLFWwindow* window,
|
||||||
|
const MirPointerEvent* pointer_event)
|
||||||
{
|
{
|
||||||
_glfwInputCursorMotion(window, x, y);
|
int current_x = window->cursorPosX;
|
||||||
}
|
int current_y = window->cursorPosY;
|
||||||
|
int x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x);
|
||||||
|
int y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y);
|
||||||
|
int dx = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll);
|
||||||
|
int dy = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll);
|
||||||
|
|
||||||
static void handleMouseScroll(_GLFWwindow* window, int dx, int dy)
|
if (current_x != x || current_y != y)
|
||||||
{
|
_glfwInputCursorMotion(window, x, y);
|
||||||
|
if (dx != 0 || dy != 0)
|
||||||
_glfwInputScroll(window, dx, dy);
|
_glfwInputScroll(window, dx, dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleMouseEvent(const MirMotionEvent motion,
|
static void handlePointerEvent(const MirPointerEvent* pointer_event,
|
||||||
int cord_index,
|
|
||||||
_GLFWwindow* window)
|
_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
switch (motion.action)
|
int action = mir_pointer_event_action(pointer_event);
|
||||||
|
|
||||||
|
switch (action)
|
||||||
{
|
{
|
||||||
case mir_motion_action_down:
|
case mir_pointer_action_button_down:
|
||||||
case mir_motion_action_pointer_down:
|
handlePointerButton(window, GLFW_PRESS, pointer_event);
|
||||||
handleMouseButton(window, GLFW_PRESS,
|
|
||||||
motion.modifiers, motion.button_state);
|
|
||||||
break;
|
break;
|
||||||
case mir_motion_action_up:
|
case mir_pointer_action_button_up:
|
||||||
case mir_motion_action_pointer_up:
|
handlePointerButton(window, GLFW_RELEASE, pointer_event);
|
||||||
handleMouseButton(window, GLFW_RELEASE,
|
|
||||||
motion.modifiers, motion.button_state);
|
|
||||||
break;
|
break;
|
||||||
case mir_motion_action_hover_move:
|
case mir_pointer_action_motion:
|
||||||
case mir_motion_action_move:
|
handlePointerMotion(window, pointer_event);
|
||||||
handleMouseMotion(window,
|
|
||||||
motion.pointer_coordinates[cord_index].x,
|
|
||||||
motion.pointer_coordinates[cord_index].y);
|
|
||||||
break;
|
break;
|
||||||
case mir_motion_action_outside:
|
case mir_pointer_action_enter:
|
||||||
break;
|
case mir_pointer_action_leave:
|
||||||
case mir_motion_action_scroll:
|
|
||||||
handleMouseScroll(window,
|
|
||||||
motion.pointer_coordinates[cord_index].hscroll,
|
|
||||||
motion.pointer_coordinates[cord_index].vscroll);
|
|
||||||
break;
|
|
||||||
case mir_motion_action_cancel:
|
|
||||||
case mir_motion_action_hover_enter:
|
|
||||||
case mir_motion_action_hover_exit:
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -349,61 +349,66 @@ static void handleMouseEvent(const MirMotionEvent motion,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleMotionEvent(const MirMotionEvent motion, _GLFWwindow* window)
|
static void handleInput(const MirInputEvent* input_event, _GLFWwindow* window)
|
||||||
{
|
{
|
||||||
int i;
|
int type = mir_input_event_get_type(input_event);
|
||||||
for (i = 0; i < motion.pointer_count; i++)
|
|
||||||
handleMouseEvent(motion, i, window);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handleInput(MirEvent const* event, _GLFWwindow* window)
|
switch (type)
|
||||||
{
|
|
||||||
switch (event->type)
|
|
||||||
{
|
{
|
||||||
case mir_event_type_key:
|
case mir_input_event_type_key:
|
||||||
handleKeyEvent(event->key, window);
|
handleKeyEvent(mir_input_event_get_keyboard_event(input_event), window);
|
||||||
break;
|
break;
|
||||||
case mir_event_type_motion:
|
case mir_input_event_type_pointer:
|
||||||
handleMotionEvent(event->motion, window);
|
handlePointerEvent(mir_input_event_get_pointer_event(input_event), window);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addNewEvent(MirSurface* surface, MirEvent const* event, void* context)
|
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(MirSurface* surface, const MirEvent* event, void* context)
|
||||||
{
|
{
|
||||||
enqueueEvent(event, context);
|
enqueueEvent(event, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int createSurface(_GLFWwindow* window)
|
static int createSurface(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
MirSurfaceParameters params =
|
MirSurfaceSpec* spec;
|
||||||
{
|
MirBufferUsage buffer_usage = mir_buffer_usage_hardware;
|
||||||
.name = "MirSurface",
|
MirPixelFormat pixel_format = findValidPixelFormat();
|
||||||
.width = window->mir.width,
|
|
||||||
.height = window->mir.height,
|
|
||||||
.pixel_format = mir_pixel_format_invalid,
|
|
||||||
.buffer_usage = mir_buffer_usage_hardware,
|
|
||||||
.output_id = mir_display_output_id_invalid
|
|
||||||
};
|
|
||||||
|
|
||||||
MirEventDelegate delegate =
|
if (pixel_format == mir_pixel_format_invalid)
|
||||||
{
|
|
||||||
addNewEvent,
|
|
||||||
window
|
|
||||||
};
|
|
||||||
|
|
||||||
params.pixel_format = findValidPixelFormat();
|
|
||||||
if (params.pixel_format == mir_pixel_format_invalid)
|
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Mir: Unable to find a correct pixel format");
|
"Mir: Unable to find a correct pixel format");
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
window->mir.surface =
|
spec = mir_connection_create_spec_for_normal_surface(_glfw.mir.connection,
|
||||||
mir_connection_create_surface_sync(_glfw.mir.connection, ¶ms);
|
window->mir.width,
|
||||||
|
window->mir.height,
|
||||||
|
pixel_format);
|
||||||
|
|
||||||
|
mir_surface_spec_set_buffer_usage(spec, buffer_usage);
|
||||||
|
mir_surface_spec_set_name(spec, "MirSurface");
|
||||||
|
|
||||||
|
window->mir.surface = mir_surface_create_sync(spec);
|
||||||
|
mir_surface_spec_release(spec);
|
||||||
|
|
||||||
if (!mir_surface_is_valid(window->mir.surface))
|
if (!mir_surface_is_valid(window->mir.surface))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
@@ -413,7 +418,7 @@ static int createSurface(_GLFWwindow* window)
|
|||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
mir_surface_set_event_handler(window->mir.surface, &delegate);
|
mir_surface_set_event_handler(window->mir.surface, addNewEvent, window);
|
||||||
|
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
@@ -483,7 +488,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
if (!createSurface(window))
|
if (!createSurface(window))
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
|
|
||||||
window->mir.window = mir_surface_get_egl_native_window(window->mir.surface);
|
window->mir.window = mir_buffer_stream_get_egl_native_window(
|
||||||
|
mir_surface_get_buffer_stream(window->mir.surface));
|
||||||
|
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
@@ -501,8 +507,26 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
MirSurfaceSpec* spec;
|
||||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
const char* e_title = title ? title : "";
|
||||||
|
|
||||||
|
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
||||||
|
mir_surface_spec_set_name(spec, e_title);
|
||||||
|
|
||||||
|
mir_surface_apply_spec(window->mir.surface, spec);
|
||||||
|
mir_surface_spec_release(spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||||
|
{
|
||||||
|
MirSurfaceSpec* spec;
|
||||||
|
|
||||||
|
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
||||||
|
mir_surface_spec_set_width (spec, width);
|
||||||
|
mir_surface_spec_set_height(spec, height);
|
||||||
|
|
||||||
|
mir_surface_apply_spec(window->mir.surface, spec);
|
||||||
|
mir_surface_spec_release(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
|
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
|
||||||
@@ -525,12 +549,6 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
|||||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
||||||
{
|
{
|
||||||
if (width)
|
if (width)
|
||||||
@@ -551,14 +569,24 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
MirSurfaceSpec* spec;
|
||||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
|
||||||
|
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
||||||
|
mir_surface_spec_set_state(spec, mir_surface_state_hidden);
|
||||||
|
|
||||||
|
mir_surface_apply_spec(window->mir.surface, spec);
|
||||||
|
mir_surface_spec_release(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
MirSurfaceSpec* spec;
|
||||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
|
||||||
|
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
||||||
|
mir_surface_spec_set_state(spec, mir_surface_state_restored);
|
||||||
|
|
||||||
|
mir_surface_apply_spec(window->mir.surface, spec);
|
||||||
|
mir_surface_spec_release(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
|
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
|
||||||
@@ -583,9 +611,7 @@ int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
|||||||
|
|
||||||
int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
return mir_surface_get_visibility(window->mir.surface) == mir_surface_visibility_exposed;
|
||||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
|
||||||
return GL_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformPollEvents(void)
|
void _glfwPlatformPollEvents(void)
|
||||||
@@ -594,7 +620,7 @@ void _glfwPlatformPollEvents(void)
|
|||||||
|
|
||||||
while ((node = dequeueEvent(_glfw.mir.event_queue)))
|
while ((node = dequeueEvent(_glfw.mir.event_queue)))
|
||||||
{
|
{
|
||||||
handleInput(node->event, node->window);
|
handleEvent(node->event, node->window);
|
||||||
deleteNode(_glfw.mir.event_queue, node);
|
deleteNode(_glfw.mir.event_queue, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -623,34 +649,122 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* heigh
|
|||||||
*height = window->mir.height;
|
*height = window->mir.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME implement
|
||||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||||
const GLFWimage* image,
|
const GLFWimage* image,
|
||||||
int xhot, int yhot)
|
int xhot, int yhot)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
MirBufferStream* stream;
|
||||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
MirPixelFormat pixel_format = findValidPixelFormat();
|
||||||
|
|
||||||
|
int i_w = image->width;
|
||||||
|
int i_h = image->height;
|
||||||
|
|
||||||
|
if (pixel_format == mir_pixel_format_invalid)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Mir: Unable to find a correct pixel format");
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream = mir_connection_create_buffer_stream_sync(_glfw.mir.connection,
|
||||||
|
i_w, i_h,
|
||||||
|
pixel_format,
|
||||||
|
mir_buffer_usage_software);
|
||||||
|
|
||||||
|
cursor->mir.conf = mir_cursor_configuration_from_buffer_stream(stream, xhot, yhot);
|
||||||
|
|
||||||
|
char* dest;
|
||||||
|
unsigned char *pixels;
|
||||||
|
int i, r_stride, bytes_per_pixel, bytes_per_row;
|
||||||
|
|
||||||
|
MirGraphicsRegion region;
|
||||||
|
mir_buffer_stream_get_graphics_region(stream, ®ion);
|
||||||
|
|
||||||
|
// FIXME Figure this out based on the current_pf
|
||||||
|
bytes_per_pixel = 4;
|
||||||
|
bytes_per_row = bytes_per_pixel * i_w;
|
||||||
|
|
||||||
|
dest = region.vaddr;
|
||||||
|
pixels = image->pixels;
|
||||||
|
|
||||||
|
r_stride = region.stride;
|
||||||
|
|
||||||
|
for (i = 0; i < i_h; i++)
|
||||||
|
{
|
||||||
|
memcpy(dest, pixels, bytes_per_row);
|
||||||
|
dest += r_stride;
|
||||||
|
pixels += r_stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor->mir.custom_cursor = stream;
|
||||||
|
|
||||||
|
return GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
const char* cursor_name = getSystemCursorName(shape);
|
||||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
|
||||||
|
if (cursor_name)
|
||||||
|
{
|
||||||
|
cursor->mir.conf = mir_cursor_configuration_from_name(cursor_name);
|
||||||
|
cursor->mir.custom_cursor = NULL;
|
||||||
|
|
||||||
|
return GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
if (cursor->mir.conf)
|
||||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
mir_cursor_configuration_destroy(cursor->mir.conf);
|
||||||
|
if (cursor->mir.custom_cursor)
|
||||||
|
mir_buffer_stream_release_sync(cursor->mir.custom_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
if (cursor && cursor->mir.conf)
|
||||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
{
|
||||||
|
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, cursor->mir.conf));
|
||||||
|
if (cursor->mir.custom_cursor)
|
||||||
|
{
|
||||||
|
/* FIXME Bug https://bugs.launchpad.net/mir/+bug/1477285
|
||||||
|
Requires a triple buffer swap to get the cursor buffer on top! (since mir is tripled buffered)
|
||||||
|
*/
|
||||||
|
mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor);
|
||||||
|
mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor);
|
||||||
|
mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, _glfw.mir.default_conf));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||||
|
|||||||
@@ -305,6 +305,10 @@ GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
|
|||||||
GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void)
|
GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (!_glfw.monitorCount)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return (GLFWmonitor*) _glfw.monitors[0];
|
return (GLFWmonitor*) _glfw.monitors[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -24,8 +24,8 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _nsgl_context_h_
|
#ifndef _glfw3_nsgl_context_h_
|
||||||
#define _nsgl_context_h_
|
#define _glfw3_nsgl_context_h_
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_FBCONFIG
|
#define _GLFW_PLATFORM_FBCONFIG
|
||||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl
|
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl
|
||||||
@@ -59,4 +59,4 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
void _glfwDestroyContext(_GLFWwindow* window);
|
void _glfwDestroyContext(_GLFWwindow* window);
|
||||||
|
|
||||||
#endif // _nsgl_context_h_
|
#endif // _glfw3_nsgl_context_h_
|
||||||
|
|||||||
+7
-7
@@ -35,7 +35,7 @@
|
|||||||
//
|
//
|
||||||
int _glfwInitContextAPI(void)
|
int _glfwInitContextAPI(void)
|
||||||
{
|
{
|
||||||
if (!_glfwInitTLS())
|
if (!_glfwCreateContextTLS())
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
|
|
||||||
_glfw.nsgl.framework =
|
_glfw.nsgl.framework =
|
||||||
@@ -54,7 +54,7 @@ int _glfwInitContextAPI(void)
|
|||||||
//
|
//
|
||||||
void _glfwTerminateContextAPI(void)
|
void _glfwTerminateContextAPI(void)
|
||||||
{
|
{
|
||||||
_glfwTerminateTLS();
|
_glfwDestroyContextTLS();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the OpenGL context
|
// Create the OpenGL context
|
||||||
@@ -67,8 +67,8 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (ctxconfig->api == GLFW_OPENGL_ES_API)
|
if (ctxconfig->api == GLFW_OPENGL_ES_API)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"NSGL: This API does not support OpenGL ES");
|
"NSGL: OpenGL ES is not available on OS X");
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,8 +211,8 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
|
[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
|
||||||
if (window->nsgl.pixelFormat == nil)
|
if (window->nsgl.pixelFormat == nil)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
"NSGL: Failed to create OpenGL pixel format");
|
"NSGL: Failed to find a suitable pixel format");
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +257,7 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
|
|||||||
else
|
else
|
||||||
[NSOpenGLContext clearCurrentContext];
|
[NSOpenGLContext clearCurrentContext];
|
||||||
|
|
||||||
_glfwSetCurrentContext(window);
|
_glfwSetContextTLS(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
|
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
|
||||||
|
|||||||
+3
-3
@@ -25,8 +25,8 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _posix_time_h_
|
#ifndef _glfw3_posix_time_h_
|
||||||
#define _posix_time_h_
|
#define _glfw3_posix_time_h_
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimePOSIX posix_time
|
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimePOSIX posix_time
|
||||||
|
|
||||||
@@ -46,4 +46,4 @@ typedef struct _GLFWtimePOSIX
|
|||||||
|
|
||||||
void _glfwInitTimer(void);
|
void _glfwInitTimer(void);
|
||||||
|
|
||||||
#endif // _posix_time_h_
|
#endif // _glfw3_posix_time_h_
|
||||||
|
|||||||
+3
-3
@@ -32,7 +32,7 @@
|
|||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int _glfwInitTLS(void)
|
int _glfwCreateContextTLS(void)
|
||||||
{
|
{
|
||||||
if (pthread_key_create(&_glfw.posix_tls.context, NULL) != 0)
|
if (pthread_key_create(&_glfw.posix_tls.context, NULL) != 0)
|
||||||
{
|
{
|
||||||
@@ -44,12 +44,12 @@ int _glfwInitTLS(void)
|
|||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwTerminateTLS(void)
|
void _glfwDestroyContextTLS(void)
|
||||||
{
|
{
|
||||||
pthread_key_delete(_glfw.posix_tls.context);
|
pthread_key_delete(_glfw.posix_tls.context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwSetCurrentContext(_GLFWwindow* context)
|
void _glfwSetContextTLS(_GLFWwindow* context)
|
||||||
{
|
{
|
||||||
pthread_setspecific(_glfw.posix_tls.context, context);
|
pthread_setspecific(_glfw.posix_tls.context, context);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -25,8 +25,8 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _posix_tls_h_
|
#ifndef _glfw3_posix_tls_h_
|
||||||
#define _posix_tls_h_
|
#define _glfw3_posix_tls_h_
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
@@ -42,8 +42,8 @@ typedef struct _GLFWtlsPOSIX
|
|||||||
} _GLFWtlsPOSIX;
|
} _GLFWtlsPOSIX;
|
||||||
|
|
||||||
|
|
||||||
int _glfwInitTLS(void);
|
int _glfwCreateContextTLS(void);
|
||||||
void _glfwTerminateTLS(void);
|
void _glfwDestroyContextTLS(void);
|
||||||
void _glfwSetCurrentContext(_GLFWwindow* context);
|
void _glfwSetContextTLS(_GLFWwindow* context);
|
||||||
|
|
||||||
#endif // _posix_tls_h_
|
#endif // _glfw3_posix_tls_h_
|
||||||
|
|||||||
+116
-136
@@ -33,110 +33,67 @@
|
|||||||
|
|
||||||
|
|
||||||
// Initialize WGL-specific extensions
|
// Initialize WGL-specific extensions
|
||||||
// This function is called once before initial context creation, i.e. before
|
|
||||||
// any WGL extensions could be present. This is done in order to have both
|
|
||||||
// extension variable clearing and loading in the same place, hopefully
|
|
||||||
// decreasing the possibility of forgetting to add one without the other.
|
|
||||||
//
|
//
|
||||||
static void initWGLExtensions(_GLFWwindow* window)
|
static void initWGLExtensions(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
// This needs to include every function pointer loaded below
|
// Functions for WGL_EXT_extension_string
|
||||||
window->wgl.SwapIntervalEXT = NULL;
|
// NOTE: These are needed by _glfwPlatformExtensionSupported
|
||||||
window->wgl.GetPixelFormatAttribivARB = NULL;
|
window->wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
|
||||||
window->wgl.GetExtensionsStringARB = NULL;
|
_glfw_wglGetProcAddress("wglGetExtensionsStringEXT");
|
||||||
window->wgl.GetExtensionsStringEXT = NULL;
|
window->wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
|
||||||
window->wgl.CreateContextAttribsARB = NULL;
|
_glfw_wglGetProcAddress("wglGetExtensionsStringARB");
|
||||||
|
|
||||||
|
// Functions for WGL_ARB_create_context
|
||||||
|
window->wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
|
||||||
|
_glfw_wglGetProcAddress("wglCreateContextAttribsARB");
|
||||||
|
|
||||||
|
// Functions for WGL_EXT_swap_control
|
||||||
|
window->wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
|
||||||
|
_glfw_wglGetProcAddress("wglSwapIntervalEXT");
|
||||||
|
|
||||||
|
// Functions for WGL_ARB_pixel_format
|
||||||
|
window->wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
|
||||||
|
_glfw_wglGetProcAddress("wglGetPixelFormatAttribivARB");
|
||||||
|
|
||||||
// This needs to include every extension used below except for
|
// This needs to include every extension used below except for
|
||||||
// WGL_ARB_extensions_string and WGL_EXT_extensions_string
|
// WGL_ARB_extensions_string and WGL_EXT_extensions_string
|
||||||
window->wgl.ARB_multisample = GL_FALSE;
|
window->wgl.ARB_multisample =
|
||||||
window->wgl.ARB_framebuffer_sRGB = GL_FALSE;
|
_glfwPlatformExtensionSupported("WGL_ARB_multisample");
|
||||||
window->wgl.ARB_create_context = GL_FALSE;
|
window->wgl.ARB_framebuffer_sRGB =
|
||||||
window->wgl.ARB_create_context_profile = GL_FALSE;
|
_glfwPlatformExtensionSupported("WGL_ARB_framebuffer_sRGB");
|
||||||
window->wgl.EXT_create_context_es2_profile = GL_FALSE;
|
window->wgl.EXT_framebuffer_sRGB =
|
||||||
window->wgl.ARB_create_context_robustness = GL_FALSE;
|
_glfwPlatformExtensionSupported("WGL_EXT_framebuffer_sRGB");
|
||||||
window->wgl.EXT_swap_control = GL_FALSE;
|
window->wgl.ARB_create_context =
|
||||||
window->wgl.ARB_pixel_format = GL_FALSE;
|
_glfwPlatformExtensionSupported("WGL_ARB_create_context");
|
||||||
window->wgl.ARB_context_flush_control = GL_FALSE;
|
window->wgl.ARB_create_context_profile =
|
||||||
|
_glfwPlatformExtensionSupported("WGL_ARB_create_context_profile");
|
||||||
window->wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
|
window->wgl.EXT_create_context_es2_profile =
|
||||||
wglGetProcAddress("wglGetExtensionsStringEXT");
|
_glfwPlatformExtensionSupported("WGL_EXT_create_context_es2_profile");
|
||||||
if (!window->wgl.GetExtensionsStringEXT)
|
window->wgl.ARB_create_context_robustness =
|
||||||
{
|
_glfwPlatformExtensionSupported("WGL_ARB_create_context_robustness");
|
||||||
window->wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
|
window->wgl.EXT_swap_control =
|
||||||
wglGetProcAddress("wglGetExtensionsStringARB");
|
_glfwPlatformExtensionSupported("WGL_EXT_swap_control");
|
||||||
if (!window->wgl.GetExtensionsStringARB)
|
window->wgl.ARB_pixel_format =
|
||||||
return;
|
_glfwPlatformExtensionSupported("WGL_ARB_pixel_format");
|
||||||
}
|
window->wgl.ARB_context_flush_control =
|
||||||
|
_glfwPlatformExtensionSupported("WGL_ARB_context_flush_control");
|
||||||
if (_glfwPlatformExtensionSupported("WGL_ARB_multisample"))
|
|
||||||
window->wgl.ARB_multisample = GL_TRUE;
|
|
||||||
|
|
||||||
if (_glfwPlatformExtensionSupported("WGL_ARB_framebuffer_sRGB"))
|
|
||||||
window->wgl.ARB_framebuffer_sRGB = GL_TRUE;
|
|
||||||
|
|
||||||
if (_glfwPlatformExtensionSupported("WGL_ARB_create_context"))
|
|
||||||
{
|
|
||||||
window->wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
|
|
||||||
wglGetProcAddress("wglCreateContextAttribsARB");
|
|
||||||
|
|
||||||
if (window->wgl.CreateContextAttribsARB)
|
|
||||||
window->wgl.ARB_create_context = GL_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window->wgl.ARB_create_context)
|
|
||||||
{
|
|
||||||
if (_glfwPlatformExtensionSupported("WGL_ARB_create_context_profile"))
|
|
||||||
window->wgl.ARB_create_context_profile = GL_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window->wgl.ARB_create_context &&
|
|
||||||
window->wgl.ARB_create_context_profile)
|
|
||||||
{
|
|
||||||
if (_glfwPlatformExtensionSupported("WGL_EXT_create_context_es2_profile"))
|
|
||||||
window->wgl.EXT_create_context_es2_profile = GL_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window->wgl.ARB_create_context)
|
|
||||||
{
|
|
||||||
if (_glfwPlatformExtensionSupported("WGL_ARB_create_context_robustness"))
|
|
||||||
window->wgl.ARB_create_context_robustness = GL_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfwPlatformExtensionSupported("WGL_EXT_swap_control"))
|
|
||||||
{
|
|
||||||
window->wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
|
|
||||||
wglGetProcAddress("wglSwapIntervalEXT");
|
|
||||||
|
|
||||||
if (window->wgl.SwapIntervalEXT)
|
|
||||||
window->wgl.EXT_swap_control = GL_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfwPlatformExtensionSupported("WGL_ARB_pixel_format"))
|
|
||||||
{
|
|
||||||
window->wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
|
|
||||||
wglGetProcAddress("wglGetPixelFormatAttribivARB");
|
|
||||||
|
|
||||||
if (window->wgl.GetPixelFormatAttribivARB)
|
|
||||||
window->wgl.ARB_pixel_format = GL_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfwPlatformExtensionSupported("WGL_ARB_context_flush_control"))
|
|
||||||
window->wgl.ARB_context_flush_control = GL_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the specified attribute of the specified pixel format
|
// Returns the specified attribute of the specified pixel format
|
||||||
// NOTE: Do not call this unless we have found WGL_ARB_pixel_format
|
|
||||||
//
|
//
|
||||||
static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib)
|
static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib)
|
||||||
{
|
{
|
||||||
int value = 0;
|
int value = 0;
|
||||||
|
|
||||||
|
assert(window->wgl.ARB_pixel_format);
|
||||||
|
|
||||||
if (!window->wgl.GetPixelFormatAttribivARB(window->wgl.dc,
|
if (!window->wgl.GetPixelFormatAttribivARB(window->wgl.dc,
|
||||||
pixelFormat,
|
pixelFormat,
|
||||||
0, 1, &attrib, &value))
|
0, 1, &attrib, &value))
|
||||||
{
|
{
|
||||||
// NOTE: We should probably handle this error somehow
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to retrieve pixel format attribute %i",
|
||||||
|
attrib);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +134,8 @@ static GLboolean choosePixelFormat(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (window->wgl.ARB_pixel_format)
|
if (window->wgl.ARB_pixel_format)
|
||||||
{
|
{
|
||||||
// Get pixel format attributes through WGL_ARB_pixel_format
|
// Get pixel format attributes through "modern" extension
|
||||||
|
|
||||||
if (!getPixelFormatAttrib(window, n, WGL_SUPPORT_OPENGL_ARB) ||
|
if (!getPixelFormatAttrib(window, n, WGL_SUPPORT_OPENGL_ARB) ||
|
||||||
!getPixelFormatAttrib(window, n, WGL_DRAW_TO_WINDOW_ARB))
|
!getPixelFormatAttrib(window, n, WGL_DRAW_TO_WINDOW_ARB))
|
||||||
{
|
{
|
||||||
@@ -219,7 +177,8 @@ static GLboolean choosePixelFormat(_GLFWwindow* window,
|
|||||||
if (window->wgl.ARB_multisample)
|
if (window->wgl.ARB_multisample)
|
||||||
u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
|
u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
|
||||||
|
|
||||||
if (window->wgl.ARB_framebuffer_sRGB)
|
if (window->wgl.ARB_framebuffer_sRGB ||
|
||||||
|
window->wgl.EXT_framebuffer_sRGB)
|
||||||
{
|
{
|
||||||
if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
|
if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
|
||||||
u->sRGB = GL_TRUE;
|
u->sRGB = GL_TRUE;
|
||||||
@@ -229,7 +188,7 @@ static GLboolean choosePixelFormat(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
PIXELFORMATDESCRIPTOR pfd;
|
PIXELFORMATDESCRIPTOR pfd;
|
||||||
|
|
||||||
// Get pixel format attributes through old-fashioned PFDs
|
// Get pixel format attributes through legacy PFDs
|
||||||
|
|
||||||
if (!DescribePixelFormat(window->wgl.dc,
|
if (!DescribePixelFormat(window->wgl.dc,
|
||||||
n,
|
n,
|
||||||
@@ -291,7 +250,7 @@ static GLboolean choosePixelFormat(_GLFWwindow* window,
|
|||||||
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
|
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
|
||||||
if (!closest)
|
if (!closest)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
"WGL: Failed to find a suitable pixel format");
|
"WGL: Failed to find a suitable pixel format");
|
||||||
|
|
||||||
free(usableConfigs);
|
free(usableConfigs);
|
||||||
@@ -313,7 +272,7 @@ static GLboolean choosePixelFormat(_GLFWwindow* window,
|
|||||||
//
|
//
|
||||||
int _glfwInitContextAPI(void)
|
int _glfwInitContextAPI(void)
|
||||||
{
|
{
|
||||||
if (!_glfwInitTLS())
|
if (!_glfwCreateContextTLS())
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
|
|
||||||
_glfw.wgl.opengl32.instance = LoadLibraryW(L"opengl32.dll");
|
_glfw.wgl.opengl32.instance = LoadLibraryW(L"opengl32.dll");
|
||||||
@@ -323,6 +282,28 @@ int _glfwInitContextAPI(void)
|
|||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_glfw.wgl.opengl32.CreateContext = (WGLCREATECONTEXT_T)
|
||||||
|
GetProcAddress(_glfw.wgl.opengl32.instance, "wglCreateContext");
|
||||||
|
_glfw.wgl.opengl32.DeleteContext = (WGLDELETECONTEXT_T)
|
||||||
|
GetProcAddress(_glfw.wgl.opengl32.instance, "wglDeleteContext");
|
||||||
|
_glfw.wgl.opengl32.GetProcAddress = (WGLGETPROCADDRESS_T)
|
||||||
|
GetProcAddress(_glfw.wgl.opengl32.instance, "wglGetProcAddress");
|
||||||
|
_glfw.wgl.opengl32.MakeCurrent = (WGLMAKECURRENT_T)
|
||||||
|
GetProcAddress(_glfw.wgl.opengl32.instance, "wglMakeCurrent");
|
||||||
|
_glfw.wgl.opengl32.ShareLists = (WGLSHARELISTS_T)
|
||||||
|
GetProcAddress(_glfw.wgl.opengl32.instance, "wglShareLists");
|
||||||
|
|
||||||
|
if (!_glfw.wgl.opengl32.CreateContext ||
|
||||||
|
!_glfw.wgl.opengl32.DeleteContext ||
|
||||||
|
!_glfw.wgl.opengl32.GetProcAddress ||
|
||||||
|
!_glfw.wgl.opengl32.MakeCurrent ||
|
||||||
|
!_glfw.wgl.opengl32.ShareLists)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to load opengl32 functions");
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,7 +314,7 @@ void _glfwTerminateContextAPI(void)
|
|||||||
if (_glfw.wgl.opengl32.instance)
|
if (_glfw.wgl.opengl32.instance)
|
||||||
FreeLibrary(_glfw.wgl.opengl32.instance);
|
FreeLibrary(_glfw.wgl.opengl32.instance);
|
||||||
|
|
||||||
_glfwTerminateTLS();
|
_glfwDestroyContextTLS();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define setWGLattrib(attribName, attribValue) \
|
#define setWGLattrib(attribName, attribValue) \
|
||||||
@@ -384,21 +365,18 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (window->wgl.ARB_create_context)
|
if (window->wgl.ARB_create_context)
|
||||||
{
|
{
|
||||||
int index = 0, mask = 0, flags = 0, strategy = 0;
|
int index = 0, mask = 0, flags = 0;
|
||||||
|
|
||||||
if (ctxconfig->api == GLFW_OPENGL_API)
|
if (ctxconfig->api == GLFW_OPENGL_API)
|
||||||
{
|
{
|
||||||
if (ctxconfig->forward)
|
if (ctxconfig->forward)
|
||||||
flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
|
flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
|
||||||
|
|
||||||
if (ctxconfig->profile)
|
|
||||||
{
|
|
||||||
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
||||||
mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||||
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
||||||
mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
mask |= WGL_CONTEXT_ES2_PROFILE_BIT_EXT;
|
mask |= WGL_CONTEXT_ES2_PROFILE_BIT_EXT;
|
||||||
|
|
||||||
@@ -410,9 +388,15 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
if (window->wgl.ARB_create_context_robustness)
|
if (window->wgl.ARB_create_context_robustness)
|
||||||
{
|
{
|
||||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||||
strategy = WGL_NO_RESET_NOTIFICATION_ARB;
|
{
|
||||||
|
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||||
|
WGL_NO_RESET_NOTIFICATION_ARB);
|
||||||
|
}
|
||||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||||
strategy = WGL_LOSE_CONTEXT_ON_RESET_ARB;
|
{
|
||||||
|
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||||
|
WGL_LOSE_CONTEXT_ON_RESET_ARB);
|
||||||
|
}
|
||||||
|
|
||||||
flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
|
flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
|
||||||
}
|
}
|
||||||
@@ -435,12 +419,11 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)
|
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||||
{
|
{
|
||||||
// NOTE: Only request an explicitly versioned context when
|
|
||||||
// necessary, as explicitly requesting version 1.0 does not
|
|
||||||
// always return the highest available version
|
|
||||||
|
|
||||||
setWGLattrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
setWGLattrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||||
setWGLattrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
setWGLattrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||||
}
|
}
|
||||||
@@ -451,9 +434,6 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
if (mask)
|
if (mask)
|
||||||
setWGLattrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
|
setWGLattrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||||
|
|
||||||
if (strategy)
|
|
||||||
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, strategy);
|
|
||||||
|
|
||||||
setWGLattrib(0, 0);
|
setWGLattrib(0, 0);
|
||||||
|
|
||||||
window->wgl.context = window->wgl.CreateContextAttribsARB(window->wgl.dc,
|
window->wgl.context = window->wgl.CreateContextAttribsARB(window->wgl.dc,
|
||||||
@@ -468,7 +448,7 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
window->wgl.context = wglCreateContext(window->wgl.dc);
|
window->wgl.context = _glfw_wglCreateContext(window->wgl.dc);
|
||||||
if (!window->wgl.context)
|
if (!window->wgl.context)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
@@ -478,7 +458,7 @@ int _glfwCreateContext(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (share)
|
if (share)
|
||||||
{
|
{
|
||||||
if (!wglShareLists(share, window->wgl.context))
|
if (!_glfw_wglShareLists(share, window->wgl.context))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to enable sharing with specified OpenGL context");
|
"WGL: Failed to enable sharing with specified OpenGL context");
|
||||||
@@ -501,7 +481,7 @@ void _glfwDestroyContext(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
if (window->wgl.context)
|
if (window->wgl.context)
|
||||||
{
|
{
|
||||||
wglDeleteContext(window->wgl.context);
|
_glfw_wglDeleteContext(window->wgl.context);
|
||||||
window->wgl.context = NULL;
|
window->wgl.context = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,24 +560,18 @@ int _glfwAnalyzeContext(const _GLFWwindow* window,
|
|||||||
|
|
||||||
if (fbconfig->samples > 0)
|
if (fbconfig->samples > 0)
|
||||||
{
|
{
|
||||||
// We want FSAA, but can we get it?
|
// MSAA is not a hard constraint, so do nothing if it's not supported
|
||||||
// FSAA is not a hard constraint, so otherwise we just don't care
|
|
||||||
|
|
||||||
if (window->wgl.ARB_multisample && window->wgl.ARB_pixel_format)
|
if (window->wgl.ARB_multisample && window->wgl.ARB_pixel_format)
|
||||||
{
|
|
||||||
// We appear to have both the extension and the means to ask for it
|
|
||||||
required = GL_TRUE;
|
required = GL_TRUE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (fbconfig->sRGB)
|
if (fbconfig->sRGB)
|
||||||
{
|
{
|
||||||
// We want sRGB, but can we get it?
|
// sRGB is not a hard constraint, so do nothing if it's not supported
|
||||||
// sRGB is not a hard constraint, so otherwise we just don't care
|
if ((window->wgl.ARB_framebuffer_sRGB ||
|
||||||
|
window->wgl.EXT_framebuffer_sRGB) &&
|
||||||
if (window->wgl.ARB_framebuffer_sRGB && window->wgl.ARB_pixel_format)
|
window->wgl.ARB_pixel_format)
|
||||||
{
|
{
|
||||||
// We appear to have both the extension and the means to ask for it
|
|
||||||
required = GL_TRUE;
|
required = GL_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -616,15 +590,23 @@ int _glfwAnalyzeContext(const _GLFWwindow* window,
|
|||||||
void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
|
void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window)
|
if (window)
|
||||||
wglMakeCurrent(window->wgl.dc, window->wgl.context);
|
_glfw_wglMakeCurrent(window->wgl.dc, window->wgl.context);
|
||||||
else
|
else
|
||||||
wglMakeCurrent(NULL, NULL);
|
_glfw_wglMakeCurrent(NULL, NULL);
|
||||||
|
|
||||||
_glfwSetCurrentContext(window);
|
_glfwSetContextTLS(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
|
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
|
// HACK: Use DwmFlush when desktop composition is enabled
|
||||||
|
if (_glfwIsCompositionEnabled() && !window->monitor)
|
||||||
|
{
|
||||||
|
int count = abs(window->wgl.interval);
|
||||||
|
while (count--)
|
||||||
|
_glfw_DwmFlush();
|
||||||
|
}
|
||||||
|
|
||||||
SwapBuffers(window->wgl.dc);
|
SwapBuffers(window->wgl.dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,14 +614,12 @@ void _glfwPlatformSwapInterval(int interval)
|
|||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||||
|
|
||||||
#if !defined(_GLFW_USE_DWM_SWAP_INTERVAL)
|
window->wgl.interval = interval;
|
||||||
if (_glfwIsCompositionEnabled() && interval)
|
|
||||||
{
|
// HACK: Disable WGL swap interval when desktop composition is enabled to
|
||||||
// Don't enabled vsync when desktop compositing is enabled, as it leads
|
// avoid interfering with DWM vsync
|
||||||
// to frame jitter
|
if (_glfwIsCompositionEnabled() && !window->monitor)
|
||||||
return;
|
interval = 0;
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (window->wgl.EXT_swap_control)
|
if (window->wgl.EXT_swap_control)
|
||||||
window->wgl.SwapIntervalEXT(interval);
|
window->wgl.SwapIntervalEXT(interval);
|
||||||
@@ -647,14 +627,14 @@ void _glfwPlatformSwapInterval(int interval)
|
|||||||
|
|
||||||
int _glfwPlatformExtensionSupported(const char* extension)
|
int _glfwPlatformExtensionSupported(const char* extension)
|
||||||
{
|
{
|
||||||
const GLubyte* extensions;
|
const char* extensions;
|
||||||
|
|
||||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||||
|
|
||||||
if (window->wgl.GetExtensionsStringEXT != NULL)
|
if (window->wgl.GetExtensionsStringEXT != NULL)
|
||||||
{
|
{
|
||||||
extensions = (GLubyte*) window->wgl.GetExtensionsStringEXT();
|
extensions = window->wgl.GetExtensionsStringEXT();
|
||||||
if (extensions != NULL)
|
if (extensions)
|
||||||
{
|
{
|
||||||
if (_glfwStringInExtensionString(extension, extensions))
|
if (_glfwStringInExtensionString(extension, extensions))
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
@@ -663,8 +643,8 @@ int _glfwPlatformExtensionSupported(const char* extension)
|
|||||||
|
|
||||||
if (window->wgl.GetExtensionsStringARB != NULL)
|
if (window->wgl.GetExtensionsStringARB != NULL)
|
||||||
{
|
{
|
||||||
extensions = (GLubyte*) window->wgl.GetExtensionsStringARB(window->wgl.dc);
|
extensions = window->wgl.GetExtensionsStringARB(window->wgl.dc);
|
||||||
if (extensions != NULL)
|
if (extensions)
|
||||||
{
|
{
|
||||||
if (_glfwStringInExtensionString(extension, extensions))
|
if (_glfwStringInExtensionString(extension, extensions))
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
@@ -676,7 +656,7 @@ int _glfwPlatformExtensionSupported(const char* extension)
|
|||||||
|
|
||||||
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
|
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
|
||||||
{
|
{
|
||||||
const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
|
const GLFWglproc proc = (GLFWglproc) _glfw_wglGetProcAddress(procname);
|
||||||
if (proc)
|
if (proc)
|
||||||
return proc;
|
return proc;
|
||||||
|
|
||||||
|
|||||||
+22
-4
@@ -25,14 +25,26 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _wgl_context_h_
|
#ifndef _glfw3_wgl_context_h_
|
||||||
#define _wgl_context_h_
|
#define _glfw3_wgl_context_h_
|
||||||
|
|
||||||
// This path may need to be changed if you build GLFW using your own setup
|
// This path may need to be changed if you build GLFW using your own setup
|
||||||
// We ship and use our own copy of wglext.h since GLFW uses fairly new
|
// We ship and use our own copy of wglext.h since GLFW uses fairly new
|
||||||
// extensions and not all operating systems come with an up-to-date version
|
// extensions and not all operating systems come with an up-to-date version
|
||||||
#include "../deps/GL/wglext.h"
|
#include "../deps/GL/wglext.h"
|
||||||
|
|
||||||
|
// opengl32.dll function pointer typedefs
|
||||||
|
typedef HGLRC (WINAPI * WGLCREATECONTEXT_T)(HDC);
|
||||||
|
typedef BOOL (WINAPI * WGLDELETECONTEXT_T)(HGLRC);
|
||||||
|
typedef PROC (WINAPI * WGLGETPROCADDRESS_T)(LPCSTR);
|
||||||
|
typedef BOOL (WINAPI * WGLMAKECURRENT_T)(HDC,HGLRC);
|
||||||
|
typedef BOOL (WINAPI * WGLSHARELISTS_T)(HGLRC,HGLRC);
|
||||||
|
#define _glfw_wglCreateContext _glfw.wgl.opengl32.CreateContext
|
||||||
|
#define _glfw_wglDeleteContext _glfw.wgl.opengl32.DeleteContext
|
||||||
|
#define _glfw_wglGetProcAddress _glfw.wgl.opengl32.GetProcAddress
|
||||||
|
#define _glfw_wglMakeCurrent _glfw.wgl.opengl32.MakeCurrent
|
||||||
|
#define _glfw_wglShareLists _glfw.wgl.opengl32.ShareLists
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_FBCONFIG int wgl
|
#define _GLFW_PLATFORM_FBCONFIG int wgl
|
||||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL wgl
|
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL wgl
|
||||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl
|
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl
|
||||||
@@ -44,6 +56,7 @@ typedef struct _GLFWcontextWGL
|
|||||||
{
|
{
|
||||||
HDC dc; // Private GDI device context
|
HDC dc; // Private GDI device context
|
||||||
HGLRC context; // Permanent rendering context
|
HGLRC context; // Permanent rendering context
|
||||||
|
int interval;
|
||||||
|
|
||||||
// WGL extensions (context specific)
|
// WGL extensions (context specific)
|
||||||
PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;
|
PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;
|
||||||
@@ -54,6 +67,7 @@ typedef struct _GLFWcontextWGL
|
|||||||
GLboolean EXT_swap_control;
|
GLboolean EXT_swap_control;
|
||||||
GLboolean ARB_multisample;
|
GLboolean ARB_multisample;
|
||||||
GLboolean ARB_framebuffer_sRGB;
|
GLboolean ARB_framebuffer_sRGB;
|
||||||
|
GLboolean EXT_framebuffer_sRGB;
|
||||||
GLboolean ARB_pixel_format;
|
GLboolean ARB_pixel_format;
|
||||||
GLboolean ARB_create_context;
|
GLboolean ARB_create_context;
|
||||||
GLboolean ARB_create_context_profile;
|
GLboolean ARB_create_context_profile;
|
||||||
@@ -68,9 +82,13 @@ typedef struct _GLFWcontextWGL
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWlibraryWGL
|
typedef struct _GLFWlibraryWGL
|
||||||
{
|
{
|
||||||
// opengl32.dll (for glfwGetProcAddress)
|
|
||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
|
WGLCREATECONTEXT_T CreateContext;
|
||||||
|
WGLDELETECONTEXT_T DeleteContext;
|
||||||
|
WGLGETPROCADDRESS_T GetProcAddress;
|
||||||
|
WGLMAKECURRENT_T MakeCurrent;
|
||||||
|
WGLSHARELISTS_T ShareLists;
|
||||||
} opengl32;
|
} opengl32;
|
||||||
|
|
||||||
} _GLFWlibraryWGL;
|
} _GLFWlibraryWGL;
|
||||||
@@ -86,4 +104,4 @@ int _glfwAnalyzeContext(const _GLFWwindow* window,
|
|||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
|
|
||||||
#endif // _wgl_context_h_
|
#endif // _glfw3_wgl_context_h_
|
||||||
|
|||||||
+17
-7
@@ -31,14 +31,21 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
|
||||||
|
|
||||||
#if defined(_GLFW_USE_OPTIMUS_HPG)
|
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
|
||||||
|
|
||||||
// Applications exporting this symbol with this value will be automatically
|
// Applications exporting this symbol with this value will be automatically
|
||||||
// directed to the high-performance GPU on Nvidia Optimus systems
|
// directed to the high-performance GPU on Nvidia Optimus systems with
|
||||||
|
// up-to-date drivers
|
||||||
//
|
//
|
||||||
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
__declspec(dllexport) DWORD NvOptimusEnablement = 1;
|
||||||
|
|
||||||
#endif // _GLFW_USE_OPTIMUS_HPG
|
// Applications exporting this symbol with this value will be automatically
|
||||||
|
// directed to the high-performance GPU on AMD PowerXpress systems with
|
||||||
|
// up-to-date drivers
|
||||||
|
//
|
||||||
|
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||||
|
|
||||||
|
#endif // _GLFW_USE_HYBRID_HPG
|
||||||
|
|
||||||
#if defined(_GLFW_BUILD_DLL)
|
#if defined(_GLFW_BUILD_DLL)
|
||||||
|
|
||||||
@@ -96,6 +103,8 @@ static GLboolean initLibraries(void)
|
|||||||
{
|
{
|
||||||
_glfw.win32.dwmapi.DwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED_T)
|
_glfw.win32.dwmapi.DwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED_T)
|
||||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
|
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
|
||||||
|
_glfw.win32.dwmapi.DwmFlush = (DWMFLUSH_T)
|
||||||
|
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
|
||||||
}
|
}
|
||||||
|
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
@@ -360,7 +369,7 @@ void _glfwPlatformTerminate(void)
|
|||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
{
|
{
|
||||||
const char* version = _GLFW_VERSION_NUMBER " Win32"
|
return _GLFW_VERSION_NUMBER " Win32"
|
||||||
#if defined(_GLFW_WGL)
|
#if defined(_GLFW_WGL)
|
||||||
" WGL"
|
" WGL"
|
||||||
#elif defined(_GLFW_EGL)
|
#elif defined(_GLFW_EGL)
|
||||||
@@ -371,11 +380,12 @@ const char* _glfwPlatformGetVersionString(void)
|
|||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
" VisualC"
|
" VisualC"
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
|
||||||
|
" hybrid-GPU"
|
||||||
|
#endif
|
||||||
#if defined(_GLFW_BUILD_DLL)
|
#if defined(_GLFW_BUILD_DLL)
|
||||||
" DLL"
|
" DLL"
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
|
||||||
return version;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+46
-37
@@ -103,7 +103,7 @@ void _glfwRestoreVideoMode(_GLFWmonitor* monitor)
|
|||||||
|
|
||||||
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
||||||
{
|
{
|
||||||
int size = 0, found = 0;
|
int found = 0;
|
||||||
_GLFWmonitor** monitors = NULL;
|
_GLFWmonitor** monitors = NULL;
|
||||||
DWORD adapterIndex, displayIndex;
|
DWORD adapterIndex, displayIndex;
|
||||||
|
|
||||||
@@ -125,6 +125,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
|||||||
for (displayIndex = 0; ; displayIndex++)
|
for (displayIndex = 0; ; displayIndex++)
|
||||||
{
|
{
|
||||||
DISPLAY_DEVICEW display;
|
DISPLAY_DEVICEW display;
|
||||||
|
_GLFWmonitor* monitor;
|
||||||
char* name;
|
char* name;
|
||||||
HDC dc;
|
HDC dc;
|
||||||
|
|
||||||
@@ -134,12 +135,6 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
|||||||
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
|
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (found == size)
|
|
||||||
{
|
|
||||||
size += 4;
|
|
||||||
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * size);
|
|
||||||
}
|
|
||||||
|
|
||||||
name = _glfwCreateUTF8FromWideString(display.DeviceString);
|
name = _glfwCreateUTF8FromWideString(display.DeviceString);
|
||||||
if (!name)
|
if (!name)
|
||||||
{
|
{
|
||||||
@@ -150,35 +145,40 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
|||||||
|
|
||||||
dc = CreateDCW(L"DISPLAY", adapter.DeviceName, NULL, NULL);
|
dc = CreateDCW(L"DISPLAY", adapter.DeviceName, NULL, NULL);
|
||||||
|
|
||||||
monitors[found] = _glfwAllocMonitor(name,
|
monitor = _glfwAllocMonitor(name,
|
||||||
GetDeviceCaps(dc, HORZSIZE),
|
GetDeviceCaps(dc, HORZSIZE),
|
||||||
GetDeviceCaps(dc, VERTSIZE));
|
GetDeviceCaps(dc, VERTSIZE));
|
||||||
|
|
||||||
DeleteDC(dc);
|
DeleteDC(dc);
|
||||||
free(name);
|
free(name);
|
||||||
|
|
||||||
wcscpy(monitors[found]->win32.adapterName, adapter.DeviceName);
|
if (adapter.StateFlags & DISPLAY_DEVICE_MODESPRUNED)
|
||||||
wcscpy(monitors[found]->win32.displayName, display.DeviceName);
|
monitor->win32.modesPruned = GL_TRUE;
|
||||||
|
|
||||||
|
wcscpy(monitor->win32.adapterName, adapter.DeviceName);
|
||||||
|
wcscpy(monitor->win32.displayName, display.DeviceName);
|
||||||
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0,
|
WideCharToMultiByte(CP_UTF8, 0,
|
||||||
adapter.DeviceName, -1,
|
adapter.DeviceName, -1,
|
||||||
monitors[found]->win32.publicAdapterName,
|
monitor->win32.publicAdapterName,
|
||||||
sizeof(monitors[found]->win32.publicAdapterName),
|
sizeof(monitor->win32.publicAdapterName),
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0,
|
WideCharToMultiByte(CP_UTF8, 0,
|
||||||
display.DeviceName, -1,
|
display.DeviceName, -1,
|
||||||
monitors[found]->win32.publicDisplayName,
|
monitor->win32.publicDisplayName,
|
||||||
sizeof(monitors[found]->win32.publicDisplayName),
|
sizeof(monitor->win32.publicDisplayName),
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
|
||||||
|
found++;
|
||||||
|
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
|
||||||
|
monitors[found - 1] = monitor;
|
||||||
|
|
||||||
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE &&
|
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE &&
|
||||||
displayIndex == 0)
|
displayIndex == 0)
|
||||||
{
|
{
|
||||||
_GLFW_SWAP_POINTERS(monitors[0], monitors[found]);
|
_GLFW_SWAP_POINTERS(monitors[0], monitors[found - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
found++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,12 +208,12 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
|||||||
*ypos = settings.dmPosition.y;
|
*ypos = settings.dmPosition.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||||
{
|
{
|
||||||
int modeIndex = 0, count = 0;
|
int modeIndex = 0, size = 0;
|
||||||
GLFWvidmode* result = NULL;
|
GLFWvidmode* result = NULL;
|
||||||
|
|
||||||
*found = 0;
|
*count = 0;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@@ -229,11 +229,9 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
|||||||
|
|
||||||
modeIndex++;
|
modeIndex++;
|
||||||
|
|
||||||
if (dm.dmBitsPerPel < 15)
|
|
||||||
{
|
|
||||||
// Skip modes with less than 15 BPP
|
// Skip modes with less than 15 BPP
|
||||||
|
if (dm.dmBitsPerPel < 15)
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
mode.width = dm.dmPelsWidth;
|
mode.width = dm.dmPelsWidth;
|
||||||
mode.height = dm.dmPelsHeight;
|
mode.height = dm.dmPelsHeight;
|
||||||
@@ -243,30 +241,41 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
|||||||
&mode.greenBits,
|
&mode.greenBits,
|
||||||
&mode.blueBits);
|
&mode.blueBits);
|
||||||
|
|
||||||
for (i = 0; i < *found; i++)
|
for (i = 0; i < *count; i++)
|
||||||
{
|
{
|
||||||
if (_glfwCompareVideoModes(result + i, &mode) == 0)
|
if (_glfwCompareVideoModes(result + i, &mode) == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < *found)
|
// Skip duplicate modes
|
||||||
|
if (i < *count)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (monitor->win32.modesPruned)
|
||||||
|
{
|
||||||
|
// Skip modes not supported by the connected displays
|
||||||
|
if (ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
||||||
|
&dm,
|
||||||
|
NULL,
|
||||||
|
CDS_TEST,
|
||||||
|
NULL) != DISP_CHANGE_SUCCESSFUL)
|
||||||
{
|
{
|
||||||
// This is a duplicate, so skip it
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*found == count)
|
|
||||||
{
|
|
||||||
if (count)
|
|
||||||
count *= 2;
|
|
||||||
else
|
|
||||||
count = 128;
|
|
||||||
|
|
||||||
result = (GLFWvidmode*) realloc(result, count * sizeof(GLFWvidmode));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result[*found] = mode;
|
if (*count == size)
|
||||||
(*found)++;
|
{
|
||||||
|
if (*count)
|
||||||
|
size *= 2;
|
||||||
|
else
|
||||||
|
size = 128;
|
||||||
|
|
||||||
|
result = (GLFWvidmode*) realloc(result, size * sizeof(GLFWvidmode));
|
||||||
|
}
|
||||||
|
|
||||||
|
(*count)++;
|
||||||
|
result[*count - 1] = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
+9
-14
@@ -25,9 +25,8 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _win32_platform_h_
|
#ifndef _glfw3_win32_platform_h_
|
||||||
#define _win32_platform_h_
|
#define _glfw3_win32_platform_h_
|
||||||
|
|
||||||
|
|
||||||
// We don't need all the fancy stuff
|
// We don't need all the fancy stuff
|
||||||
#ifndef NOMINMAX
|
#ifndef NOMINMAX
|
||||||
@@ -71,9 +70,7 @@
|
|||||||
#define strdup _strdup
|
#define strdup _strdup
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// HACK: Define macros that some older windows.h variants don't
|
// HACK: Define macros that some older windows.h variants don't
|
||||||
|
|
||||||
#ifndef WM_MOUSEHWHEEL
|
#ifndef WM_MOUSEHWHEEL
|
||||||
#define WM_MOUSEHWHEEL 0x020E
|
#define WM_MOUSEHWHEEL 0x020E
|
||||||
#endif
|
#endif
|
||||||
@@ -102,7 +99,6 @@ typedef struct tagCHANGEFILTERSTRUCT
|
|||||||
#endif
|
#endif
|
||||||
#endif /*Windows 7*/
|
#endif /*Windows 7*/
|
||||||
|
|
||||||
|
|
||||||
// winmm.dll function pointer typedefs
|
// winmm.dll function pointer typedefs
|
||||||
typedef MMRESULT (WINAPI * JOYGETDEVCAPS_T)(UINT,LPJOYCAPS,UINT);
|
typedef MMRESULT (WINAPI * JOYGETDEVCAPS_T)(UINT,LPJOYCAPS,UINT);
|
||||||
typedef MMRESULT (WINAPI * JOYGETPOS_T)(UINT,LPJOYINFO);
|
typedef MMRESULT (WINAPI * JOYGETPOS_T)(UINT,LPJOYINFO);
|
||||||
@@ -121,15 +117,16 @@ typedef BOOL (WINAPI * CHANGEWINDOWMESSAGEFILTEREX_T)(HWND,UINT,DWORD,PCHANGEFIL
|
|||||||
|
|
||||||
// dwmapi.dll function pointer typedefs
|
// dwmapi.dll function pointer typedefs
|
||||||
typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*);
|
typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*);
|
||||||
|
typedef HRESULT (WINAPI * DWMFLUSH_T)(VOID);
|
||||||
#define _glfw_DwmIsCompositionEnabled _glfw.win32.dwmapi.DwmIsCompositionEnabled
|
#define _glfw_DwmIsCompositionEnabled _glfw.win32.dwmapi.DwmIsCompositionEnabled
|
||||||
|
#define _glfw_DwmFlush _glfw.win32.dwmapi.DwmFlush
|
||||||
|
|
||||||
#define _GLFW_RECREATION_NOT_NEEDED 0
|
#define _GLFW_RECREATION_NOT_NEEDED 0
|
||||||
#define _GLFW_RECREATION_REQUIRED 1
|
#define _GLFW_RECREATION_REQUIRED 1
|
||||||
#define _GLFW_RECREATION_IMPOSSIBLE 2
|
#define _GLFW_RECREATION_IMPOSSIBLE 2
|
||||||
|
|
||||||
|
|
||||||
#include "win32_tls.h"
|
#include "win32_tls.h"
|
||||||
|
#include "winmm_joystick.h"
|
||||||
|
|
||||||
#if defined(_GLFW_WGL)
|
#if defined(_GLFW_WGL)
|
||||||
#include "wgl_context.h"
|
#include "wgl_context.h"
|
||||||
@@ -141,8 +138,6 @@ typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*);
|
|||||||
#error "No supported context creation API selected"
|
#error "No supported context creation API selected"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "winmm_joystick.h"
|
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
|
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
|
||||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
|
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
|
||||||
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time
|
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time
|
||||||
@@ -155,10 +150,8 @@ typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*);
|
|||||||
typedef struct _GLFWwindowWin32
|
typedef struct _GLFWwindowWin32
|
||||||
{
|
{
|
||||||
HWND handle;
|
HWND handle;
|
||||||
DWORD dwStyle;
|
|
||||||
DWORD dwExStyle;
|
|
||||||
|
|
||||||
GLboolean cursorInside;
|
GLboolean cursorTracked;
|
||||||
GLboolean iconified;
|
GLboolean iconified;
|
||||||
|
|
||||||
// The last received cursor position, regardless of source
|
// The last received cursor position, regardless of source
|
||||||
@@ -195,6 +188,7 @@ typedef struct _GLFWlibraryWin32
|
|||||||
struct {
|
struct {
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
DWMISCOMPOSITIONENABLED_T DwmIsCompositionEnabled;
|
DWMISCOMPOSITIONENABLED_T DwmIsCompositionEnabled;
|
||||||
|
DWMFLUSH_T DwmFlush;
|
||||||
} dwmapi;
|
} dwmapi;
|
||||||
|
|
||||||
} _GLFWlibraryWin32;
|
} _GLFWlibraryWin32;
|
||||||
@@ -209,6 +203,7 @@ typedef struct _GLFWmonitorWin32
|
|||||||
WCHAR displayName[32];
|
WCHAR displayName[32];
|
||||||
char publicAdapterName[64];
|
char publicAdapterName[64];
|
||||||
char publicDisplayName[64];
|
char publicDisplayName[64];
|
||||||
|
GLboolean modesPruned;
|
||||||
GLboolean modeChanged;
|
GLboolean modeChanged;
|
||||||
|
|
||||||
} _GLFWmonitorWin32;
|
} _GLFWmonitorWin32;
|
||||||
@@ -247,4 +242,4 @@ void _glfwInitTimer(void);
|
|||||||
GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||||
void _glfwRestoreVideoMode(_GLFWmonitor* monitor);
|
void _glfwRestoreVideoMode(_GLFWmonitor* monitor);
|
||||||
|
|
||||||
#endif // _win32_platform_h_
|
#endif // _glfw3_win32_platform_h_
|
||||||
|
|||||||
+3
-3
@@ -32,7 +32,7 @@
|
|||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int _glfwInitTLS(void)
|
int _glfwCreateContextTLS(void)
|
||||||
{
|
{
|
||||||
_glfw.win32_tls.context = TlsAlloc();
|
_glfw.win32_tls.context = TlsAlloc();
|
||||||
if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES)
|
if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES)
|
||||||
@@ -46,13 +46,13 @@ int _glfwInitTLS(void)
|
|||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwTerminateTLS(void)
|
void _glfwDestroyContextTLS(void)
|
||||||
{
|
{
|
||||||
if (_glfw.win32_tls.allocated)
|
if (_glfw.win32_tls.allocated)
|
||||||
TlsFree(_glfw.win32_tls.context);
|
TlsFree(_glfw.win32_tls.context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwSetCurrentContext(_GLFWwindow* context)
|
void _glfwSetContextTLS(_GLFWwindow* context)
|
||||||
{
|
{
|
||||||
TlsSetValue(_glfw.win32_tls.context, context);
|
TlsSetValue(_glfw.win32_tls.context, context);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -25,8 +25,8 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _win32_tls_h_
|
#ifndef _glfw3_win32_tls_h_
|
||||||
#define _win32_tls_h_
|
#define _glfw3_win32_tls_h_
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsWin32 win32_tls
|
#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsWin32 win32_tls
|
||||||
|
|
||||||
@@ -41,8 +41,8 @@ typedef struct _GLFWtlsWin32
|
|||||||
} _GLFWtlsWin32;
|
} _GLFWtlsWin32;
|
||||||
|
|
||||||
|
|
||||||
int _glfwInitTLS(void);
|
int _glfwCreateContextTLS(void);
|
||||||
void _glfwTerminateTLS(void);
|
void _glfwDestroyContextTLS(void);
|
||||||
void _glfwSetCurrentContext(_GLFWwindow* context);
|
void _glfwSetContextTLS(_GLFWwindow* context);
|
||||||
|
|
||||||
#endif // _win32_tls_h_
|
#endif // _glfw3_win32_tls_h_
|
||||||
|
|||||||
+87
-74
@@ -38,6 +38,37 @@
|
|||||||
#define _GLFW_WNDCLASSNAME L"GLFW30"
|
#define _GLFW_WNDCLASSNAME L"GLFW30"
|
||||||
|
|
||||||
|
|
||||||
|
// Returns the window style for the specified window
|
||||||
|
//
|
||||||
|
static DWORD getWindowStyle(const _GLFWwindow* window)
|
||||||
|
{
|
||||||
|
DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
|
||||||
|
|
||||||
|
if (window->decorated && !window->monitor)
|
||||||
|
{
|
||||||
|
style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
|
||||||
|
|
||||||
|
if (window->resizable)
|
||||||
|
style |= WS_MAXIMIZEBOX | WS_SIZEBOX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
style |= WS_POPUP;
|
||||||
|
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the extended window style for the specified window
|
||||||
|
//
|
||||||
|
static DWORD getWindowExStyle(const _GLFWwindow* window)
|
||||||
|
{
|
||||||
|
DWORD style = WS_EX_APPWINDOW;
|
||||||
|
|
||||||
|
if (window->decorated && !window->monitor)
|
||||||
|
style |= WS_EX_WINDOWEDGE;
|
||||||
|
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
// Updates the cursor clip rect
|
// Updates the cursor clip rect
|
||||||
//
|
//
|
||||||
static void updateClipRect(_GLFWwindow* window)
|
static void updateClipRect(_GLFWwindow* window)
|
||||||
@@ -249,9 +280,6 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
if (window->cursorMode != GLFW_CURSOR_NORMAL)
|
if (window->cursorMode != GLFW_CURSOR_NORMAL)
|
||||||
_glfwPlatformApplyCursorMode(window);
|
_glfwPlatformApplyCursorMode(window);
|
||||||
|
|
||||||
if (window->monitor && window->autoIconify)
|
|
||||||
enterFullscreenMode(window);
|
|
||||||
|
|
||||||
_glfwInputWindowFocus(window, GL_TRUE);
|
_glfwInputWindowFocus(window, GL_TRUE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -262,10 +290,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
restoreCursor(window);
|
restoreCursor(window);
|
||||||
|
|
||||||
if (window->monitor && window->autoIconify)
|
if (window->monitor && window->autoIconify)
|
||||||
{
|
|
||||||
_glfwPlatformIconifyWindow(window);
|
_glfwPlatformIconifyWindow(window);
|
||||||
leaveFullscreenMode(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwInputWindowFocus(window, GL_FALSE);
|
_glfwInputWindowFocus(window, GL_FALSE);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -431,7 +456,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
|
|
||||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
{
|
{
|
||||||
if (_glfw.focusedWindow != window)
|
if (_glfw.cursorWindow != window)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
_glfwInputCursorMotion(window,
|
_glfwInputCursorMotion(window,
|
||||||
@@ -444,7 +469,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
window->win32.cursorPosX = x;
|
window->win32.cursorPosX = x;
|
||||||
window->win32.cursorPosY = y;
|
window->win32.cursorPosY = y;
|
||||||
|
|
||||||
if (!window->win32.cursorInside)
|
if (!window->win32.cursorTracked)
|
||||||
{
|
{
|
||||||
TRACKMOUSEEVENT tme;
|
TRACKMOUSEEVENT tme;
|
||||||
ZeroMemory(&tme, sizeof(tme));
|
ZeroMemory(&tme, sizeof(tme));
|
||||||
@@ -453,7 +478,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
tme.hwndTrack = window->win32.handle;
|
tme.hwndTrack = window->win32.handle;
|
||||||
TrackMouseEvent(&tme);
|
TrackMouseEvent(&tme);
|
||||||
|
|
||||||
window->win32.cursorInside = GL_TRUE;
|
window->win32.cursorTracked = GL_TRUE;
|
||||||
_glfwInputCursorEnter(window, GL_TRUE);
|
_glfwInputCursorEnter(window, GL_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,7 +487,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
|
|
||||||
case WM_MOUSELEAVE:
|
case WM_MOUSELEAVE:
|
||||||
{
|
{
|
||||||
window->win32.cursorInside = GL_FALSE;
|
window->win32.cursorTracked = GL_FALSE;
|
||||||
_glfwInputCursorEnter(window, GL_FALSE);
|
_glfwInputCursorEnter(window, GL_FALSE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -483,7 +508,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
|
|
||||||
case WM_SIZE:
|
case WM_SIZE:
|
||||||
{
|
{
|
||||||
if (_glfw.focusedWindow == window)
|
if (_glfw.cursorWindow == window)
|
||||||
{
|
{
|
||||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
updateClipRect(window);
|
updateClipRect(window);
|
||||||
@@ -492,12 +517,18 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
if (!window->win32.iconified && wParam == SIZE_MINIMIZED)
|
if (!window->win32.iconified && wParam == SIZE_MINIMIZED)
|
||||||
{
|
{
|
||||||
window->win32.iconified = GL_TRUE;
|
window->win32.iconified = GL_TRUE;
|
||||||
|
if (window->monitor)
|
||||||
|
leaveFullscreenMode(window);
|
||||||
|
|
||||||
_glfwInputWindowIconify(window, GL_TRUE);
|
_glfwInputWindowIconify(window, GL_TRUE);
|
||||||
}
|
}
|
||||||
else if (window->win32.iconified &&
|
else if (window->win32.iconified &&
|
||||||
(wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED))
|
(wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED))
|
||||||
{
|
{
|
||||||
window->win32.iconified = GL_FALSE;
|
window->win32.iconified = GL_FALSE;
|
||||||
|
if (window->monitor)
|
||||||
|
enterFullscreenMode(window);
|
||||||
|
|
||||||
_glfwInputWindowIconify(window, GL_FALSE);
|
_glfwInputWindowIconify(window, GL_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,7 +539,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
|
|
||||||
case WM_MOVE:
|
case WM_MOVE:
|
||||||
{
|
{
|
||||||
if (_glfw.focusedWindow == window)
|
if (_glfw.cursorWindow == window)
|
||||||
{
|
{
|
||||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
updateClipRect(window);
|
updateClipRect(window);
|
||||||
@@ -535,7 +566,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
|
|
||||||
case WM_SETCURSOR:
|
case WM_SETCURSOR:
|
||||||
{
|
{
|
||||||
if (_glfw.focusedWindow == window && LOWORD(lParam) == HTCLIENT)
|
if (_glfw.cursorWindow == window && LOWORD(lParam) == HTCLIENT)
|
||||||
{
|
{
|
||||||
if (window->cursorMode == GLFW_CURSOR_HIDDEN ||
|
if (window->cursorMode == GLFW_CURSOR_HIDDEN ||
|
||||||
window->cursorMode == GLFW_CURSOR_DISABLED)
|
window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
@@ -563,39 +594,25 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case WM_DWMCOMPOSITIONCHANGED:
|
|
||||||
{
|
|
||||||
if (_glfwIsCompositionEnabled())
|
|
||||||
{
|
|
||||||
_GLFWwindow* previous = _glfwPlatformGetCurrentContext();
|
|
||||||
_glfwPlatformMakeContextCurrent(window);
|
|
||||||
_glfwPlatformSwapInterval(0);
|
|
||||||
_glfwPlatformMakeContextCurrent(previous);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Restore vsync if compositing was disabled
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_DROPFILES:
|
case WM_DROPFILES:
|
||||||
{
|
{
|
||||||
HDROP hDrop = (HDROP) wParam;
|
HDROP drop = (HDROP) wParam;
|
||||||
POINT pt;
|
POINT pt;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
const int count = DragQueryFileW(hDrop, 0xffffffff, NULL, 0);
|
const int count = DragQueryFileW(drop, 0xffffffff, NULL, 0);
|
||||||
char** paths = calloc(count, sizeof(char*));
|
char** paths = calloc(count, sizeof(char*));
|
||||||
|
|
||||||
// Move the mouse to the position of the drop
|
// Move the mouse to the position of the drop
|
||||||
DragQueryPoint(hDrop, &pt);
|
DragQueryPoint(drop, &pt);
|
||||||
_glfwInputCursorMotion(window, pt.x, pt.y);
|
_glfwInputCursorMotion(window, pt.x, pt.y);
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
const UINT length = DragQueryFileW(hDrop, i, NULL, 0);
|
const UINT length = DragQueryFileW(drop, i, NULL, 0);
|
||||||
WCHAR* buffer = calloc(length + 1, sizeof(WCHAR));
|
WCHAR* buffer = calloc(length + 1, sizeof(WCHAR));
|
||||||
|
|
||||||
DragQueryFileW(hDrop, i, buffer, length + 1);
|
DragQueryFileW(drop, i, buffer, length + 1);
|
||||||
paths[i] = _glfwCreateUTF8FromWideString(buffer);
|
paths[i] = _glfwCreateUTF8FromWideString(buffer);
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
@@ -607,7 +624,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
free(paths[i]);
|
free(paths[i]);
|
||||||
free(paths);
|
free(paths);
|
||||||
|
|
||||||
DragFinish(hDrop);
|
DragFinish(drop);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -622,8 +639,8 @@ static void getFullWindowSize(_GLFWwindow* window,
|
|||||||
int* fullWidth, int* fullHeight)
|
int* fullWidth, int* fullHeight)
|
||||||
{
|
{
|
||||||
RECT rect = { 0, 0, clientWidth, clientHeight };
|
RECT rect = { 0, 0, clientWidth, clientHeight };
|
||||||
AdjustWindowRectEx(&rect, window->win32.dwStyle,
|
AdjustWindowRectEx(&rect, getWindowStyle(window),
|
||||||
FALSE, window->win32.dwExStyle);
|
FALSE, getWindowExStyle(window));
|
||||||
*fullWidth = rect.right - rect.left;
|
*fullWidth = rect.right - rect.left;
|
||||||
*fullHeight = rect.bottom - rect.top;
|
*fullHeight = rect.bottom - rect.top;
|
||||||
}
|
}
|
||||||
@@ -638,35 +655,20 @@ static int createWindow(_GLFWwindow* window,
|
|||||||
int xpos, ypos, fullWidth, fullHeight;
|
int xpos, ypos, fullWidth, fullHeight;
|
||||||
WCHAR* wideTitle;
|
WCHAR* wideTitle;
|
||||||
|
|
||||||
window->win32.dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
|
if (wndconfig->monitor)
|
||||||
window->win32.dwExStyle = WS_EX_APPWINDOW;
|
|
||||||
|
|
||||||
if (window->monitor)
|
|
||||||
{
|
{
|
||||||
window->win32.dwStyle |= WS_POPUP;
|
GLFWvidmode mode;
|
||||||
|
|
||||||
// NOTE: This window placement is temporary and approximate, as the
|
// NOTE: This window placement is temporary and approximate, as the
|
||||||
// correct position and size cannot be known until the monitor
|
// correct position and size cannot be known until the monitor
|
||||||
// video mode has been set
|
// video mode has been set
|
||||||
_glfwPlatformGetMonitorPos(wndconfig->monitor, &xpos, &ypos);
|
_glfwPlatformGetMonitorPos(wndconfig->monitor, &xpos, &ypos);
|
||||||
fullWidth = wndconfig->width;
|
_glfwPlatformGetVideoMode(wndconfig->monitor, &mode);
|
||||||
fullHeight = wndconfig->height;
|
fullWidth = mode.width;
|
||||||
|
fullHeight = mode.height;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (wndconfig->decorated)
|
|
||||||
{
|
|
||||||
window->win32.dwStyle |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
|
|
||||||
|
|
||||||
if (wndconfig->resizable)
|
|
||||||
{
|
|
||||||
window->win32.dwStyle |= WS_MAXIMIZEBOX | WS_SIZEBOX;
|
|
||||||
window->win32.dwExStyle |= WS_EX_WINDOWEDGE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
window->win32.dwStyle |= WS_POPUP;
|
|
||||||
|
|
||||||
xpos = CW_USEDEFAULT;
|
xpos = CW_USEDEFAULT;
|
||||||
ypos = CW_USEDEFAULT;
|
ypos = CW_USEDEFAULT;
|
||||||
|
|
||||||
@@ -683,10 +685,10 @@ static int createWindow(_GLFWwindow* window,
|
|||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
window->win32.handle = CreateWindowExW(window->win32.dwExStyle,
|
window->win32.handle = CreateWindowExW(getWindowExStyle(window),
|
||||||
_GLFW_WNDCLASSNAME,
|
_GLFW_WNDCLASSNAME,
|
||||||
wideTitle,
|
wideTitle,
|
||||||
window->win32.dwStyle,
|
getWindowStyle(window),
|
||||||
xpos, ypos,
|
xpos, ypos,
|
||||||
fullWidth, fullHeight,
|
fullWidth, fullHeight,
|
||||||
NULL, // No parent window
|
NULL, // No parent window
|
||||||
@@ -884,8 +886,8 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
|||||||
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
|
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
|
||||||
{
|
{
|
||||||
RECT rect = { xpos, ypos, xpos, ypos };
|
RECT rect = { xpos, ypos, xpos, ypos };
|
||||||
AdjustWindowRectEx(&rect, window->win32.dwStyle,
|
AdjustWindowRectEx(&rect, getWindowStyle(window),
|
||||||
FALSE, window->win32.dwExStyle);
|
FALSE, getWindowExStyle(window));
|
||||||
SetWindowPos(window->win32.handle, NULL, rect.left, rect.top, 0, 0,
|
SetWindowPos(window->win32.handle, NULL, rect.left, rect.top, 0, 0,
|
||||||
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
|
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
|
||||||
}
|
}
|
||||||
@@ -930,8 +932,8 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
|||||||
|
|
||||||
_glfwPlatformGetWindowSize(window, &width, &height);
|
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||||
SetRect(&rect, 0, 0, width, height);
|
SetRect(&rect, 0, 0, width, height);
|
||||||
AdjustWindowRectEx(&rect, window->win32.dwStyle,
|
AdjustWindowRectEx(&rect, getWindowStyle(window),
|
||||||
FALSE, window->win32.dwExStyle);
|
FALSE, getWindowExStyle(window));
|
||||||
|
|
||||||
if (left)
|
if (left)
|
||||||
*left = -rect.left;
|
*left = -rect.left;
|
||||||
@@ -989,7 +991,6 @@ int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
|||||||
void _glfwPlatformPollEvents(void)
|
void _glfwPlatformPollEvents(void)
|
||||||
{
|
{
|
||||||
MSG msg;
|
MSG msg;
|
||||||
_GLFWwindow* window;
|
|
||||||
|
|
||||||
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
|
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
|
||||||
{
|
{
|
||||||
@@ -999,7 +1000,7 @@ void _glfwPlatformPollEvents(void)
|
|||||||
// While GLFW does not itself post WM_QUIT, other processes may post
|
// While GLFW does not itself post WM_QUIT, other processes may post
|
||||||
// it to this one, for example Task Manager
|
// it to this one, for example Task Manager
|
||||||
|
|
||||||
window = _glfw.windowListHead;
|
_GLFWwindow* window = _glfw.windowListHead;
|
||||||
while (window)
|
while (window)
|
||||||
{
|
{
|
||||||
_glfwInputWindowCloseRequest(window);
|
_glfwInputWindowCloseRequest(window);
|
||||||
@@ -1013,9 +1014,10 @@ void _glfwPlatformPollEvents(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window = _glfw.focusedWindow;
|
if (_glfw.cursorWindow)
|
||||||
if (window)
|
|
||||||
{
|
{
|
||||||
|
_GLFWwindow* window = _glfw.cursorWindow;
|
||||||
|
|
||||||
// LSHIFT/RSHIFT fixup (keys tend to "stick" without this fix)
|
// LSHIFT/RSHIFT fixup (keys tend to "stick" without this fix)
|
||||||
// This is the only async event handling in GLFW, but it solves some
|
// This is the only async event handling in GLFW, but it solves some
|
||||||
// nasty problems
|
// nasty problems
|
||||||
@@ -1035,14 +1037,20 @@ void _glfwPlatformPollEvents(void)
|
|||||||
_glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, 0, GLFW_RELEASE, mods);
|
_glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, 0, GLFW_RELEASE, mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Did the cursor move in an focused window that has disabled the cursor
|
|
||||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
_glfwPlatformGetWindowSize(window, &width, &height);
|
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||||
|
|
||||||
|
// NOTE: Re-center the cursor only if it has moved since the last
|
||||||
|
// call, to avoid breaking glfwWaitEvents with WM_MOUSEMOVE
|
||||||
|
if (window->win32.cursorPosX != width / 2 ||
|
||||||
|
window->win32.cursorPosY != height / 2)
|
||||||
|
{
|
||||||
_glfwPlatformSetCursorPos(window, width / 2, height / 2);
|
_glfwPlatformSetCursorPos(window, width / 2, height / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformWaitEvents(void)
|
void _glfwPlatformWaitEvents(void)
|
||||||
@@ -1188,19 +1196,24 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
|||||||
|
|
||||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
||||||
{
|
{
|
||||||
// It should be guaranteed that the cursor is not being used by this window if
|
POINT pos;
|
||||||
// the following condition is not met. That way it should be safe to destroy the
|
|
||||||
// cursor after calling glfwSetCursor(window, NULL) on all windows using the cursor.
|
if (_glfw.cursorWindow != window)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (window->cursorMode != GLFW_CURSOR_NORMAL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!GetCursorPos(&pos))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (WindowFromPoint(pos) != window->win32.handle)
|
||||||
|
return;
|
||||||
|
|
||||||
if (_glfw.focusedWindow == window &&
|
|
||||||
window->cursorMode == GLFW_CURSOR_NORMAL &&
|
|
||||||
window->win32.cursorInside)
|
|
||||||
{
|
|
||||||
if (cursor)
|
if (cursor)
|
||||||
SetCursor(cursor->win32.handle);
|
SetCursor(cursor->win32.handle);
|
||||||
else
|
else
|
||||||
SetCursor(LoadCursorW(NULL, IDC_ARROW));
|
SetCursor(LoadCursorW(NULL, IDC_ARROW));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
||||||
|
|||||||
+99
-132
@@ -40,7 +40,7 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLboolean focused)
|
|||||||
{
|
{
|
||||||
if (focused)
|
if (focused)
|
||||||
{
|
{
|
||||||
_glfw.focusedWindow = window;
|
_glfw.cursorWindow = window;
|
||||||
|
|
||||||
if (window->callbacks.focus)
|
if (window->callbacks.focus)
|
||||||
window->callbacks.focus((GLFWwindow*) window, focused);
|
window->callbacks.focus((GLFWwindow*) window, focused);
|
||||||
@@ -49,7 +49,7 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLboolean focused)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
_glfw.focusedWindow = NULL;
|
_glfw.cursorWindow = NULL;
|
||||||
|
|
||||||
if (window->callbacks.focus)
|
if (window->callbacks.focus)
|
||||||
window->callbacks.focus((GLFWwindow*) window, focused);
|
window->callbacks.focus((GLFWwindow*) window, focused);
|
||||||
@@ -132,46 +132,23 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up desired framebuffer config
|
fbconfig = _glfw.hints.framebuffer;
|
||||||
fbconfig.redBits = _glfw.hints.redBits;
|
ctxconfig = _glfw.hints.context;
|
||||||
fbconfig.greenBits = _glfw.hints.greenBits;
|
wndconfig = _glfw.hints.window;
|
||||||
fbconfig.blueBits = _glfw.hints.blueBits;
|
|
||||||
fbconfig.alphaBits = _glfw.hints.alphaBits;
|
|
||||||
fbconfig.depthBits = _glfw.hints.depthBits;
|
|
||||||
fbconfig.stencilBits = _glfw.hints.stencilBits;
|
|
||||||
fbconfig.accumRedBits = _glfw.hints.accumRedBits;
|
|
||||||
fbconfig.accumGreenBits = _glfw.hints.accumGreenBits;
|
|
||||||
fbconfig.accumBlueBits = _glfw.hints.accumBlueBits;
|
|
||||||
fbconfig.accumAlphaBits = _glfw.hints.accumAlphaBits;
|
|
||||||
fbconfig.auxBuffers = _glfw.hints.auxBuffers;
|
|
||||||
fbconfig.stereo = _glfw.hints.stereo ? GL_TRUE : GL_FALSE;
|
|
||||||
fbconfig.samples = _glfw.hints.samples;
|
|
||||||
fbconfig.sRGB = _glfw.hints.sRGB;
|
|
||||||
fbconfig.doublebuffer = _glfw.hints.doublebuffer ? GL_TRUE : GL_FALSE;
|
|
||||||
|
|
||||||
// Set up desired window config
|
|
||||||
wndconfig.width = width;
|
wndconfig.width = width;
|
||||||
wndconfig.height = height;
|
wndconfig.height = height;
|
||||||
wndconfig.title = title;
|
wndconfig.title = title;
|
||||||
wndconfig.resizable = _glfw.hints.resizable ? GL_TRUE : GL_FALSE;
|
|
||||||
wndconfig.visible = _glfw.hints.visible ? GL_TRUE : GL_FALSE;
|
|
||||||
wndconfig.decorated = _glfw.hints.decorated ? GL_TRUE : GL_FALSE;
|
|
||||||
wndconfig.focused = _glfw.hints.focused ? GL_TRUE : GL_FALSE;
|
|
||||||
wndconfig.autoIconify = _glfw.hints.autoIconify ? GL_TRUE : GL_FALSE;
|
|
||||||
wndconfig.floating = _glfw.hints.floating ? GL_TRUE : GL_FALSE;
|
|
||||||
wndconfig.monitor = (_GLFWmonitor*) monitor;
|
wndconfig.monitor = (_GLFWmonitor*) monitor;
|
||||||
|
|
||||||
// Set up desired context config
|
|
||||||
ctxconfig.api = _glfw.hints.api;
|
|
||||||
ctxconfig.major = _glfw.hints.major;
|
|
||||||
ctxconfig.minor = _glfw.hints.minor;
|
|
||||||
ctxconfig.forward = _glfw.hints.forward ? GL_TRUE : GL_FALSE;
|
|
||||||
ctxconfig.debug = _glfw.hints.debug ? GL_TRUE : GL_FALSE;
|
|
||||||
ctxconfig.profile = _glfw.hints.profile;
|
|
||||||
ctxconfig.robustness = _glfw.hints.robustness;
|
|
||||||
ctxconfig.release = _glfw.hints.release;
|
|
||||||
ctxconfig.share = (_GLFWwindow*) share;
|
ctxconfig.share = (_GLFWwindow*) share;
|
||||||
|
|
||||||
|
if (wndconfig.monitor)
|
||||||
|
{
|
||||||
|
wndconfig.resizable = GL_TRUE;
|
||||||
|
wndconfig.visible = GL_TRUE;
|
||||||
|
wndconfig.focused = GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
// Check the OpenGL bits of the window config
|
// Check the OpenGL bits of the window config
|
||||||
if (!_glfwIsValidContextConfig(&ctxconfig))
|
if (!_glfwIsValidContextConfig(&ctxconfig))
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -180,23 +157,13 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
|||||||
window->next = _glfw.windowListHead;
|
window->next = _glfw.windowListHead;
|
||||||
_glfw.windowListHead = window;
|
_glfw.windowListHead = window;
|
||||||
|
|
||||||
if (wndconfig.monitor)
|
|
||||||
{
|
|
||||||
wndconfig.resizable = GL_TRUE;
|
|
||||||
wndconfig.visible = GL_TRUE;
|
|
||||||
wndconfig.focused = GL_TRUE;
|
|
||||||
|
|
||||||
// Set up desired video mode
|
|
||||||
window->videoMode.width = width;
|
window->videoMode.width = width;
|
||||||
window->videoMode.height = height;
|
window->videoMode.height = height;
|
||||||
window->videoMode.redBits = _glfw.hints.redBits;
|
window->videoMode.redBits = fbconfig.redBits;
|
||||||
window->videoMode.greenBits = _glfw.hints.greenBits;
|
window->videoMode.greenBits = fbconfig.greenBits;
|
||||||
window->videoMode.blueBits = _glfw.hints.blueBits;
|
window->videoMode.blueBits = fbconfig.blueBits;
|
||||||
window->videoMode.refreshRate = _glfw.hints.refreshRate;
|
window->videoMode.refreshRate = _glfw.hints.refreshRate;
|
||||||
}
|
|
||||||
|
|
||||||
// Transfer window hints that are persistent settings and not
|
|
||||||
// just initial states
|
|
||||||
window->monitor = wndconfig.monitor;
|
window->monitor = wndconfig.monitor;
|
||||||
window->resizable = wndconfig.resizable;
|
window->resizable = wndconfig.resizable;
|
||||||
window->decorated = wndconfig.decorated;
|
window->decorated = wndconfig.decorated;
|
||||||
@@ -235,7 +202,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
|||||||
|
|
||||||
// Clearing the front buffer to black to avoid garbage pixels left over
|
// Clearing the front buffer to black to avoid garbage pixels left over
|
||||||
// from previous uses of our bit of VRAM
|
// from previous uses of our bit of VRAM
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
window->Clear(GL_COLOR_BUFFER_BIT);
|
||||||
_glfwPlatformSwapBuffers(window);
|
_glfwPlatformSwapBuffers(window);
|
||||||
|
|
||||||
// Restore the previously current context (or NULL)
|
// Restore the previously current context (or NULL)
|
||||||
@@ -272,29 +239,29 @@ void glfwDefaultWindowHints(void)
|
|||||||
memset(&_glfw.hints, 0, sizeof(_glfw.hints));
|
memset(&_glfw.hints, 0, sizeof(_glfw.hints));
|
||||||
|
|
||||||
// The default is OpenGL with minimum version 1.0
|
// The default is OpenGL with minimum version 1.0
|
||||||
_glfw.hints.api = GLFW_OPENGL_API;
|
_glfw.hints.context.api = GLFW_OPENGL_API;
|
||||||
_glfw.hints.major = 1;
|
_glfw.hints.context.major = 1;
|
||||||
_glfw.hints.minor = 0;
|
_glfw.hints.context.minor = 0;
|
||||||
|
|
||||||
// The default is a focused, visible, resizable window with decorations
|
// The default is a focused, visible, resizable window with decorations
|
||||||
_glfw.hints.resizable = GL_TRUE;
|
_glfw.hints.window.resizable = GL_TRUE;
|
||||||
_glfw.hints.visible = GL_TRUE;
|
_glfw.hints.window.visible = GL_TRUE;
|
||||||
_glfw.hints.decorated = GL_TRUE;
|
_glfw.hints.window.decorated = GL_TRUE;
|
||||||
_glfw.hints.focused = GL_TRUE;
|
_glfw.hints.window.focused = GL_TRUE;
|
||||||
_glfw.hints.autoIconify = GL_TRUE;
|
_glfw.hints.window.autoIconify = GL_TRUE;
|
||||||
|
|
||||||
// The default is to select the highest available refresh rate
|
|
||||||
_glfw.hints.refreshRate = GLFW_DONT_CARE;
|
|
||||||
|
|
||||||
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
|
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
|
||||||
// double buffered
|
// double buffered
|
||||||
_glfw.hints.redBits = 8;
|
_glfw.hints.framebuffer.redBits = 8;
|
||||||
_glfw.hints.greenBits = 8;
|
_glfw.hints.framebuffer.greenBits = 8;
|
||||||
_glfw.hints.blueBits = 8;
|
_glfw.hints.framebuffer.blueBits = 8;
|
||||||
_glfw.hints.alphaBits = 8;
|
_glfw.hints.framebuffer.alphaBits = 8;
|
||||||
_glfw.hints.depthBits = 24;
|
_glfw.hints.framebuffer.depthBits = 24;
|
||||||
_glfw.hints.stencilBits = 8;
|
_glfw.hints.framebuffer.stencilBits = 8;
|
||||||
_glfw.hints.doublebuffer = GL_TRUE;
|
_glfw.hints.framebuffer.doublebuffer = GL_TRUE;
|
||||||
|
|
||||||
|
// The default is to select the highest available refresh rate
|
||||||
|
_glfw.hints.refreshRate = GLFW_DONT_CARE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwWindowHint(int target, int hint)
|
GLFWAPI void glfwWindowHint(int target, int hint)
|
||||||
@@ -304,95 +271,95 @@ GLFWAPI void glfwWindowHint(int target, int hint)
|
|||||||
switch (target)
|
switch (target)
|
||||||
{
|
{
|
||||||
case GLFW_RED_BITS:
|
case GLFW_RED_BITS:
|
||||||
_glfw.hints.redBits = hint;
|
_glfw.hints.framebuffer.redBits = hint;
|
||||||
break;
|
break;
|
||||||
case GLFW_GREEN_BITS:
|
case GLFW_GREEN_BITS:
|
||||||
_glfw.hints.greenBits = hint;
|
_glfw.hints.framebuffer.greenBits = hint;
|
||||||
break;
|
break;
|
||||||
case GLFW_BLUE_BITS:
|
case GLFW_BLUE_BITS:
|
||||||
_glfw.hints.blueBits = hint;
|
_glfw.hints.framebuffer.blueBits = hint;
|
||||||
break;
|
break;
|
||||||
case GLFW_ALPHA_BITS:
|
case GLFW_ALPHA_BITS:
|
||||||
_glfw.hints.alphaBits = hint;
|
_glfw.hints.framebuffer.alphaBits = hint;
|
||||||
break;
|
break;
|
||||||
case GLFW_DEPTH_BITS:
|
case GLFW_DEPTH_BITS:
|
||||||
_glfw.hints.depthBits = hint;
|
_glfw.hints.framebuffer.depthBits = hint;
|
||||||
break;
|
break;
|
||||||
case GLFW_STENCIL_BITS:
|
case GLFW_STENCIL_BITS:
|
||||||
_glfw.hints.stencilBits = hint;
|
_glfw.hints.framebuffer.stencilBits = hint;
|
||||||
break;
|
break;
|
||||||
case GLFW_ACCUM_RED_BITS:
|
case GLFW_ACCUM_RED_BITS:
|
||||||
_glfw.hints.accumRedBits = hint;
|
_glfw.hints.framebuffer.accumRedBits = hint;
|
||||||
break;
|
break;
|
||||||
case GLFW_ACCUM_GREEN_BITS:
|
case GLFW_ACCUM_GREEN_BITS:
|
||||||
_glfw.hints.accumGreenBits = hint;
|
_glfw.hints.framebuffer.accumGreenBits = hint;
|
||||||
break;
|
break;
|
||||||
case GLFW_ACCUM_BLUE_BITS:
|
case GLFW_ACCUM_BLUE_BITS:
|
||||||
_glfw.hints.accumBlueBits = hint;
|
_glfw.hints.framebuffer.accumBlueBits = hint;
|
||||||
break;
|
break;
|
||||||
case GLFW_ACCUM_ALPHA_BITS:
|
case GLFW_ACCUM_ALPHA_BITS:
|
||||||
_glfw.hints.accumAlphaBits = hint;
|
_glfw.hints.framebuffer.accumAlphaBits = hint;
|
||||||
break;
|
break;
|
||||||
case GLFW_AUX_BUFFERS:
|
case GLFW_AUX_BUFFERS:
|
||||||
_glfw.hints.auxBuffers = hint;
|
_glfw.hints.framebuffer.auxBuffers = hint;
|
||||||
break;
|
break;
|
||||||
case GLFW_STEREO:
|
case GLFW_STEREO:
|
||||||
_glfw.hints.stereo = hint;
|
_glfw.hints.framebuffer.stereo = hint ? GL_TRUE : GL_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_DOUBLEBUFFER:
|
||||||
|
_glfw.hints.framebuffer.doublebuffer = hint ? GL_TRUE : GL_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_SAMPLES:
|
||||||
|
_glfw.hints.framebuffer.samples = hint;
|
||||||
|
break;
|
||||||
|
case GLFW_SRGB_CAPABLE:
|
||||||
|
_glfw.hints.framebuffer.sRGB = hint ? GL_TRUE : GL_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_RESIZABLE:
|
||||||
|
_glfw.hints.window.resizable = hint ? GL_TRUE : GL_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_DECORATED:
|
||||||
|
_glfw.hints.window.decorated = hint ? GL_TRUE : GL_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_FOCUSED:
|
||||||
|
_glfw.hints.window.focused = hint ? GL_TRUE : GL_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_AUTO_ICONIFY:
|
||||||
|
_glfw.hints.window.autoIconify = hint ? GL_TRUE : GL_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_FLOATING:
|
||||||
|
_glfw.hints.window.floating = hint ? GL_TRUE : GL_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_VISIBLE:
|
||||||
|
_glfw.hints.window.visible = hint ? GL_TRUE : GL_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_CLIENT_API:
|
||||||
|
_glfw.hints.context.api = hint;
|
||||||
|
break;
|
||||||
|
case GLFW_CONTEXT_VERSION_MAJOR:
|
||||||
|
_glfw.hints.context.major = hint;
|
||||||
|
break;
|
||||||
|
case GLFW_CONTEXT_VERSION_MINOR:
|
||||||
|
_glfw.hints.context.minor = hint;
|
||||||
|
break;
|
||||||
|
case GLFW_CONTEXT_ROBUSTNESS:
|
||||||
|
_glfw.hints.context.robustness = hint;
|
||||||
|
break;
|
||||||
|
case GLFW_OPENGL_FORWARD_COMPAT:
|
||||||
|
_glfw.hints.context.forward = hint ? GL_TRUE : GL_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_OPENGL_DEBUG_CONTEXT:
|
||||||
|
_glfw.hints.context.debug = hint ? GL_TRUE : GL_FALSE;
|
||||||
|
break;
|
||||||
|
case GLFW_OPENGL_PROFILE:
|
||||||
|
_glfw.hints.context.profile = hint;
|
||||||
|
break;
|
||||||
|
case GLFW_CONTEXT_RELEASE_BEHAVIOR:
|
||||||
|
_glfw.hints.context.release = hint;
|
||||||
break;
|
break;
|
||||||
case GLFW_REFRESH_RATE:
|
case GLFW_REFRESH_RATE:
|
||||||
_glfw.hints.refreshRate = hint;
|
_glfw.hints.refreshRate = hint;
|
||||||
break;
|
break;
|
||||||
case GLFW_DOUBLEBUFFER:
|
|
||||||
_glfw.hints.doublebuffer = hint;
|
|
||||||
break;
|
|
||||||
case GLFW_RESIZABLE:
|
|
||||||
_glfw.hints.resizable = hint;
|
|
||||||
break;
|
|
||||||
case GLFW_DECORATED:
|
|
||||||
_glfw.hints.decorated = hint;
|
|
||||||
break;
|
|
||||||
case GLFW_FOCUSED:
|
|
||||||
_glfw.hints.focused = hint;
|
|
||||||
break;
|
|
||||||
case GLFW_AUTO_ICONIFY:
|
|
||||||
_glfw.hints.autoIconify = hint;
|
|
||||||
break;
|
|
||||||
case GLFW_FLOATING:
|
|
||||||
_glfw.hints.floating = hint;
|
|
||||||
break;
|
|
||||||
case GLFW_VISIBLE:
|
|
||||||
_glfw.hints.visible = hint;
|
|
||||||
break;
|
|
||||||
case GLFW_SAMPLES:
|
|
||||||
_glfw.hints.samples = hint;
|
|
||||||
break;
|
|
||||||
case GLFW_SRGB_CAPABLE:
|
|
||||||
_glfw.hints.sRGB = hint;
|
|
||||||
break;
|
|
||||||
case GLFW_CLIENT_API:
|
|
||||||
_glfw.hints.api = hint;
|
|
||||||
break;
|
|
||||||
case GLFW_CONTEXT_VERSION_MAJOR:
|
|
||||||
_glfw.hints.major = hint;
|
|
||||||
break;
|
|
||||||
case GLFW_CONTEXT_VERSION_MINOR:
|
|
||||||
_glfw.hints.minor = hint;
|
|
||||||
break;
|
|
||||||
case GLFW_CONTEXT_ROBUSTNESS:
|
|
||||||
_glfw.hints.robustness = hint;
|
|
||||||
break;
|
|
||||||
case GLFW_OPENGL_FORWARD_COMPAT:
|
|
||||||
_glfw.hints.forward = hint;
|
|
||||||
break;
|
|
||||||
case GLFW_OPENGL_DEBUG_CONTEXT:
|
|
||||||
_glfw.hints.debug = hint;
|
|
||||||
break;
|
|
||||||
case GLFW_OPENGL_PROFILE:
|
|
||||||
_glfw.hints.profile = hint;
|
|
||||||
break;
|
|
||||||
case GLFW_CONTEXT_RELEASE_BEHAVIOR:
|
|
||||||
_glfw.hints.release = hint;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint");
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint");
|
||||||
break;
|
break;
|
||||||
@@ -418,8 +385,8 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
|
|||||||
_glfwPlatformMakeContextCurrent(NULL);
|
_glfwPlatformMakeContextCurrent(NULL);
|
||||||
|
|
||||||
// Clear the focused window pointer if this is the focused window
|
// Clear the focused window pointer if this is the focused window
|
||||||
if (_glfw.focusedWindow == window)
|
if (_glfw.cursorWindow == window)
|
||||||
_glfw.focusedWindow = NULL;
|
_glfw.cursorWindow = NULL;
|
||||||
|
|
||||||
_glfwPlatformDestroyWindow(window);
|
_glfwPlatformDestroyWindow(window);
|
||||||
|
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _winmm_joystick_h_
|
#ifndef _glfw3_winmm_joystick_h_
|
||||||
#define _winmm_joystick_h_
|
#define _glfw3_winmm_joystick_h_
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
|
||||||
_GLFWjoystickWinMM winmm_js[GLFW_JOYSTICK_LAST + 1]
|
_GLFWjoystickWinMM winmm_js[GLFW_JOYSTICK_LAST + 1]
|
||||||
@@ -44,4 +44,4 @@ typedef struct _GLFWjoystickWinMM
|
|||||||
void _glfwInitJoysticks(void);
|
void _glfwInitJoysticks(void);
|
||||||
void _glfwTerminateJoysticks(void);
|
void _glfwTerminateJoysticks(void);
|
||||||
|
|
||||||
#endif // _winmm_joystick_h_
|
#endif // _glfw3_winmm_joystick_h_
|
||||||
|
|||||||
+11
-4
@@ -35,7 +35,6 @@
|
|||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <wayland-cursor.h>
|
#include <wayland-cursor.h>
|
||||||
|
|
||||||
#include "xkb_unicode.h"
|
|
||||||
|
|
||||||
static void pointerHandleEnter(void* data,
|
static void pointerHandleEnter(void* data,
|
||||||
struct wl_pointer* pointer,
|
struct wl_pointer* pointer,
|
||||||
@@ -86,6 +85,11 @@ static void pointerHandleMotion(void* data,
|
|||||||
"Wayland: GLFW_CURSOR_DISABLED not supported");
|
"Wayland: GLFW_CURSOR_DISABLED not supported");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window->wl.cursorPosX = wl_fixed_to_double(sx);
|
||||||
|
window->wl.cursorPosY = wl_fixed_to_double(sy);
|
||||||
|
}
|
||||||
|
|
||||||
_glfwInputCursorMotion(window,
|
_glfwInputCursorMotion(window,
|
||||||
wl_fixed_to_double(sx),
|
wl_fixed_to_double(sx),
|
||||||
@@ -616,15 +620,18 @@ void _glfwPlatformTerminate(void)
|
|||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
{
|
{
|
||||||
const char* version = _GLFW_VERSION_NUMBER " Wayland EGL "
|
return _GLFW_VERSION_NUMBER " Wayland EGL"
|
||||||
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
|
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
|
||||||
" clock_gettime"
|
" clock_gettime"
|
||||||
|
#else
|
||||||
|
" gettimeofday"
|
||||||
|
#endif
|
||||||
|
#if defined(__linux__)
|
||||||
|
" /dev/js"
|
||||||
#endif
|
#endif
|
||||||
#if defined(_GLFW_BUILD_DLL)
|
#if defined(_GLFW_BUILD_DLL)
|
||||||
" shared"
|
" shared"
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
|
||||||
return version;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-8
@@ -24,23 +24,23 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _wayland_platform_h_
|
#ifndef _glfw3_wayland_platform_h_
|
||||||
#define _wayland_platform_h_
|
#define _glfw3_wayland_platform_h_
|
||||||
|
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
|
#include "posix_tls.h"
|
||||||
|
#include "posix_time.h"
|
||||||
|
#include "linux_joystick.h"
|
||||||
|
#include "xkb_unicode.h"
|
||||||
|
|
||||||
#if defined(_GLFW_EGL)
|
#if defined(_GLFW_EGL)
|
||||||
#include "egl_context.h"
|
#include "egl_context.h"
|
||||||
#else
|
#else
|
||||||
#error "The Wayland backend depends on EGL platform support"
|
#error "The Wayland backend depends on EGL platform support"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "posix_tls.h"
|
|
||||||
#include "posix_time.h"
|
|
||||||
#include "linux_joystick.h"
|
|
||||||
|
|
||||||
#define _GLFW_EGL_NATIVE_WINDOW window->wl.native
|
#define _GLFW_EGL_NATIVE_WINDOW window->wl.native
|
||||||
#define _GLFW_EGL_NATIVE_DISPLAY _glfw.wl.display
|
#define _GLFW_EGL_NATIVE_DISPLAY _glfw.wl.display
|
||||||
|
|
||||||
@@ -66,6 +66,7 @@ typedef struct _GLFWwindowWayland
|
|||||||
struct wl_shell_surface* shell_surface;
|
struct wl_shell_surface* shell_surface;
|
||||||
struct wl_callback* callback;
|
struct wl_callback* callback;
|
||||||
_GLFWcursor* currentCursor;
|
_GLFWcursor* currentCursor;
|
||||||
|
double cursorPosX, cursorPosY;
|
||||||
} _GLFWwindowWayland;
|
} _GLFWwindowWayland;
|
||||||
|
|
||||||
|
|
||||||
@@ -137,4 +138,4 @@ typedef struct _GLFWcursorWayland
|
|||||||
|
|
||||||
void _glfwAddOutput(uint32_t name, uint32_t version);
|
void _glfwAddOutput(uint32_t name, uint32_t version);
|
||||||
|
|
||||||
#endif // _wayland_platform_h_
|
#endif // _glfw3_wayland_platform_h_
|
||||||
|
|||||||
+44
-37
@@ -114,6 +114,43 @@ createTmpfileCloexec(char* tmpname)
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handleEvents(int timeout)
|
||||||
|
{
|
||||||
|
struct wl_display* display = _glfw.wl.display;
|
||||||
|
struct pollfd fds[] = {
|
||||||
|
{ wl_display_get_fd(display), POLLIN },
|
||||||
|
};
|
||||||
|
|
||||||
|
while (wl_display_prepare_read(display) != 0)
|
||||||
|
wl_display_dispatch_pending(display);
|
||||||
|
|
||||||
|
// If an error different from EAGAIN happens, we have likely been
|
||||||
|
// disconnected from the Wayland session, try to handle that the best we
|
||||||
|
// can.
|
||||||
|
if (wl_display_flush(display) < 0 && errno != EAGAIN)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = _glfw.windowListHead;
|
||||||
|
while (window)
|
||||||
|
{
|
||||||
|
_glfwInputWindowCloseRequest(window);
|
||||||
|
window = window->next;
|
||||||
|
}
|
||||||
|
wl_display_cancel_read(display);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (poll(fds, 1, timeout) > 0)
|
||||||
|
{
|
||||||
|
wl_display_read_events(display);
|
||||||
|
wl_display_dispatch_pending(display);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wl_display_cancel_read(display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a new, unique, anonymous file of the given size, and
|
* Create a new, unique, anonymous file of the given size, and
|
||||||
* return the file descriptor for it. The file descriptor is set
|
* return the file descriptor for it. The file descriptor is set
|
||||||
@@ -150,7 +187,7 @@ createAnonymousFile(off_t size)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
name = malloc(strlen(path) + sizeof(template));
|
name = calloc(strlen(path) + sizeof(template), 1);
|
||||||
strcpy(name, path);
|
strcpy(name, path);
|
||||||
strcat(name, template);
|
strcat(name, template);
|
||||||
|
|
||||||
@@ -327,44 +364,12 @@ int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformPollEvents(void)
|
void _glfwPlatformPollEvents(void)
|
||||||
{
|
{
|
||||||
struct wl_display* display = _glfw.wl.display;
|
handleEvents(0);
|
||||||
struct pollfd fds[] = {
|
|
||||||
{ wl_display_get_fd(display), POLLIN },
|
|
||||||
};
|
|
||||||
|
|
||||||
while (wl_display_prepare_read(display) != 0)
|
|
||||||
wl_display_dispatch_pending(display);
|
|
||||||
wl_display_flush(display);
|
|
||||||
if (poll(fds, 1, 0) > 0)
|
|
||||||
{
|
|
||||||
wl_display_read_events(display);
|
|
||||||
wl_display_dispatch_pending(display);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wl_display_cancel_read(display);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformWaitEvents(void)
|
void _glfwPlatformWaitEvents(void)
|
||||||
{
|
{
|
||||||
struct wl_display* display = _glfw.wl.display;
|
handleEvents(-1);
|
||||||
struct pollfd fds[] = {
|
|
||||||
{ wl_display_get_fd(display), POLLIN },
|
|
||||||
};
|
|
||||||
|
|
||||||
while (wl_display_prepare_read(display) != 0)
|
|
||||||
wl_display_dispatch_pending(display);
|
|
||||||
wl_display_flush(display);
|
|
||||||
if (poll(fds, 1, -1) > 0)
|
|
||||||
{
|
|
||||||
wl_display_read_events(display);
|
|
||||||
wl_display_dispatch_pending(display);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wl_display_cancel_read(display);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformPostEmptyEvent(void)
|
void _glfwPlatformPostEmptyEvent(void)
|
||||||
@@ -374,8 +379,10 @@ void _glfwPlatformPostEmptyEvent(void)
|
|||||||
|
|
||||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||||
{
|
{
|
||||||
// TODO
|
if (xpos)
|
||||||
fprintf(stderr, "_glfwPlatformGetCursorPos not implemented yet\n");
|
*xpos = window->wl.cursorPosX;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = window->wl.cursorPosY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
|
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
|
||||||
|
|||||||
+51
-43
@@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
// Translate an X11 key code to a GLFW key code.
|
// Translate an X11 key code to a GLFW key code.
|
||||||
//
|
//
|
||||||
static int translateKey(int scancode)
|
static int translateKeyCode(int scancode)
|
||||||
{
|
{
|
||||||
int keySym;
|
int keySym;
|
||||||
|
|
||||||
@@ -241,15 +241,14 @@ static void createKeyTables(void)
|
|||||||
// keyboard layout
|
// keyboard layout
|
||||||
|
|
||||||
char name[XkbKeyNameLength + 1];
|
char name[XkbKeyNameLength + 1];
|
||||||
XkbDescPtr descr = XkbGetKeyboard(_glfw.x11.display,
|
XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd);
|
||||||
XkbAllComponentsMask,
|
XkbGetNames(_glfw.x11.display, XkbKeyNamesMask, desc);
|
||||||
XkbUseCoreKbd);
|
|
||||||
|
|
||||||
// Find the X11 key code -> GLFW key code mapping
|
// Find the X11 key code -> GLFW key code mapping
|
||||||
for (scancode = descr->min_key_code; scancode <= descr->max_key_code; scancode++)
|
for (scancode = desc->min_key_code; scancode <= desc->max_key_code; scancode++)
|
||||||
{
|
{
|
||||||
memcpy(name, descr->names->keys[scancode].name, XkbKeyNameLength);
|
memcpy(name, desc->names->keys[scancode].name, XkbKeyNameLength);
|
||||||
name[XkbKeyNameLength] = 0;
|
name[XkbKeyNameLength] = '\0';
|
||||||
|
|
||||||
// Map the key name to a GLFW key code. Note: We only map printable
|
// Map the key name to a GLFW key code. Note: We only map printable
|
||||||
// keys here, and we use the US keyboard layout. The rest of the
|
// keys here, and we use the US keyboard layout. The rest of the
|
||||||
@@ -309,7 +308,8 @@ static void createKeyTables(void)
|
|||||||
_glfw.x11.publicKeys[scancode] = key;
|
_glfw.x11.publicKeys[scancode] = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
XkbFreeKeyboard(descr, 0, True);
|
XkbFreeNames(desc, XkbKeyNamesMask, True);
|
||||||
|
XkbFreeClientMap(desc, 0, True);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate the un-translated key codes using traditional X11 KeySym
|
// Translate the un-translated key codes using traditional X11 KeySym
|
||||||
@@ -317,7 +317,7 @@ static void createKeyTables(void)
|
|||||||
for (scancode = 0; scancode < 256; scancode++)
|
for (scancode = 0; scancode < 256; scancode++)
|
||||||
{
|
{
|
||||||
if (_glfw.x11.publicKeys[scancode] < 0)
|
if (_glfw.x11.publicKeys[scancode] < 0)
|
||||||
_glfw.x11.publicKeys[scancode] = translateKey(scancode);
|
_glfw.x11.publicKeys[scancode] = translateKeyCode(scancode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,8 +459,6 @@ static void detectEWMH(void)
|
|||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_BYPASS_COMPOSITOR");
|
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_BYPASS_COMPOSITOR");
|
||||||
|
|
||||||
XFree(supportedAtoms);
|
XFree(supportedAtoms);
|
||||||
|
|
||||||
_glfw.x11.hasEWMH = GL_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize X11 display and look for supported X11 extensions
|
// Initialize X11 display and look for supported X11 extensions
|
||||||
@@ -498,8 +496,8 @@ static GLboolean initExtensions(void)
|
|||||||
XRRScreenResources* sr;
|
XRRScreenResources* sr;
|
||||||
|
|
||||||
if (!XRRQueryVersion(_glfw.x11.display,
|
if (!XRRQueryVersion(_glfw.x11.display,
|
||||||
&_glfw.x11.randr.versionMajor,
|
&_glfw.x11.randr.major,
|
||||||
&_glfw.x11.randr.versionMinor))
|
&_glfw.x11.randr.minor))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"X11: Failed to query RandR version");
|
"X11: Failed to query RandR version");
|
||||||
@@ -507,11 +505,8 @@ static GLboolean initExtensions(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The GLFW RandR path requires at least version 1.3
|
// The GLFW RandR path requires at least version 1.3
|
||||||
if (_glfw.x11.randr.versionMajor == 1 &&
|
if (_glfw.x11.randr.major == 1 && _glfw.x11.randr.minor < 3)
|
||||||
_glfw.x11.randr.versionMinor < 3)
|
|
||||||
{
|
|
||||||
_glfw.x11.randr.available = GL_FALSE;
|
_glfw.x11.randr.available = GL_FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root);
|
sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root);
|
||||||
|
|
||||||
@@ -530,8 +525,8 @@ static GLboolean initExtensions(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (XineramaQueryExtension(_glfw.x11.display,
|
if (XineramaQueryExtension(_glfw.x11.display,
|
||||||
&_glfw.x11.xinerama.versionMajor,
|
&_glfw.x11.xinerama.major,
|
||||||
&_glfw.x11.xinerama.versionMinor))
|
&_glfw.x11.xinerama.minor))
|
||||||
{
|
{
|
||||||
if (XineramaIsActive(_glfw.x11.display))
|
if (XineramaIsActive(_glfw.x11.display))
|
||||||
_glfw.x11.xinerama.available = GL_TRUE;
|
_glfw.x11.xinerama.available = GL_TRUE;
|
||||||
@@ -544,12 +539,12 @@ static GLboolean initExtensions(void)
|
|||||||
&_glfw.x11.xi.eventBase,
|
&_glfw.x11.xi.eventBase,
|
||||||
&_glfw.x11.xi.errorBase))
|
&_glfw.x11.xi.errorBase))
|
||||||
{
|
{
|
||||||
_glfw.x11.xi.versionMajor = 2;
|
_glfw.x11.xi.major = 2;
|
||||||
_glfw.x11.xi.versionMinor = 0;
|
_glfw.x11.xi.minor = 0;
|
||||||
|
|
||||||
if (XIQueryVersion(_glfw.x11.display,
|
if (XIQueryVersion(_glfw.x11.display,
|
||||||
&_glfw.x11.xi.versionMajor,
|
&_glfw.x11.xi.major,
|
||||||
&_glfw.x11.xi.versionMinor) != BadRequest)
|
&_glfw.x11.xi.minor) != BadRequest)
|
||||||
{
|
{
|
||||||
_glfw.x11.xi.available = GL_TRUE;
|
_glfw.x11.xi.available = GL_TRUE;
|
||||||
}
|
}
|
||||||
@@ -557,15 +552,15 @@ static GLboolean initExtensions(void)
|
|||||||
#endif /*_GLFW_HAS_XINPUT*/
|
#endif /*_GLFW_HAS_XINPUT*/
|
||||||
|
|
||||||
// Check if Xkb is supported on this display
|
// Check if Xkb is supported on this display
|
||||||
_glfw.x11.xkb.versionMajor = 1;
|
_glfw.x11.xkb.major = 1;
|
||||||
_glfw.x11.xkb.versionMinor = 0;
|
_glfw.x11.xkb.minor = 0;
|
||||||
_glfw.x11.xkb.available =
|
_glfw.x11.xkb.available =
|
||||||
XkbQueryExtension(_glfw.x11.display,
|
XkbQueryExtension(_glfw.x11.display,
|
||||||
&_glfw.x11.xkb.majorOpcode,
|
&_glfw.x11.xkb.majorOpcode,
|
||||||
&_glfw.x11.xkb.eventBase,
|
&_glfw.x11.xkb.eventBase,
|
||||||
&_glfw.x11.xkb.errorBase,
|
&_glfw.x11.xkb.errorBase,
|
||||||
&_glfw.x11.xkb.versionMajor,
|
&_glfw.x11.xkb.major,
|
||||||
&_glfw.x11.xkb.versionMinor);
|
&_glfw.x11.xkb.minor);
|
||||||
|
|
||||||
if (_glfw.x11.xkb.available)
|
if (_glfw.x11.xkb.available)
|
||||||
{
|
{
|
||||||
@@ -714,17 +709,30 @@ Cursor _glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)
|
|||||||
|
|
||||||
int _glfwPlatformInit(void)
|
int _glfwPlatformInit(void)
|
||||||
{
|
{
|
||||||
|
#if !defined(X_HAVE_UTF8_STRING)
|
||||||
// HACK: If the current locale is C, apply the environment's locale
|
// HACK: If the current locale is C, apply the environment's locale
|
||||||
// This is done because the C locale breaks character input
|
// This is done because the C locale breaks wide character input
|
||||||
if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0)
|
if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0)
|
||||||
setlocale(LC_CTYPE, "");
|
setlocale(LC_CTYPE, "");
|
||||||
|
#endif
|
||||||
|
|
||||||
XInitThreads();
|
XInitThreads();
|
||||||
|
|
||||||
_glfw.x11.display = XOpenDisplay(NULL);
|
_glfw.x11.display = XOpenDisplay(NULL);
|
||||||
if (!_glfw.x11.display)
|
if (!_glfw.x11.display)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to open X display");
|
const char* display = getenv("DISPLAY");
|
||||||
|
if (display)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"X11: Failed to open display %s", display);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"X11: The DISPLAY environment variable is missing");
|
||||||
|
}
|
||||||
|
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -741,7 +749,7 @@ int _glfwPlatformInit(void)
|
|||||||
{
|
{
|
||||||
XSetLocaleModifiers("");
|
XSetLocaleModifiers("");
|
||||||
|
|
||||||
_glfw.x11.im = XOpenIM(_glfw.x11.display, 0, 0, 0);
|
_glfw.x11.im = XOpenIM(_glfw.x11.display, 0, NULL, NULL);
|
||||||
if (_glfw.x11.im)
|
if (_glfw.x11.im)
|
||||||
{
|
{
|
||||||
if (!hasUsableInputMethodStyle())
|
if (!hasUsableInputMethodStyle())
|
||||||
@@ -780,43 +788,43 @@ void _glfwPlatformTerminate(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
_glfwTerminateJoysticks();
|
_glfwTerminateJoysticks();
|
||||||
_glfwTerminateContextAPI();
|
|
||||||
|
|
||||||
if (_glfw.x11.display)
|
if (_glfw.x11.display)
|
||||||
{
|
{
|
||||||
XCloseDisplay(_glfw.x11.display);
|
XCloseDisplay(_glfw.x11.display);
|
||||||
_glfw.x11.display = NULL;
|
_glfw.x11.display = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: This needs to be done after XCloseDisplay, as libGL registers
|
||||||
|
// internal cleanup callbacks in libX11
|
||||||
|
_glfwTerminateContextAPI();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
{
|
{
|
||||||
const char* version = _GLFW_VERSION_NUMBER " X11"
|
return _GLFW_VERSION_NUMBER " X11"
|
||||||
#if defined(_GLFW_GLX)
|
#if defined(_GLFW_GLX)
|
||||||
" GLX"
|
" GLX"
|
||||||
#elif defined(_GLFW_EGL)
|
#elif defined(_GLFW_EGL)
|
||||||
" EGL"
|
" EGL"
|
||||||
#endif
|
#endif
|
||||||
#if defined(_GLFW_HAS_GLXGETPROCADDRESS)
|
|
||||||
" glXGetProcAddress"
|
|
||||||
#elif defined(_GLFW_HAS_GLXGETPROCADDRESSARB)
|
|
||||||
" glXGetProcAddressARB"
|
|
||||||
#elif defined(_GLFW_HAS_GLXGETPROCADDRESSEXT)
|
|
||||||
" glXGetProcAddressEXT"
|
|
||||||
#elif defined(_GLFW_DLOPEN_LIBGL)
|
|
||||||
" dlsym(libGL)"
|
|
||||||
#endif
|
|
||||||
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
|
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
|
||||||
" clock_gettime"
|
" clock_gettime"
|
||||||
|
#else
|
||||||
|
" gettimeofday"
|
||||||
#endif
|
#endif
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
" /dev/js"
|
" /dev/js"
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(_GLFW_HAS_XINPUT)
|
||||||
|
" XI"
|
||||||
|
#endif
|
||||||
|
#if defined(_GLFW_HAS_XF86VM)
|
||||||
|
" Xf86vm"
|
||||||
|
#endif
|
||||||
#if defined(_GLFW_BUILD_DLL)
|
#if defined(_GLFW_BUILD_DLL)
|
||||||
" shared"
|
" shared"
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
|
||||||
return version;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
-26
@@ -200,7 +200,7 @@ void _glfwRestoreVideoMode(_GLFWmonitor* monitor)
|
|||||||
|
|
||||||
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
||||||
{
|
{
|
||||||
int i, j, k, size = 0, found = 0;
|
int i, j, k, found = 0;
|
||||||
_GLFWmonitor** monitors = NULL;
|
_GLFWmonitor** monitors = NULL;
|
||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
@@ -214,6 +214,8 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
|||||||
RROutput primary = XRRGetOutputPrimary(_glfw.x11.display,
|
RROutput primary = XRRGetOutputPrimary(_glfw.x11.display,
|
||||||
_glfw.x11.root);
|
_glfw.x11.root);
|
||||||
|
|
||||||
|
monitors = calloc(sr->noutput, sizeof(_GLFWmonitor*));
|
||||||
|
|
||||||
if (_glfw.x11.xinerama.available)
|
if (_glfw.x11.xinerama.available)
|
||||||
screens = XineramaQueryScreens(_glfw.x11.display, &screenCount);
|
screens = XineramaQueryScreens(_glfw.x11.display, &screenCount);
|
||||||
|
|
||||||
@@ -225,6 +227,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
|||||||
for (j = 0; j < ci->noutput; j++)
|
for (j = 0; j < ci->noutput; j++)
|
||||||
{
|
{
|
||||||
int widthMM, heightMM;
|
int widthMM, heightMM;
|
||||||
|
_GLFWmonitor* monitor;
|
||||||
XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display,
|
XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display,
|
||||||
sr, ci->outputs[j]);
|
sr, ci->outputs[j]);
|
||||||
if (oi->connection != RR_Connected)
|
if (oi->connection != RR_Connected)
|
||||||
@@ -233,12 +236,6 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found == size)
|
|
||||||
{
|
|
||||||
size += 4;
|
|
||||||
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * size);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
|
if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
|
||||||
{
|
{
|
||||||
widthMM = oi->mm_height;
|
widthMM = oi->mm_height;
|
||||||
@@ -250,9 +247,9 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
|||||||
heightMM = oi->mm_height;
|
heightMM = oi->mm_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
monitors[found] = _glfwAllocMonitor(oi->name, widthMM, heightMM);
|
monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);
|
||||||
monitors[found]->x11.output = ci->outputs[j];
|
monitor->x11.output = ci->outputs[j];
|
||||||
monitors[found]->x11.crtc = oi->crtc;
|
monitor->x11.crtc = oi->crtc;
|
||||||
|
|
||||||
for (k = 0; k < screenCount; k++)
|
for (k = 0; k < screenCount; k++)
|
||||||
{
|
{
|
||||||
@@ -261,17 +258,18 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
|||||||
screens[k].width == ci->width &&
|
screens[k].width == ci->width &&
|
||||||
screens[k].height == ci->height)
|
screens[k].height == ci->height)
|
||||||
{
|
{
|
||||||
monitors[found]->x11.index = k;
|
monitor->x11.index = k;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XRRFreeOutputInfo(oi);
|
XRRFreeOutputInfo(oi);
|
||||||
|
|
||||||
if (ci->outputs[j] == primary)
|
|
||||||
_GLFW_SWAP_POINTERS(monitors[0], monitors[found]);
|
|
||||||
|
|
||||||
found++;
|
found++;
|
||||||
|
monitors[found - 1] = monitor;
|
||||||
|
|
||||||
|
if (ci->outputs[j] == primary)
|
||||||
|
_GLFW_SWAP_POINTERS(monitors[0], monitors[found - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
XRRFreeCrtcInfo(ci);
|
XRRFreeCrtcInfo(ci);
|
||||||
@@ -286,7 +284,10 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"X11: RandR monitor support seems broken");
|
"X11: RandR monitor support seems broken");
|
||||||
|
|
||||||
_glfw.x11.randr.monitorBroken = GL_TRUE;
|
_glfw.x11.randr.monitorBroken = GL_TRUE;
|
||||||
|
free(monitors);
|
||||||
|
monitors = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,13 +331,11 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||||
{
|
{
|
||||||
GLFWvidmode* result;
|
GLFWvidmode* result;
|
||||||
|
|
||||||
*found = 0;
|
*count = 0;
|
||||||
|
|
||||||
// Build array of available resolutions
|
|
||||||
|
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
{
|
{
|
||||||
@@ -359,20 +358,18 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
|||||||
|
|
||||||
const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
|
const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
|
||||||
|
|
||||||
for (j = 0; j < *found; j++)
|
for (j = 0; j < *count; j++)
|
||||||
{
|
{
|
||||||
if (_glfwCompareVideoModes(result + j, &mode) == 0)
|
if (_glfwCompareVideoModes(result + j, &mode) == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j < *found)
|
// Skip duplicate modes
|
||||||
{
|
if (j < *count)
|
||||||
// This is a duplicate, so skip it
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
result[*found] = mode;
|
(*count)++;
|
||||||
(*found)++;
|
result[*count - 1] = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
XRRFreeOutputInfo(oi);
|
XRRFreeOutputInfo(oi);
|
||||||
@@ -381,7 +378,7 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*found = 1;
|
*count = 1;
|
||||||
result = calloc(1, sizeof(GLFWvidmode));
|
result = calloc(1, sizeof(GLFWvidmode));
|
||||||
_glfwPlatformGetVideoMode(monitor, result);
|
_glfwPlatformGetVideoMode(monitor, result);
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-19
@@ -25,8 +25,8 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _x11_platform_h_
|
#ifndef _glfw3_x11_platform_h_
|
||||||
#define _x11_platform_h_
|
#define _glfw3_x11_platform_h_
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@@ -57,6 +57,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "posix_tls.h"
|
#include "posix_tls.h"
|
||||||
|
#include "posix_time.h"
|
||||||
|
#include "linux_joystick.h"
|
||||||
|
#include "xkb_unicode.h"
|
||||||
|
|
||||||
#if defined(_GLFW_GLX)
|
#if defined(_GLFW_GLX)
|
||||||
#define _GLFW_X11_CONTEXT_VISUAL window->glx.visual
|
#define _GLFW_X11_CONTEXT_VISUAL window->glx.visual
|
||||||
@@ -70,10 +73,6 @@
|
|||||||
#error "No supported context creation API selected"
|
#error "No supported context creation API selected"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "posix_time.h"
|
|
||||||
#include "linux_joystick.h"
|
|
||||||
#include "xkb_unicode.h"
|
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11
|
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11
|
||||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11
|
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11
|
||||||
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11
|
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11
|
||||||
@@ -88,8 +87,6 @@ typedef struct _GLFWwindowX11
|
|||||||
Window handle;
|
Window handle;
|
||||||
XIC ic;
|
XIC ic;
|
||||||
|
|
||||||
GLboolean overrideRedirect;
|
|
||||||
|
|
||||||
// Cached position and size used to filter out duplicate events
|
// Cached position and size used to filter out duplicate events
|
||||||
int width, height;
|
int width, height;
|
||||||
int xpos, ypos;
|
int xpos, ypos;
|
||||||
@@ -99,6 +96,12 @@ typedef struct _GLFWwindowX11
|
|||||||
// The last position the cursor was warped to by GLFW
|
// The last position the cursor was warped to by GLFW
|
||||||
int warpPosX, warpPosY;
|
int warpPosX, warpPosY;
|
||||||
|
|
||||||
|
// The information from the last KeyPress event
|
||||||
|
struct {
|
||||||
|
unsigned int keycode;
|
||||||
|
Time time;
|
||||||
|
} last;
|
||||||
|
|
||||||
} _GLFWwindowX11;
|
} _GLFWwindowX11;
|
||||||
|
|
||||||
|
|
||||||
@@ -116,8 +119,6 @@ typedef struct _GLFWlibraryX11
|
|||||||
XContext context;
|
XContext context;
|
||||||
// XIM input method
|
// XIM input method
|
||||||
XIM im;
|
XIM im;
|
||||||
// True if window manager supports EWMH
|
|
||||||
GLboolean hasEWMH;
|
|
||||||
// Most recent error code received by X error handler
|
// Most recent error code received by X error handler
|
||||||
int errorCode;
|
int errorCode;
|
||||||
// Clipboard string (while the selection is owned)
|
// Clipboard string (while the selection is owned)
|
||||||
@@ -170,8 +171,8 @@ typedef struct _GLFWlibraryX11
|
|||||||
GLboolean available;
|
GLboolean available;
|
||||||
int eventBase;
|
int eventBase;
|
||||||
int errorBase;
|
int errorBase;
|
||||||
int versionMajor;
|
int major;
|
||||||
int versionMinor;
|
int minor;
|
||||||
GLboolean gammaBroken;
|
GLboolean gammaBroken;
|
||||||
GLboolean monitorBroken;
|
GLboolean monitorBroken;
|
||||||
} randr;
|
} randr;
|
||||||
@@ -182,8 +183,8 @@ typedef struct _GLFWlibraryX11
|
|||||||
int majorOpcode;
|
int majorOpcode;
|
||||||
int eventBase;
|
int eventBase;
|
||||||
int errorBase;
|
int errorBase;
|
||||||
int versionMajor;
|
int major;
|
||||||
int versionMinor;
|
int minor;
|
||||||
} xkb;
|
} xkb;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -200,8 +201,8 @@ typedef struct _GLFWlibraryX11
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
GLboolean available;
|
GLboolean available;
|
||||||
int versionMajor;
|
int major;
|
||||||
int versionMinor;
|
int minor;
|
||||||
} xinerama;
|
} xinerama;
|
||||||
|
|
||||||
#if defined(_GLFW_HAS_XINPUT)
|
#if defined(_GLFW_HAS_XINPUT)
|
||||||
@@ -210,8 +211,8 @@ typedef struct _GLFWlibraryX11
|
|||||||
int majorOpcode;
|
int majorOpcode;
|
||||||
int eventBase;
|
int eventBase;
|
||||||
int errorBase;
|
int errorBase;
|
||||||
int versionMajor;
|
int major;
|
||||||
int versionMinor;
|
int minor;
|
||||||
} xi;
|
} xi;
|
||||||
#endif /*_GLFW_HAS_XINPUT*/
|
#endif /*_GLFW_HAS_XINPUT*/
|
||||||
|
|
||||||
@@ -264,4 +265,4 @@ void _glfwGrabXErrorHandler(void);
|
|||||||
void _glfwReleaseXErrorHandler(void);
|
void _glfwReleaseXErrorHandler(void);
|
||||||
void _glfwInputXError(int error, const char* message);
|
void _glfwInputXError(int error, const char* message);
|
||||||
|
|
||||||
#endif // _x11_platform_h_
|
#endif // _glfw3_x11_platform_h_
|
||||||
|
|||||||
+315
-250
@@ -36,6 +36,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
// Action for EWMH client messages
|
// Action for EWMH client messages
|
||||||
#define _NET_WM_STATE_REMOVE 0
|
#define _NET_WM_STATE_REMOVE 0
|
||||||
@@ -46,32 +48,29 @@
|
|||||||
#define Button6 6
|
#define Button6 6
|
||||||
#define Button7 7
|
#define Button7 7
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
unsigned long functions;
|
|
||||||
unsigned long decorations;
|
|
||||||
long input_mode;
|
|
||||||
unsigned long status;
|
|
||||||
} MotifWmHints;
|
|
||||||
|
|
||||||
#define MWM_HINTS_DECORATIONS (1L << 1)
|
|
||||||
|
|
||||||
|
|
||||||
// Wait for data to arrive
|
// Wait for data to arrive
|
||||||
//
|
//
|
||||||
void selectDisplayConnection(struct timeval* timeout)
|
void selectDisplayConnection(struct timeval* timeout)
|
||||||
{
|
{
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
|
int result;
|
||||||
const int fd = ConnectionNumber(_glfw.x11.display);
|
const int fd = ConnectionNumber(_glfw.x11.display);
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(fd, &fds);
|
FD_SET(fd, &fds);
|
||||||
|
|
||||||
// select(1) is used instead of an X function like XNextEvent, as the
|
// NOTE: We use select instead of an X function like XNextEvent, as the
|
||||||
// wait inside those are guarded by the mutex protecting the display
|
// wait inside those are guarded by the mutex protecting the display
|
||||||
// struct, locking out other threads from using X (including GLX)
|
// struct, locking out other threads from using X (including GLX)
|
||||||
select(fd + 1, &fds, NULL, NULL, timeout);
|
// NOTE: Only retry on EINTR if there is no timeout, as select is not
|
||||||
|
// required to update it for the time elapsed
|
||||||
|
// TODO: Update timeout value manually
|
||||||
|
do
|
||||||
|
{
|
||||||
|
result = select(fd + 1, &fds, NULL, NULL, timeout);
|
||||||
|
}
|
||||||
|
while (result == -1 && errno == EINTR && timeout == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns whether the window is iconified
|
// Returns whether the window is iconified
|
||||||
@@ -114,7 +113,7 @@ static int translateCursorShape(int shape)
|
|||||||
switch (shape)
|
switch (shape)
|
||||||
{
|
{
|
||||||
case GLFW_ARROW_CURSOR:
|
case GLFW_ARROW_CURSOR:
|
||||||
return XC_arrow;
|
return XC_left_ptr;
|
||||||
case GLFW_IBEAM_CURSOR:
|
case GLFW_IBEAM_CURSOR:
|
||||||
return XC_xterm;
|
return XC_xterm;
|
||||||
case GLFW_CROSSHAIR_CURSOR:
|
case GLFW_CROSSHAIR_CURSOR:
|
||||||
@@ -148,7 +147,7 @@ static int translateState(int state)
|
|||||||
return mods;
|
return mods;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translates an X Window key to internal coding
|
// Translates an X11 key code to a GLFW key token
|
||||||
//
|
//
|
||||||
static int translateKey(int scancode)
|
static int translateKey(int scancode)
|
||||||
{
|
{
|
||||||
@@ -176,9 +175,10 @@ static _GLFWwindow* findWindowByHandle(Window handle)
|
|||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds or removes an EWMH state to a window
|
// Sends an EWMH or ICCCM event to the window manager
|
||||||
//
|
//
|
||||||
static void changeWindowState(_GLFWwindow* window, Atom state, int action)
|
static void sendEventToWM(_GLFWwindow* window, Atom type,
|
||||||
|
long a, long b, long c, long d, long e)
|
||||||
{
|
{
|
||||||
XEvent event;
|
XEvent event;
|
||||||
memset(&event, 0, sizeof(event));
|
memset(&event, 0, sizeof(event));
|
||||||
@@ -186,14 +186,14 @@ static void changeWindowState(_GLFWwindow* window, Atom state, int action)
|
|||||||
event.type = ClientMessage;
|
event.type = ClientMessage;
|
||||||
event.xclient.window = window->x11.handle;
|
event.xclient.window = window->x11.handle;
|
||||||
event.xclient.format = 32; // Data is 32-bit longs
|
event.xclient.format = 32; // Data is 32-bit longs
|
||||||
event.xclient.message_type = _glfw.x11.NET_WM_STATE;
|
event.xclient.message_type = type;
|
||||||
event.xclient.data.l[0] = action;
|
event.xclient.data.l[0] = a;
|
||||||
event.xclient.data.l[1] = state;
|
event.xclient.data.l[1] = b;
|
||||||
event.xclient.data.l[2] = 0; // No secondary property
|
event.xclient.data.l[2] = c;
|
||||||
event.xclient.data.l[3] = 1; // Sender is a normal application
|
event.xclient.data.l[3] = d;
|
||||||
|
event.xclient.data.l[4] = e;
|
||||||
|
|
||||||
XSendEvent(_glfw.x11.display,
|
XSendEvent(_glfw.x11.display, _glfw.x11.root,
|
||||||
_glfw.x11.root,
|
|
||||||
False,
|
False,
|
||||||
SubstructureNotifyMask | SubstructureRedirectMask,
|
SubstructureNotifyMask | SubstructureRedirectMask,
|
||||||
&event);
|
&event);
|
||||||
@@ -252,7 +252,7 @@ static GLboolean createWindow(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
unsigned long wamask;
|
unsigned long wamask;
|
||||||
XSetWindowAttributes wa;
|
XSetWindowAttributes wa;
|
||||||
XVisualInfo* visual = _GLFW_X11_CONTEXT_VISUAL;
|
XVisualInfo* vi = _GLFW_X11_CONTEXT_VISUAL;
|
||||||
|
|
||||||
// Every window needs a colormap
|
// Every window needs a colormap
|
||||||
// Create one based on the visual used by the current context
|
// Create one based on the visual used by the current context
|
||||||
@@ -260,7 +260,7 @@ static GLboolean createWindow(_GLFWwindow* window,
|
|||||||
|
|
||||||
window->x11.colormap = XCreateColormap(_glfw.x11.display,
|
window->x11.colormap = XCreateColormap(_glfw.x11.display,
|
||||||
_glfw.x11.root,
|
_glfw.x11.root,
|
||||||
visual->visual,
|
vi->visual,
|
||||||
AllocNone);
|
AllocNone);
|
||||||
|
|
||||||
// Create the actual window
|
// Create the actual window
|
||||||
@@ -281,9 +281,9 @@ static GLboolean createWindow(_GLFWwindow* window,
|
|||||||
0, 0,
|
0, 0,
|
||||||
wndconfig->width, wndconfig->height,
|
wndconfig->width, wndconfig->height,
|
||||||
0, // Border width
|
0, // Border width
|
||||||
visual->depth, // Color depth
|
vi->depth, // Color depth
|
||||||
InputOutput,
|
InputOutput,
|
||||||
visual->visual,
|
vi->visual,
|
||||||
wamask,
|
wamask,
|
||||||
&wa);
|
&wa);
|
||||||
|
|
||||||
@@ -296,35 +296,23 @@ static GLboolean createWindow(_GLFWwindow* window,
|
|||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wndconfig->decorated)
|
|
||||||
{
|
|
||||||
MotifWmHints hints;
|
|
||||||
hints.flags = MWM_HINTS_DECORATIONS;
|
|
||||||
hints.decorations = 0;
|
|
||||||
|
|
||||||
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
|
||||||
_glfw.x11.MOTIF_WM_HINTS,
|
|
||||||
_glfw.x11.MOTIF_WM_HINTS, 32,
|
|
||||||
PropModeReplace,
|
|
||||||
(unsigned char*) &hints,
|
|
||||||
sizeof(MotifWmHints) / sizeof(long));
|
|
||||||
}
|
|
||||||
|
|
||||||
XSaveContext(_glfw.x11.display,
|
XSaveContext(_glfw.x11.display,
|
||||||
window->x11.handle,
|
window->x11.handle,
|
||||||
_glfw.x11.context,
|
_glfw.x11.context,
|
||||||
(XPointer) window);
|
(XPointer) window);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->monitor && !_glfw.x11.hasEWMH)
|
if (wndconfig->monitor)
|
||||||
|
{
|
||||||
|
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_FULLSCREEN)
|
||||||
{
|
{
|
||||||
// This is the butcher's way of removing window decorations
|
// This is the butcher's way of removing window decorations
|
||||||
// Setting the override-redirect attribute on a window makes the window
|
// Setting the override-redirect attribute on a window makes the
|
||||||
// manager ignore the window completely (ICCCM, section 4)
|
// window manager ignore the window completely (ICCCM, section 4)
|
||||||
// The good thing is that this makes undecorated full screen windows
|
// The good thing is that this makes undecorated full screen windows
|
||||||
// easy to do; the bad thing is that we have to do everything manually
|
// easy to do; the bad thing is that we have to do everything
|
||||||
// and some things (like iconify/restore) won't work at all, as those
|
// manually and some things (like iconify/restore) won't work at
|
||||||
// are tasks usually performed by the window manager
|
// all, as those are tasks usually performed by the window manager
|
||||||
|
|
||||||
XSetWindowAttributes attributes;
|
XSetWindowAttributes attributes;
|
||||||
attributes.override_redirect = True;
|
attributes.override_redirect = True;
|
||||||
@@ -332,9 +320,45 @@ static GLboolean createWindow(_GLFWwindow* window,
|
|||||||
window->x11.handle,
|
window->x11.handle,
|
||||||
CWOverrideRedirect,
|
CWOverrideRedirect,
|
||||||
&attributes);
|
&attributes);
|
||||||
|
|
||||||
window->x11.overrideRedirect = GL_TRUE;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!wndconfig->decorated)
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned long functions;
|
||||||
|
unsigned long decorations;
|
||||||
|
long input_mode;
|
||||||
|
unsigned long status;
|
||||||
|
} hints;
|
||||||
|
|
||||||
|
hints.flags = 2; // Set decorations
|
||||||
|
hints.decorations = 0; // No decorations
|
||||||
|
|
||||||
|
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
||||||
|
_glfw.x11.MOTIF_WM_HINTS,
|
||||||
|
_glfw.x11.MOTIF_WM_HINTS, 32,
|
||||||
|
PropModeReplace,
|
||||||
|
(unsigned char*) &hints,
|
||||||
|
sizeof(hints) / sizeof(long));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wndconfig->floating)
|
||||||
|
{
|
||||||
|
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_ABOVE)
|
||||||
|
{
|
||||||
|
sendEventToWM(window,
|
||||||
|
_glfw.x11.NET_WM_STATE,
|
||||||
|
_NET_WM_STATE_ADD,
|
||||||
|
_glfw.x11.NET_WM_STATE_ABOVE,
|
||||||
|
0, 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Declare the WM protocols supported by GLFW
|
// Declare the WM protocols supported by GLFW
|
||||||
{
|
{
|
||||||
@@ -455,16 +479,6 @@ static GLboolean createWindow(_GLFWwindow* window,
|
|||||||
PropModeReplace, (unsigned char*) &version, 1);
|
PropModeReplace, (unsigned char*) &version, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wndconfig->floating && !wndconfig->monitor)
|
|
||||||
{
|
|
||||||
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_ABOVE)
|
|
||||||
{
|
|
||||||
changeWindowState(window,
|
|
||||||
_glfw.x11.NET_WM_STATE_ABOVE,
|
|
||||||
_NET_WM_STATE_ADD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwPlatformSetWindowTitle(window, wndconfig->title);
|
_glfwPlatformSetWindowTitle(window, wndconfig->title);
|
||||||
|
|
||||||
XRRSelectInput(_glfw.x11.display, window->x11.handle,
|
XRRSelectInput(_glfw.x11.display, window->x11.handle,
|
||||||
@@ -673,18 +687,18 @@ static void handleSelectionRequest(XEvent* event)
|
|||||||
{
|
{
|
||||||
const XSelectionRequestEvent* request = &event->xselectionrequest;
|
const XSelectionRequestEvent* request = &event->xselectionrequest;
|
||||||
|
|
||||||
XEvent response;
|
XEvent reply;
|
||||||
memset(&response, 0, sizeof(response));
|
memset(&reply, 0, sizeof(reply));
|
||||||
|
|
||||||
response.xselection.property = writeTargetToProperty(request);
|
reply.xselection.property = writeTargetToProperty(request);
|
||||||
response.xselection.type = SelectionNotify;
|
reply.xselection.type = SelectionNotify;
|
||||||
response.xselection.display = request->display;
|
reply.xselection.display = request->display;
|
||||||
response.xselection.requestor = request->requestor;
|
reply.xselection.requestor = request->requestor;
|
||||||
response.xselection.selection = request->selection;
|
reply.xselection.selection = request->selection;
|
||||||
response.xselection.target = request->target;
|
reply.xselection.target = request->target;
|
||||||
response.xselection.time = request->time;
|
reply.xselection.time = request->time;
|
||||||
|
|
||||||
XSendEvent(_glfw.x11.display, request->requestor, False, 0, &response);
|
XSendEvent(_glfw.x11.display, request->requestor, False, 0, &reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pushSelectionToManager(_GLFWwindow* window)
|
static void pushSelectionToManager(_GLFWwindow* window)
|
||||||
@@ -763,80 +777,53 @@ static void enterFullscreenMode(_GLFWwindow* window)
|
|||||||
PropModeReplace, (unsigned char*) &value, 1);
|
PropModeReplace, (unsigned char*) &value, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfw.x11.xinerama.available && _glfw.x11.NET_WM_FULLSCREEN_MONITORS)
|
// Position the window over its monitor
|
||||||
{
|
{
|
||||||
XEvent event;
|
|
||||||
memset(&event, 0, sizeof(event));
|
|
||||||
|
|
||||||
event.type = ClientMessage;
|
|
||||||
event.xclient.window = window->x11.handle;
|
|
||||||
event.xclient.format = 32; // Data is 32-bit longs
|
|
||||||
event.xclient.message_type = _glfw.x11.NET_WM_FULLSCREEN_MONITORS;
|
|
||||||
event.xclient.data.l[0] = window->monitor->x11.index;
|
|
||||||
event.xclient.data.l[1] = window->monitor->x11.index;
|
|
||||||
event.xclient.data.l[2] = window->monitor->x11.index;
|
|
||||||
event.xclient.data.l[3] = window->monitor->x11.index;
|
|
||||||
|
|
||||||
XSendEvent(_glfw.x11.display,
|
|
||||||
_glfw.x11.root,
|
|
||||||
False,
|
|
||||||
SubstructureNotifyMask | SubstructureRedirectMask,
|
|
||||||
&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
|
|
||||||
{
|
|
||||||
int x, y;
|
|
||||||
_glfwPlatformGetMonitorPos(window->monitor, &x, &y);
|
|
||||||
_glfwPlatformSetWindowPos(window, x, y);
|
|
||||||
|
|
||||||
if (_glfw.x11.NET_ACTIVE_WINDOW)
|
|
||||||
{
|
|
||||||
// Ask the window manager to raise and focus the GLFW window
|
|
||||||
// Only focused windows with the _NET_WM_STATE_FULLSCREEN state end
|
|
||||||
// up on top of all other windows ("Stacking order" in EWMH spec)
|
|
||||||
|
|
||||||
XEvent event;
|
|
||||||
memset(&event, 0, sizeof(event));
|
|
||||||
|
|
||||||
event.type = ClientMessage;
|
|
||||||
event.xclient.window = window->x11.handle;
|
|
||||||
event.xclient.format = 32; // Data is 32-bit longs
|
|
||||||
event.xclient.message_type = _glfw.x11.NET_ACTIVE_WINDOW;
|
|
||||||
event.xclient.data.l[0] = 1; // Sender is a normal application
|
|
||||||
event.xclient.data.l[1] = 0; // We don't really know the timestamp
|
|
||||||
|
|
||||||
XSendEvent(_glfw.x11.display,
|
|
||||||
_glfw.x11.root,
|
|
||||||
False,
|
|
||||||
SubstructureNotifyMask | SubstructureRedirectMask,
|
|
||||||
&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ask the window manager to make the GLFW window a full screen window
|
|
||||||
// Full screen windows are undecorated and, when focused, are kept
|
|
||||||
// on top of all other windows
|
|
||||||
|
|
||||||
changeWindowState(window,
|
|
||||||
_glfw.x11.NET_WM_STATE_FULLSCREEN,
|
|
||||||
_NET_WM_STATE_ADD);
|
|
||||||
}
|
|
||||||
else if (window->x11.overrideRedirect)
|
|
||||||
{
|
|
||||||
// In override-redirect mode we have divorced ourselves from the
|
|
||||||
// window manager, so we need to do everything manually
|
|
||||||
int xpos, ypos;
|
int xpos, ypos;
|
||||||
GLFWvidmode mode;
|
GLFWvidmode mode;
|
||||||
|
|
||||||
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
|
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
|
||||||
_glfwPlatformGetVideoMode(window->monitor, &mode);
|
_glfwPlatformGetVideoMode(window->monitor, &mode);
|
||||||
|
|
||||||
|
XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
|
||||||
|
xpos, ypos, mode.width, mode.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.x11.xinerama.available && _glfw.x11.NET_WM_FULLSCREEN_MONITORS)
|
||||||
|
{
|
||||||
|
sendEventToWM(window,
|
||||||
|
_glfw.x11.NET_WM_FULLSCREEN_MONITORS,
|
||||||
|
window->monitor->x11.index,
|
||||||
|
window->monitor->x11.index,
|
||||||
|
window->monitor->x11.index,
|
||||||
|
window->monitor->x11.index,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.x11.NET_ACTIVE_WINDOW)
|
||||||
|
{
|
||||||
|
// Ask the window manager to raise and focus the GLFW window
|
||||||
|
// Only focused windows with the _NET_WM_STATE_FULLSCREEN state end up
|
||||||
|
// on top of all other windows ("Stacking order" in EWMH spec)
|
||||||
|
sendEventToWM(window, _glfw.x11.NET_ACTIVE_WINDOW, 1, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
XRaiseWindow(_glfw.x11.display, window->x11.handle);
|
XRaiseWindow(_glfw.x11.display, window->x11.handle);
|
||||||
XSetInputFocus(_glfw.x11.display, window->x11.handle,
|
XSetInputFocus(_glfw.x11.display, window->x11.handle,
|
||||||
RevertToParent, CurrentTime);
|
RevertToParent, CurrentTime);
|
||||||
XMoveWindow(_glfw.x11.display, window->x11.handle, xpos, ypos);
|
}
|
||||||
XResizeWindow(_glfw.x11.display, window->x11.handle,
|
|
||||||
mode.width, mode.height);
|
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
|
||||||
|
{
|
||||||
|
// Ask the window manager to make the GLFW window a full screen window
|
||||||
|
// Full screen windows are undecorated and, when focused, are kept
|
||||||
|
// on top of all other windows
|
||||||
|
sendEventToWM(window,
|
||||||
|
_glfw.x11.NET_WM_STATE,
|
||||||
|
_NET_WM_STATE_ADD,
|
||||||
|
_glfw.x11.NET_WM_STATE_FULLSCREEN,
|
||||||
|
0, 1, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -857,32 +844,47 @@ static void leaveFullscreenMode(_GLFWwindow* window)
|
|||||||
_glfw.x11.saver.blanking,
|
_glfw.x11.saver.blanking,
|
||||||
_glfw.x11.saver.exposure);
|
_glfw.x11.saver.exposure);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfw.x11.NET_WM_BYPASS_COMPOSITOR)
|
|
||||||
{
|
|
||||||
const unsigned long value = 0;
|
|
||||||
|
|
||||||
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
|
||||||
_glfw.x11.NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
|
|
||||||
PropModeReplace, (unsigned char*) &value, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
|
|
||||||
{
|
|
||||||
// Ask the window manager to make the GLFW window a normal window
|
|
||||||
// Normal windows usually have frames and other decorations
|
|
||||||
|
|
||||||
changeWindowState(window,
|
|
||||||
_glfw.x11.NET_WM_STATE_FULLSCREEN,
|
|
||||||
_NET_WM_STATE_REMOVE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decode a Unicode code point from a UTF-8 stream
|
||||||
|
// Based on cutef8 by Jeff Bezanson (Public Domain)
|
||||||
|
//
|
||||||
|
#if defined(X_HAVE_UTF8_STRING)
|
||||||
|
static unsigned int decodeUTF8(const char** s)
|
||||||
|
{
|
||||||
|
unsigned int ch = 0, count = 0;
|
||||||
|
static const unsigned int offsets[] =
|
||||||
|
{
|
||||||
|
0x00000000u, 0x00003080u, 0x000e2080u,
|
||||||
|
0x03c82080u, 0xfa082080u, 0x82082080u
|
||||||
|
};
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ch = (ch << 6) + (unsigned char) **s;
|
||||||
|
(*s)++;
|
||||||
|
count++;
|
||||||
|
} while ((**s & 0xc0) == 0x80);
|
||||||
|
|
||||||
|
assert(count <= 6);
|
||||||
|
return ch - offsets[count - 1];
|
||||||
|
}
|
||||||
|
#endif /*X_HAVE_UTF8_STRING*/
|
||||||
|
|
||||||
// Process the specified X event
|
// Process the specified X event
|
||||||
//
|
//
|
||||||
static void processEvent(XEvent *event)
|
static void processEvent(XEvent *event)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = NULL;
|
_GLFWwindow* window = NULL;
|
||||||
|
int keycode = 0;
|
||||||
|
Bool filtered = False;
|
||||||
|
|
||||||
|
// HACK: Save scancode as some IMs clear the field in XFilterEvent
|
||||||
|
if (event->type == KeyPress || event->type == KeyRelease)
|
||||||
|
keycode = event->xkey.keycode;
|
||||||
|
|
||||||
|
if (_glfw.x11.im)
|
||||||
|
filtered = XFilterEvent(event, None);
|
||||||
|
|
||||||
if (event->type != GenericEvent)
|
if (event->type != GenericEvent)
|
||||||
{
|
{
|
||||||
@@ -898,53 +900,101 @@ static void processEvent(XEvent *event)
|
|||||||
{
|
{
|
||||||
case KeyPress:
|
case KeyPress:
|
||||||
{
|
{
|
||||||
const int key = translateKey(event->xkey.keycode);
|
const int key = translateKey(keycode);
|
||||||
const int mods = translateState(event->xkey.state);
|
const int mods = translateState(event->xkey.state);
|
||||||
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
||||||
|
|
||||||
if (event->xkey.keycode)
|
|
||||||
_glfwInputKey(window, key, event->xkey.keycode, GLFW_PRESS, mods);
|
|
||||||
|
|
||||||
if (window->x11.ic)
|
if (window->x11.ic)
|
||||||
{
|
{
|
||||||
// Translate keys to characters with XIM input context
|
// HACK: Ignore duplicate key press events generated by ibus
|
||||||
|
// Corresponding release events are filtered out by the
|
||||||
int i;
|
// GLFW key repeat logic
|
||||||
Status status;
|
if (window->x11.last.keycode != keycode ||
|
||||||
wchar_t buffer[16];
|
window->x11.last.time != event->xkey.time)
|
||||||
|
|
||||||
if (XFilterEvent(event, None))
|
|
||||||
{
|
{
|
||||||
// Discard intermediary (dead key) events for character input
|
if (keycode)
|
||||||
break;
|
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int count = XwcLookupString(window->x11.ic,
|
window->x11.last.keycode = keycode;
|
||||||
|
window->x11.last.time = event->xkey.time;
|
||||||
|
|
||||||
|
if (!filtered)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
Status status;
|
||||||
|
#if defined(X_HAVE_UTF8_STRING)
|
||||||
|
char buffer[96];
|
||||||
|
char* chars = buffer;
|
||||||
|
|
||||||
|
count = Xutf8LookupString(window->x11.ic,
|
||||||
&event->xkey,
|
&event->xkey,
|
||||||
buffer, sizeof(buffer),
|
buffer, sizeof(buffer),
|
||||||
NULL, &status);
|
NULL, &status);
|
||||||
|
|
||||||
|
if (status == XBufferOverflow)
|
||||||
|
{
|
||||||
|
chars = calloc(count, 1);
|
||||||
|
count = Xutf8LookupString(window->x11.ic,
|
||||||
|
&event->xkey,
|
||||||
|
chars, count,
|
||||||
|
NULL, &status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == XLookupChars || status == XLookupBoth)
|
||||||
|
{
|
||||||
|
const char* c = chars;
|
||||||
|
while (c - chars < count)
|
||||||
|
_glfwInputChar(window, decodeUTF8(&c), mods, plain);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
wchar_t buffer[16];
|
||||||
|
wchar_t* chars = buffer;
|
||||||
|
|
||||||
|
count = XwcLookupString(window->x11.ic,
|
||||||
|
&event->xkey,
|
||||||
|
buffer, sizeof(buffer) / sizeof(wchar_t),
|
||||||
|
NULL, &status);
|
||||||
|
|
||||||
|
if (status == XBufferOverflow)
|
||||||
|
{
|
||||||
|
chars = calloc(count, sizeof(wchar_t));
|
||||||
|
count = XwcLookupString(window->x11.ic,
|
||||||
|
&event->xkey,
|
||||||
|
chars, count,
|
||||||
|
NULL, &status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == XLookupChars || status == XLookupBoth)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
_glfwInputChar(window, buffer[i], mods, plain);
|
_glfwInputChar(window, chars[i], mods, plain);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (chars != buffer)
|
||||||
|
free(chars);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Translate keys to characters with fallback lookup table
|
|
||||||
|
|
||||||
KeySym keysym;
|
KeySym keysym;
|
||||||
XLookupString(&event->xkey, NULL, 0, &keysym, NULL);
|
XLookupString(&event->xkey, NULL, 0, &keysym, NULL);
|
||||||
|
|
||||||
|
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
|
||||||
|
|
||||||
const long character = _glfwKeySym2Unicode(keysym);
|
const long character = _glfwKeySym2Unicode(keysym);
|
||||||
if (character != -1)
|
if (character != -1)
|
||||||
_glfwInputChar(window, character, mods, plain);
|
_glfwInputChar(window, character, mods, plain);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case KeyRelease:
|
case KeyRelease:
|
||||||
{
|
{
|
||||||
const int key = translateKey(event->xkey.keycode);
|
const int key = translateKey(keycode);
|
||||||
const int mods = translateState(event->xkey.state);
|
const int mods = translateState(event->xkey.state);
|
||||||
|
|
||||||
if (!_glfw.x11.xkb.detectable)
|
if (!_glfw.x11.xkb.detectable)
|
||||||
@@ -955,12 +1005,12 @@ static void processEvent(XEvent *event)
|
|||||||
// presses to repeat, so detect and discard release events
|
// presses to repeat, so detect and discard release events
|
||||||
if (XEventsQueued(_glfw.x11.display, QueuedAfterReading))
|
if (XEventsQueued(_glfw.x11.display, QueuedAfterReading))
|
||||||
{
|
{
|
||||||
XEvent nextEvent;
|
XEvent next;
|
||||||
XPeekEvent(_glfw.x11.display, &nextEvent);
|
XPeekEvent(_glfw.x11.display, &next);
|
||||||
|
|
||||||
if (nextEvent.type == KeyPress &&
|
if (next.type == KeyPress &&
|
||||||
nextEvent.xkey.window == event->xkey.window &&
|
next.xkey.window == event->xkey.window &&
|
||||||
nextEvent.xkey.keycode == event->xkey.keycode)
|
next.xkey.keycode == keycode)
|
||||||
{
|
{
|
||||||
// HACK: Repeat events sometimes leak through due to
|
// HACK: Repeat events sometimes leak through due to
|
||||||
// some sort of time drift, so add an epsilon
|
// some sort of time drift, so add an epsilon
|
||||||
@@ -968,18 +1018,18 @@ static void processEvent(XEvent *event)
|
|||||||
// per second so it's fairly safe to assume that
|
// per second so it's fairly safe to assume that
|
||||||
// no human is pressing the key 50 times per
|
// no human is pressing the key 50 times per
|
||||||
// second (value is ms)
|
// second (value is ms)
|
||||||
if ((nextEvent.xkey.time - event->xkey.time) < 20)
|
if ((next.xkey.time - event->xkey.time) < 20)
|
||||||
{
|
{
|
||||||
// This is very likely a server-generated key repeat
|
// This is very likely a server-generated key repeat
|
||||||
// event, so ignore it
|
// event, so ignore it
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwInputKey(window, key, event->xkey.keycode, GLFW_RELEASE, mods);
|
_glfwInputKey(window, key, keycode, GLFW_RELEASE, mods);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ButtonPress:
|
case ButtonPress:
|
||||||
@@ -1013,7 +1063,7 @@ static void processEvent(XEvent *event)
|
|||||||
mods);
|
mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ButtonRelease:
|
case ButtonRelease:
|
||||||
@@ -1050,7 +1100,8 @@ static void processEvent(XEvent *event)
|
|||||||
GLFW_RELEASE,
|
GLFW_RELEASE,
|
||||||
mods);
|
mods);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case EnterNotify:
|
case EnterNotify:
|
||||||
@@ -1061,13 +1112,13 @@ static void processEvent(XEvent *event)
|
|||||||
hideCursor(window);
|
hideCursor(window);
|
||||||
|
|
||||||
_glfwInputCursorEnter(window, GL_TRUE);
|
_glfwInputCursorEnter(window, GL_TRUE);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LeaveNotify:
|
case LeaveNotify:
|
||||||
{
|
{
|
||||||
_glfwInputCursorEnter(window, GL_FALSE);
|
_glfwInputCursorEnter(window, GL_FALSE);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MotionNotify:
|
case MotionNotify:
|
||||||
@@ -1081,8 +1132,8 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
{
|
{
|
||||||
if (_glfw.focusedWindow != window)
|
if (_glfw.cursorWindow != window)
|
||||||
break;
|
return;
|
||||||
|
|
||||||
_glfwInputCursorMotion(window,
|
_glfwInputCursorMotion(window,
|
||||||
x - window->x11.cursorPosX,
|
x - window->x11.cursorPosX,
|
||||||
@@ -1094,7 +1145,7 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
window->x11.cursorPosX = x;
|
window->x11.cursorPosX = x;
|
||||||
window->x11.cursorPosY = y;
|
window->x11.cursorPosY = y;
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ConfigureNotify:
|
case ConfigureNotify:
|
||||||
@@ -1125,38 +1176,43 @@ static void processEvent(XEvent *event)
|
|||||||
window->x11.ypos = event->xconfigure.y;
|
window->x11.ypos = event->xconfigure.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ClientMessage:
|
case ClientMessage:
|
||||||
{
|
{
|
||||||
// Custom client message, probably from the window manager
|
// Custom client message, probably from the window manager
|
||||||
|
|
||||||
|
if (filtered)
|
||||||
|
return;
|
||||||
|
|
||||||
if (event->xclient.message_type == None)
|
if (event->xclient.message_type == None)
|
||||||
break;
|
return;
|
||||||
|
|
||||||
if (event->xclient.message_type == _glfw.x11.WM_PROTOCOLS)
|
if (event->xclient.message_type == _glfw.x11.WM_PROTOCOLS)
|
||||||
{
|
{
|
||||||
if (_glfw.x11.WM_DELETE_WINDOW &&
|
const Atom protocol = event->xclient.data.l[0];
|
||||||
(Atom) event->xclient.data.l[0] == _glfw.x11.WM_DELETE_WINDOW)
|
if (protocol == None)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (protocol == _glfw.x11.WM_DELETE_WINDOW)
|
||||||
{
|
{
|
||||||
// The window manager was asked to close the window, for example by
|
// The window manager was asked to close the window, for example by
|
||||||
// the user pressing a 'close' window decoration button
|
// the user pressing a 'close' window decoration button
|
||||||
|
|
||||||
_glfwInputWindowCloseRequest(window);
|
_glfwInputWindowCloseRequest(window);
|
||||||
}
|
}
|
||||||
else if (_glfw.x11.NET_WM_PING &&
|
else if (protocol == _glfw.x11.NET_WM_PING)
|
||||||
(Atom) event->xclient.data.l[0] == _glfw.x11.NET_WM_PING)
|
|
||||||
{
|
{
|
||||||
// The window manager is pinging the application to ensure it's
|
// The window manager is pinging the application to ensure it's
|
||||||
// still responding to events
|
// still responding to events
|
||||||
|
|
||||||
event->xclient.window = _glfw.x11.root;
|
XEvent reply = *event;
|
||||||
XSendEvent(_glfw.x11.display,
|
reply.xclient.window = _glfw.x11.root;
|
||||||
event->xclient.window,
|
|
||||||
|
XSendEvent(_glfw.x11.display, _glfw.x11.root,
|
||||||
False,
|
False,
|
||||||
SubstructureNotifyMask | SubstructureRedirectMask,
|
SubstructureNotifyMask | SubstructureRedirectMask,
|
||||||
event);
|
&reply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (event->xclient.message_type == _glfw.x11.XdndEnter)
|
else if (event->xclient.message_type == _glfw.x11.XdndEnter)
|
||||||
@@ -1204,7 +1260,7 @@ static void processEvent(XEvent *event)
|
|||||||
XFlush(_glfw.x11.display);
|
XFlush(_glfw.x11.display);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SelectionNotify:
|
case SelectionNotify:
|
||||||
@@ -1250,39 +1306,56 @@ static void processEvent(XEvent *event)
|
|||||||
XFlush(_glfw.x11.display);
|
XFlush(_glfw.x11.display);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case FocusIn:
|
case FocusIn:
|
||||||
{
|
{
|
||||||
if (event->xfocus.mode == NotifyNormal)
|
if (event->xfocus.mode == NotifyGrab ||
|
||||||
|
event->xfocus.mode == NotifyUngrab)
|
||||||
{
|
{
|
||||||
_glfwInputWindowFocus(window, GL_TRUE);
|
// Ignore focus events from popup indicator windows, window menu
|
||||||
|
// key chords and window dragging
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->x11.ic)
|
||||||
|
XSetICFocus(window->x11.ic);
|
||||||
|
|
||||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
disableCursor(window);
|
disableCursor(window);
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
_glfwInputWindowFocus(window, GL_TRUE);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case FocusOut:
|
case FocusOut:
|
||||||
{
|
{
|
||||||
if (event->xfocus.mode == NotifyNormal)
|
if (event->xfocus.mode == NotifyGrab ||
|
||||||
|
event->xfocus.mode == NotifyUngrab)
|
||||||
{
|
{
|
||||||
_glfwInputWindowFocus(window, GL_FALSE);
|
// Ignore focus events from popup indicator windows, window menu
|
||||||
|
// key chords and window dragging
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->x11.ic)
|
||||||
|
XUnsetICFocus(window->x11.ic);
|
||||||
|
|
||||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
restoreCursor(window);
|
restoreCursor(window);
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
if (window->monitor && window->autoIconify)
|
||||||
|
_glfwPlatformIconifyWindow(window);
|
||||||
|
|
||||||
|
_glfwInputWindowFocus(window, GL_FALSE);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Expose:
|
case Expose:
|
||||||
{
|
{
|
||||||
_glfwInputWindowDamage(window);
|
_glfwInputWindowDamage(window);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PropertyNotify:
|
case PropertyNotify:
|
||||||
@@ -1292,24 +1365,34 @@ static void processEvent(XEvent *event)
|
|||||||
{
|
{
|
||||||
const int state = getWindowState(window);
|
const int state = getWindowState(window);
|
||||||
if (state == IconicState)
|
if (state == IconicState)
|
||||||
|
{
|
||||||
|
if (window->monitor)
|
||||||
|
leaveFullscreenMode(window);
|
||||||
|
|
||||||
_glfwInputWindowIconify(window, GL_TRUE);
|
_glfwInputWindowIconify(window, GL_TRUE);
|
||||||
|
}
|
||||||
else if (state == NormalState)
|
else if (state == NormalState)
|
||||||
|
{
|
||||||
|
if (window->monitor)
|
||||||
|
enterFullscreenMode(window);
|
||||||
|
|
||||||
_glfwInputWindowIconify(window, GL_FALSE);
|
_glfwInputWindowIconify(window, GL_FALSE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SelectionClear:
|
case SelectionClear:
|
||||||
{
|
{
|
||||||
handleSelectionClear(event);
|
handleSelectionClear(event);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SelectionRequest:
|
case SelectionRequest:
|
||||||
{
|
{
|
||||||
handleSelectionRequest(event);
|
handleSelectionRequest(event);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case DestroyNotify:
|
case DestroyNotify:
|
||||||
@@ -1337,8 +1420,8 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
{
|
{
|
||||||
if (_glfw.focusedWindow != window)
|
if (_glfw.cursorWindow != window)
|
||||||
break;
|
return;
|
||||||
|
|
||||||
x = data->event_x - window->x11.cursorPosX;
|
x = data->event_x - window->x11.cursorPosX;
|
||||||
y = data->event_y - window->x11.cursorPosY;
|
y = data->event_y - window->x11.cursorPosY;
|
||||||
@@ -1359,23 +1442,15 @@ static void processEvent(XEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
XFreeEventData(_glfw.x11.display, &event->xcookie);
|
XFreeEventData(_glfw.x11.display, &event->xcookie);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
#endif /*_GLFW_HAS_XINPUT*/
|
#endif /*_GLFW_HAS_XINPUT*/
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
if (event->type - _glfw.x11.randr.eventBase == RRScreenChangeNotify)
|
||||||
{
|
|
||||||
switch (event->type - _glfw.x11.randr.eventBase)
|
|
||||||
{
|
|
||||||
case RRScreenChangeNotify:
|
|
||||||
{
|
{
|
||||||
XRRUpdateConfiguration(event);
|
XRRUpdateConfiguration(event);
|
||||||
break;
|
return;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1560,7 +1635,7 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
|||||||
{
|
{
|
||||||
_glfwSetVideoMode(window->monitor, &window->videoMode);
|
_glfwSetVideoMode(window->monitor, &window->videoMode);
|
||||||
|
|
||||||
if (window->x11.overrideRedirect)
|
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_FULLSCREEN)
|
||||||
{
|
{
|
||||||
GLFWvidmode mode;
|
GLFWvidmode mode;
|
||||||
_glfwPlatformGetVideoMode(window->monitor, &mode);
|
_glfwPlatformGetVideoMode(window->monitor, &mode);
|
||||||
@@ -1607,27 +1682,17 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
|||||||
if (!_glfwPlatformWindowVisible(window) &&
|
if (!_glfwPlatformWindowVisible(window) &&
|
||||||
_glfw.x11.NET_REQUEST_FRAME_EXTENTS)
|
_glfw.x11.NET_REQUEST_FRAME_EXTENTS)
|
||||||
{
|
{
|
||||||
// Ensure _NET_FRAME_EXTENTS is set, allowing glfwGetWindowFrameSize to
|
|
||||||
// function before the window is mapped
|
|
||||||
|
|
||||||
double base;
|
double base;
|
||||||
XEvent event;
|
XEvent event;
|
||||||
memset(&event, 0, sizeof(event));
|
|
||||||
|
|
||||||
event.type = ClientMessage;
|
// Ensure _NET_FRAME_EXTENTS is set, allowing glfwGetWindowFrameSize to
|
||||||
event.xclient.window = window->x11.handle;
|
// function before the window is mapped
|
||||||
event.xclient.format = 32; // Data is 32-bit longs
|
sendEventToWM(window, _glfw.x11.NET_REQUEST_FRAME_EXTENTS,
|
||||||
event.xclient.message_type = _glfw.x11.NET_REQUEST_FRAME_EXTENTS;
|
0, 0, 0, 0, 0);
|
||||||
|
|
||||||
XSendEvent(_glfw.x11.display,
|
// HACK: Poll with timeout for the required reply instead of blocking
|
||||||
_glfw.x11.root,
|
|
||||||
False,
|
|
||||||
SubstructureNotifyMask | SubstructureRedirectMask,
|
|
||||||
&event);
|
|
||||||
|
|
||||||
// HACK: Poll with timeout for the required response instead of blocking
|
|
||||||
// This is done because some window managers (at least Unity,
|
// This is done because some window managers (at least Unity,
|
||||||
// Fluxbox and Xfwm) failed to send the required response
|
// Fluxbox and Xfwm) failed to send the required reply
|
||||||
// They have been fixed but broken versions are still in the wild
|
// They have been fixed but broken versions are still in the wild
|
||||||
// If you are affected by this and your window manager is NOT
|
// If you are affected by this and your window manager is NOT
|
||||||
// listed above, PLEASE report it to their and our issue trackers
|
// listed above, PLEASE report it to their and our issue trackers
|
||||||
@@ -1675,12 +1740,12 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
|||||||
|
|
||||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window->x11.overrideRedirect)
|
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_FULLSCREEN)
|
||||||
{
|
{
|
||||||
// Override-redirect windows cannot be iconified or restored, as those
|
// Override-redirect windows cannot be iconified or restored, as those
|
||||||
// tasks are performed by the window manager
|
// tasks are performed by the window manager
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"X11: Iconification of full screen windows requires a WM that supports EWMH");
|
"X11: Iconification of full screen windows requires a WM that supports EWMH full screen");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1690,12 +1755,12 @@ void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window->x11.overrideRedirect)
|
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_FULLSCREEN)
|
||||||
{
|
{
|
||||||
// Override-redirect windows cannot be iconified or restored, as those
|
// Override-redirect windows cannot be iconified or restored, as those
|
||||||
// tasks are performed by the window manager
|
// tasks are performed by the window manager
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"X11: Iconification of full screen windows requires a WM that supports EWMH");
|
"X11: Iconification of full screen windows requires a WM that supports EWMH full screen");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1752,7 +1817,7 @@ void _glfwPlatformPollEvents(void)
|
|||||||
processEvent(&event);
|
processEvent(&event);
|
||||||
}
|
}
|
||||||
|
|
||||||
_GLFWwindow* window = _glfw.focusedWindow;
|
_GLFWwindow* window = _glfw.cursorWindow;
|
||||||
if (window && window->cursorMode == GLFW_CURSOR_DISABLED)
|
if (window && window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
@@ -1763,7 +1828,7 @@ void _glfwPlatformPollEvents(void)
|
|||||||
|
|
||||||
void _glfwPlatformWaitEvents(void)
|
void _glfwPlatformWaitEvents(void)
|
||||||
{
|
{
|
||||||
if (!XPending(_glfw.x11.display))
|
while (!XPending(_glfw.x11.display))
|
||||||
selectDisplayConnection(NULL);
|
selectDisplayConnection(NULL);
|
||||||
|
|
||||||
_glfwPlatformPollEvents();
|
_glfwPlatformPollEvents();
|
||||||
|
|||||||
+3
-3
@@ -24,10 +24,10 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#ifndef _xkb_unicode_h_
|
#ifndef _glfw3_xkb_unicode_h_
|
||||||
#define _xkb_unicode_h_
|
#define _glfw3_xkb_unicode_h_
|
||||||
|
|
||||||
|
|
||||||
long _glfwKeySym2Unicode(unsigned int keysym);
|
long _glfwKeySym2Unicode(unsigned int keysym);
|
||||||
|
|
||||||
#endif // _xkb_unicode_h_
|
#endif // _glfw3_xkb_unicode_h_
|
||||||
|
|||||||
+6
-14
@@ -21,31 +21,23 @@ set(TINYCTHREAD "${GLFW_SOURCE_DIR}/deps/tinycthread.h"
|
|||||||
"${GLFW_SOURCE_DIR}/deps/tinycthread.c")
|
"${GLFW_SOURCE_DIR}/deps/tinycthread.c")
|
||||||
|
|
||||||
add_executable(clipboard clipboard.c ${GETOPT})
|
add_executable(clipboard clipboard.c ${GETOPT})
|
||||||
add_executable(defaults defaults.c)
|
|
||||||
add_executable(events events.c ${GETOPT})
|
add_executable(events events.c ${GETOPT})
|
||||||
add_executable(fsaa fsaa.c ${GETOPT})
|
add_executable(msaa msaa.c ${GETOPT})
|
||||||
add_executable(gamma gamma.c ${GETOPT})
|
add_executable(gamma gamma.c ${GETOPT})
|
||||||
add_executable(glfwinfo glfwinfo.c ${GETOPT})
|
add_executable(glfwinfo glfwinfo.c ${GETOPT})
|
||||||
add_executable(iconify iconify.c ${GETOPT})
|
add_executable(iconify iconify.c ${GETOPT})
|
||||||
add_executable(joysticks joysticks.c)
|
add_executable(joysticks joysticks.c)
|
||||||
add_executable(monitors monitors.c ${GETOPT})
|
add_executable(monitors monitors.c ${GETOPT})
|
||||||
add_executable(peter peter.c)
|
|
||||||
add_executable(reopen reopen.c)
|
add_executable(reopen reopen.c)
|
||||||
add_executable(cursor cursor.c)
|
add_executable(cursor cursor.c)
|
||||||
|
|
||||||
add_executable(cursoranim WIN32 MACOSX_BUNDLE cursoranim.c)
|
|
||||||
set_target_properties(cursoranim PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Cursor animation")
|
|
||||||
|
|
||||||
add_executable(accuracy WIN32 MACOSX_BUNDLE accuracy.c)
|
|
||||||
set_target_properties(accuracy PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Accuracy")
|
|
||||||
|
|
||||||
add_executable(empty WIN32 MACOSX_BUNDLE empty.c ${TINYCTHREAD})
|
add_executable(empty WIN32 MACOSX_BUNDLE empty.c ${TINYCTHREAD})
|
||||||
set_target_properties(empty PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Empty Event")
|
set_target_properties(empty PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Empty Event")
|
||||||
|
|
||||||
add_executable(sharing WIN32 MACOSX_BUNDLE sharing.c)
|
add_executable(sharing WIN32 MACOSX_BUNDLE sharing.c)
|
||||||
set_target_properties(sharing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Sharing")
|
set_target_properties(sharing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Sharing")
|
||||||
|
|
||||||
add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c)
|
add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c ${GETOPT})
|
||||||
set_target_properties(tearing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Tearing")
|
set_target_properties(tearing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Tearing")
|
||||||
|
|
||||||
add_executable(threads WIN32 MACOSX_BUNDLE threads.c ${TINYCTHREAD})
|
add_executable(threads WIN32 MACOSX_BUNDLE threads.c ${TINYCTHREAD})
|
||||||
@@ -60,9 +52,9 @@ set_target_properties(windows PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Windows")
|
|||||||
target_link_libraries(empty "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
|
target_link_libraries(empty "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
|
||||||
target_link_libraries(threads "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
|
target_link_libraries(threads "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
|
||||||
|
|
||||||
set(WINDOWS_BINARIES accuracy empty sharing tearing threads title windows cursoranim)
|
set(WINDOWS_BINARIES empty sharing tearing threads title windows)
|
||||||
set(CONSOLE_BINARIES clipboard defaults events fsaa gamma glfwinfo
|
set(CONSOLE_BINARIES clipboard events msaa gamma glfwinfo
|
||||||
iconify joysticks monitors peter reopen cursor)
|
iconify joysticks monitors reopen cursor)
|
||||||
|
|
||||||
set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
|
set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
|
||||||
FOLDER "GLFW3/Tests")
|
FOLDER "GLFW3/Tests")
|
||||||
@@ -77,6 +69,6 @@ if (APPLE)
|
|||||||
set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
|
set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
|
||||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}
|
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}
|
||||||
MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION_FULL}
|
MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION_FULL}
|
||||||
MACOSX_BUNDLE_INFO_PLIST "${GLFW_SOURCE_DIR}/CMake/AppleInfo.plist")
|
MACOSX_BUNDLE_INFO_PLIST "${GLFW_SOURCE_DIR}/CMake/MacOSXBundleInfo.plist.in")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@@ -1,128 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// Mouse cursor accuracy test
|
|
||||||
// Copyright (c) Camilla Berglund <elmindreda@elmindreda.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.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
//
|
|
||||||
// This test came about as the result of bug #1867804
|
|
||||||
//
|
|
||||||
// No sign of said bug has so far been detected
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
static double cursor_x = 0.0, cursor_y = 0.0;
|
|
||||||
static int window_width = 640, window_height = 480;
|
|
||||||
static int swap_interval = 1;
|
|
||||||
|
|
||||||
static void set_swap_interval(GLFWwindow* window, int interval)
|
|
||||||
{
|
|
||||||
char title[256];
|
|
||||||
|
|
||||||
swap_interval = interval;
|
|
||||||
glfwSwapInterval(swap_interval);
|
|
||||||
|
|
||||||
sprintf(title, "Cursor Inaccuracy Detector (interval %i)", swap_interval);
|
|
||||||
|
|
||||||
glfwSetWindowTitle(window, title);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void error_callback(int error, const char* description)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Error: %s\n", description);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
|
||||||
{
|
|
||||||
window_width = width;
|
|
||||||
window_height = height;
|
|
||||||
|
|
||||||
glViewport(0, 0, window_width, window_height);
|
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glLoadIdentity();
|
|
||||||
glOrtho(0.f, window_width, 0.f, window_height, 0.f, 1.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cursor_position_callback(GLFWwindow* window, double x, double y)
|
|
||||||
{
|
|
||||||
cursor_x = x;
|
|
||||||
cursor_y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
|
||||||
{
|
|
||||||
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
|
|
||||||
set_swap_interval(window, 1 - swap_interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
GLFWwindow* window;
|
|
||||||
int width, height;
|
|
||||||
|
|
||||||
glfwSetErrorCallback(error_callback);
|
|
||||||
|
|
||||||
if (!glfwInit())
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
|
|
||||||
window = glfwCreateWindow(window_width, window_height, "", NULL, NULL);
|
|
||||||
if (!window)
|
|
||||||
{
|
|
||||||
glfwTerminate();
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwSetCursorPosCallback(window, cursor_position_callback);
|
|
||||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
|
||||||
glfwSetKeyCallback(window, key_callback);
|
|
||||||
|
|
||||||
glfwMakeContextCurrent(window);
|
|
||||||
|
|
||||||
glfwGetFramebufferSize(window, &width, &height);
|
|
||||||
framebuffer_size_callback(window, width, height);
|
|
||||||
|
|
||||||
set_swap_interval(window, swap_interval);
|
|
||||||
|
|
||||||
while (!glfwWindowShouldClose(window))
|
|
||||||
{
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
|
|
||||||
glBegin(GL_LINES);
|
|
||||||
glVertex2f(0.f, (GLfloat) (window_height - cursor_y));
|
|
||||||
glVertex2f((GLfloat) window_width, (GLfloat) (window_height - cursor_y));
|
|
||||||
glVertex2f((GLfloat) cursor_x, 0.f);
|
|
||||||
glVertex2f((GLfloat) cursor_x, (GLfloat) window_height);
|
|
||||||
glEnd();
|
|
||||||
|
|
||||||
glfwSwapBuffers(window);
|
|
||||||
glfwPollEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwTerminate();
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
+8
-2
@@ -34,6 +34,12 @@
|
|||||||
|
|
||||||
#include "getopt.h"
|
#include "getopt.h"
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#define MODIFIER GLFW_MOD_SUPER
|
||||||
|
#else
|
||||||
|
#define MODIFIER GLFW_MOD_CONTROL
|
||||||
|
#endif
|
||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
printf("Usage: clipboard [-h]\n");
|
printf("Usage: clipboard [-h]\n");
|
||||||
@@ -56,7 +62,7 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GLFW_KEY_V:
|
case GLFW_KEY_V:
|
||||||
if (mods == GLFW_MOD_CONTROL)
|
if (mods == MODIFIER)
|
||||||
{
|
{
|
||||||
const char* string;
|
const char* string;
|
||||||
|
|
||||||
@@ -69,7 +75,7 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GLFW_KEY_C:
|
case GLFW_KEY_C:
|
||||||
if (mods == GLFW_MOD_CONTROL)
|
if (mods == MODIFIER)
|
||||||
{
|
{
|
||||||
const char* string = "Hello GLFW World!";
|
const char* string = "Hello GLFW World!";
|
||||||
glfwSetClipboardString(window, string);
|
glfwSetClipboardString(window, string);
|
||||||
|
|||||||
+205
-190
@@ -23,158 +23,83 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
//
|
//
|
||||||
// System cursors and input modes tests.
|
// This test provides an interface to the cursor image and cursor mode
|
||||||
|
// parts of the API.
|
||||||
|
//
|
||||||
|
// Custom cursor image generation by urraka.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#include <GLFW/glfw3.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 <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
static int W = 640;
|
#define CURSOR_FRAME_COUNT 60
|
||||||
static int H = 480;
|
|
||||||
static int delay = 0;
|
|
||||||
|
|
||||||
static GLFWwindow* windows[2] = { NULL, NULL };
|
static double cursor_x;
|
||||||
static GLFWwindow* activeWindow = NULL;
|
static double cursor_y;
|
||||||
static GLFWcursor* cursor = NULL;
|
static int swap_interval = 1;
|
||||||
|
static GLboolean wait_events = GL_FALSE;
|
||||||
static struct
|
static GLboolean animate_cursor = GL_FALSE;
|
||||||
{
|
static GLboolean track_cursor = GL_FALSE;
|
||||||
int key;
|
static GLFWcursor* standard_cursors[6];
|
||||||
double time;
|
|
||||||
} commands[] = {
|
|
||||||
{GLFW_KEY_H, 0},
|
|
||||||
{GLFW_KEY_C, 0},
|
|
||||||
{GLFW_KEY_D, 0},
|
|
||||||
{GLFW_KEY_S, 0},
|
|
||||||
{GLFW_KEY_N, 0},
|
|
||||||
{GLFW_KEY_1, 0},
|
|
||||||
{GLFW_KEY_2, 0},
|
|
||||||
{GLFW_KEY_3, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static int CommandCount = sizeof(commands) / sizeof(commands[0]);
|
|
||||||
|
|
||||||
static struct
|
|
||||||
{
|
|
||||||
int w, h;
|
|
||||||
} cursorSize[] = {
|
|
||||||
{ 24, 24 }, { 13, 37 }, { 5, 53 }, { 43, 64 }, { 300, 300 }
|
|
||||||
};
|
|
||||||
|
|
||||||
static int SizeCount = sizeof(cursorSize) / sizeof(cursorSize[0]);
|
|
||||||
static int currentSize = 0;
|
|
||||||
|
|
||||||
static void command_callback(int key)
|
|
||||||
{
|
|
||||||
switch (key)
|
|
||||||
{
|
|
||||||
case GLFW_KEY_H:
|
|
||||||
{
|
|
||||||
printf("H: show this help\n");
|
|
||||||
printf("C: call glfwCreateCursor()\n");
|
|
||||||
printf("D: call glfwDestroyCursor()\n");
|
|
||||||
printf("S: call glfwSetCursor()\n");
|
|
||||||
printf("N: call glfwSetCursor() with NULL\n");
|
|
||||||
printf("1: set GLFW_CURSOR_NORMAL\n");
|
|
||||||
printf("2: set GLFW_CURSOR_HIDDEN\n");
|
|
||||||
printf("3: set GLFW_CURSOR_DISABLED\n");
|
|
||||||
printf("T: enable 3s delay for all previous commands\n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GLFW_KEY_C:
|
|
||||||
{
|
|
||||||
int x, y;
|
|
||||||
GLFWimage image;
|
|
||||||
unsigned char* pixels;
|
|
||||||
|
|
||||||
if (cursor)
|
|
||||||
break;
|
|
||||||
|
|
||||||
image.width = cursorSize[currentSize].w;
|
|
||||||
image.height = cursorSize[currentSize].h;
|
|
||||||
|
|
||||||
pixels = malloc(4 * image.width * image.height);
|
|
||||||
image.pixels = pixels;
|
|
||||||
|
|
||||||
for (y = 0; y < image.height; y++)
|
|
||||||
{
|
|
||||||
for (x = 0; x < image.width; x++)
|
|
||||||
{
|
|
||||||
*pixels++ = 0xff;
|
|
||||||
*pixels++ = 0;
|
|
||||||
*pixels++ = 255 * y / image.height;
|
|
||||||
*pixels++ = 255 * x / image.width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor = glfwCreateCursor(&image, image.width / 2, image.height / 2);
|
|
||||||
currentSize = (currentSize + 1) % SizeCount;
|
|
||||||
free(image.pixels);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GLFW_KEY_D:
|
|
||||||
{
|
|
||||||
if (cursor != NULL)
|
|
||||||
{
|
|
||||||
glfwDestroyCursor(cursor);
|
|
||||||
cursor = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GLFW_KEY_S:
|
|
||||||
{
|
|
||||||
if (cursor != NULL)
|
|
||||||
glfwSetCursor(activeWindow, cursor);
|
|
||||||
else
|
|
||||||
printf("The cursor is not created\n");
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GLFW_KEY_N:
|
|
||||||
glfwSetCursor(activeWindow, NULL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GLFW_KEY_1:
|
|
||||||
glfwSetInputMode(activeWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GLFW_KEY_2:
|
|
||||||
glfwSetInputMode(activeWindow, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GLFW_KEY_3:
|
|
||||||
glfwSetInputMode(activeWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void error_callback(int error, const char* description)
|
static void error_callback(int error, const char* description)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error: %s\n", description);
|
fprintf(stderr, "Error: %s\n", description);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
static float star(int x, int y, float t)
|
||||||
{
|
{
|
||||||
W = width;
|
const float c = 64 / 2.f;
|
||||||
H = height;
|
|
||||||
|
|
||||||
glViewport(0, 0, W, H);
|
const float i = (0.25f * (float) sin(2.f * M_PI * t) + 0.75f);
|
||||||
|
const float k = 64 * 0.046875f * i;
|
||||||
|
|
||||||
|
const float dist = (float) sqrt((x - c) * (x - c) + (y - c) * (y - c));
|
||||||
|
|
||||||
|
const float salpha = 1.f - dist / c;
|
||||||
|
const float xalpha = (float) x == c ? c : k / (float) fabs(x - c);
|
||||||
|
const float yalpha = (float) y == c ? c : k / (float) fabs(y - c);
|
||||||
|
|
||||||
|
return (float) fmax(0.f, fmin(1.f, i * salpha * 0.2f + salpha * xalpha * yalpha));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void refresh_callback(GLFWwindow* window)
|
static GLFWcursor* create_cursor_frame(float t)
|
||||||
{
|
{
|
||||||
glfwMakeContextCurrent(window);
|
int i = 0, x, y;
|
||||||
glClearColor(0.0f, window == activeWindow ? 0.8f : 0.0f, 0.0f, 1.0f);
|
unsigned char buffer[64 * 64 * 4];
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
const GLFWimage image = { 64, 64, buffer };
|
||||||
glfwSwapBuffers(window);
|
|
||||||
|
for (y = 0; y < image.width; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < image.height; x++)
|
||||||
|
{
|
||||||
|
buffer[i++] = 255;
|
||||||
|
buffer[i++] = 255;
|
||||||
|
buffer[i++] = 255;
|
||||||
|
buffer[i++] = (unsigned char) (255 * star(x, y, t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return glfwCreateCursor(&image, image.width / 2, image.height / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cursor_position_callback(GLFWwindow* window, double x, double y)
|
||||||
|
{
|
||||||
|
printf("%0.3f: Cursor position: %f %f (%+f %+f)\n",
|
||||||
|
glfwGetTime(),
|
||||||
|
x, y, x - cursor_x, y - cursor_y);
|
||||||
|
|
||||||
|
cursor_x = x;
|
||||||
|
cursor_y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||||
@@ -184,104 +109,194 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
|
|||||||
|
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
|
case GLFW_KEY_A:
|
||||||
|
{
|
||||||
|
animate_cursor = !animate_cursor;
|
||||||
|
if (!animate_cursor)
|
||||||
|
glfwSetCursor(window, NULL);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case GLFW_KEY_ESCAPE:
|
case GLFW_KEY_ESCAPE:
|
||||||
|
{
|
||||||
|
if (glfwGetInputMode(window, GLFW_CURSOR) != GLFW_CURSOR_DISABLED)
|
||||||
|
{
|
||||||
glfwSetWindowShouldClose(window, GL_TRUE);
|
glfwSetWindowShouldClose(window, GL_TRUE);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
}
|
||||||
|
|
||||||
|
case GLFW_KEY_N:
|
||||||
|
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||||
|
printf("(( cursor is normal ))\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GLFW_KEY_D:
|
||||||
|
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||||
|
printf("(( cursor is disabled ))\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GLFW_KEY_H:
|
||||||
|
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||||
|
printf("(( cursor is hidden ))\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GLFW_KEY_SPACE:
|
||||||
|
swap_interval = 1 - swap_interval;
|
||||||
|
printf("(( swap interval: %i ))\n", swap_interval);
|
||||||
|
glfwSwapInterval(swap_interval);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GLFW_KEY_W:
|
||||||
|
wait_events = !wait_events;
|
||||||
|
printf("(( %sing for events ))\n", wait_events ? "wait" : "poll");
|
||||||
|
break;
|
||||||
|
|
||||||
case GLFW_KEY_T:
|
case GLFW_KEY_T:
|
||||||
delay = !delay;
|
track_cursor = !track_cursor;
|
||||||
printf("Delay %s.\n", delay ? "enabled" : "disabled");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case GLFW_KEY_0:
|
||||||
{
|
glfwSetCursor(window, NULL);
|
||||||
if (delay)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while (i < CommandCount && commands[i].key != key)
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if (i < CommandCount)
|
|
||||||
commands[i].time = glfwGetTime();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
command_callback(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void focus_callback(GLFWwindow* window, int focused)
|
case GLFW_KEY_1:
|
||||||
{
|
glfwSetCursor(window, standard_cursors[0]);
|
||||||
if (focused)
|
break;
|
||||||
{
|
|
||||||
activeWindow = window;
|
case GLFW_KEY_2:
|
||||||
refresh_callback(windows[0]);
|
glfwSetCursor(window, standard_cursors[1]);
|
||||||
refresh_callback(windows[1]);
|
break;
|
||||||
|
|
||||||
|
case GLFW_KEY_3:
|
||||||
|
glfwSetCursor(window, standard_cursors[2]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GLFW_KEY_4:
|
||||||
|
glfwSetCursor(window, standard_cursors[3]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GLFW_KEY_5:
|
||||||
|
glfwSetCursor(window, standard_cursors[4]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GLFW_KEY_6:
|
||||||
|
glfwSetCursor(window, standard_cursors[5]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
GLboolean running = GL_TRUE;
|
GLFWwindow* window;
|
||||||
|
GLFWcursor* star_cursors[CURSOR_FRAME_COUNT];
|
||||||
|
|
||||||
glfwSetErrorCallback(error_callback);
|
glfwSetErrorCallback(error_callback);
|
||||||
|
|
||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < CURSOR_FRAME_COUNT; i++)
|
||||||
{
|
{
|
||||||
windows[i] = glfwCreateWindow(W, H, "Cursor testing", NULL, NULL);
|
star_cursors[i] = create_cursor_frame(i / (float) CURSOR_FRAME_COUNT);
|
||||||
|
if (!star_cursors[i])
|
||||||
|
{
|
||||||
|
glfwTerminate();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!windows[i])
|
for (i = 0; i < sizeof(standard_cursors) / sizeof(standard_cursors[0]); i++)
|
||||||
|
{
|
||||||
|
const int shapes[] = {
|
||||||
|
GLFW_ARROW_CURSOR,
|
||||||
|
GLFW_IBEAM_CURSOR,
|
||||||
|
GLFW_CROSSHAIR_CURSOR,
|
||||||
|
GLFW_HAND_CURSOR,
|
||||||
|
GLFW_HRESIZE_CURSOR,
|
||||||
|
GLFW_VRESIZE_CURSOR
|
||||||
|
};
|
||||||
|
|
||||||
|
standard_cursors[i] = glfwCreateStandardCursor(shapes[i]);
|
||||||
|
if (!standard_cursors[i])
|
||||||
|
{
|
||||||
|
glfwTerminate();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window = glfwCreateWindow(640, 480, "Cursor Test", NULL, NULL);
|
||||||
|
if (!window)
|
||||||
{
|
{
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwSetWindowPos(windows[i], 100 + (i & 1) * (W + 50), 100);
|
glfwMakeContextCurrent(window);
|
||||||
|
|
||||||
glfwSetWindowRefreshCallback(windows[i], refresh_callback);
|
glfwGetCursorPos(window, &cursor_x, &cursor_y);
|
||||||
glfwSetFramebufferSizeCallback(windows[i], framebuffer_size_callback);
|
printf("Cursor position: %f %f\n", cursor_x, cursor_y);
|
||||||
glfwSetKeyCallback(windows[i], key_callback);
|
|
||||||
glfwSetWindowFocusCallback(windows[i], focus_callback);
|
|
||||||
|
|
||||||
glfwMakeContextCurrent(windows[i]);
|
glfwSetCursorPosCallback(window, cursor_position_callback);
|
||||||
|
glfwSetKeyCallback(window, key_callback);
|
||||||
|
|
||||||
|
while (!glfwWindowShouldClose(window))
|
||||||
|
{
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
glfwSwapBuffers(windows[i]);
|
|
||||||
|
if (track_cursor)
|
||||||
|
{
|
||||||
|
int wnd_width, wnd_height, fb_width, fb_height;
|
||||||
|
float scale;
|
||||||
|
|
||||||
|
glfwGetWindowSize(window, &wnd_width, &wnd_height);
|
||||||
|
glfwGetFramebufferSize(window, &fb_width, &fb_height);
|
||||||
|
|
||||||
|
scale = (float) fb_width / (float) wnd_width;
|
||||||
|
|
||||||
|
glViewport(0, 0, fb_width, fb_height);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(0.f, fb_width, 0.f, fb_height, 0.f, 1.f);
|
||||||
|
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
glVertex2f(0.f, (GLfloat) (fb_height - cursor_y * scale));
|
||||||
|
glVertex2f((GLfloat) fb_width, (GLfloat) (fb_height - cursor_y * scale));
|
||||||
|
glVertex2f((GLfloat) cursor_x * scale, 0.f);
|
||||||
|
glVertex2f((GLfloat) cursor_x * scale, (GLfloat) fb_height);
|
||||||
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
activeWindow = windows[0];
|
glfwSwapBuffers(window);
|
||||||
|
|
||||||
key_callback(NULL, GLFW_KEY_H, 0, GLFW_PRESS, 0);
|
if (animate_cursor)
|
||||||
|
|
||||||
while (running)
|
|
||||||
{
|
{
|
||||||
if (delay)
|
const int i = (int) (glfwGetTime() * 30.0) % CURSOR_FRAME_COUNT;
|
||||||
{
|
glfwSetCursor(window, star_cursors[i]);
|
||||||
int i;
|
|
||||||
double t = glfwGetTime();
|
|
||||||
|
|
||||||
for (i = 0; i < CommandCount; i++)
|
|
||||||
{
|
|
||||||
if (commands[i].time != 0 && t - commands[i].time >= 3.0)
|
|
||||||
{
|
|
||||||
command_callback(commands[i].key);
|
|
||||||
commands[i].time = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
running = !(glfwWindowShouldClose(windows[0]) || glfwWindowShouldClose(windows[1]));
|
if (wait_events)
|
||||||
|
glfwWaitEvents();
|
||||||
|
else
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
|
// Workaround for an issue with msvcrt and mintty
|
||||||
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glfwDestroyWindow(window);
|
||||||
|
|
||||||
|
for (i = 0; i < CURSOR_FRAME_COUNT; i++)
|
||||||
|
glfwDestroyCursor(star_cursors[i]);
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(standard_cursors) / sizeof(standard_cursors[0]); i++)
|
||||||
|
glfwDestroyCursor(standard_cursors[i]);
|
||||||
|
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,135 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// Cursor animation
|
|
||||||
// Copyright (c) Camilla Berglund <elmindreda@elmindreda.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.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
//
|
|
||||||
// Cursor animation test.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#ifdef min
|
|
||||||
#undef min
|
|
||||||
#endif
|
|
||||||
#ifdef max
|
|
||||||
#undef max
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SIZE 64 // cursor size (width & height)
|
|
||||||
#define N 60 // number of frames
|
|
||||||
|
|
||||||
unsigned char buffer[4 * SIZE * SIZE];
|
|
||||||
|
|
||||||
static float max(float a, float b) { return a > b ? a : b; }
|
|
||||||
static float min(float a, float b) { return a < b ? a : b; }
|
|
||||||
|
|
||||||
static float star(int x, int y, float t)
|
|
||||||
{
|
|
||||||
float c = SIZE / 2.0f;
|
|
||||||
|
|
||||||
float i = (0.25f * (float)sin(2.0f * 3.1415926f * t) + 0.75f);
|
|
||||||
float k = SIZE * 0.046875f * i;
|
|
||||||
|
|
||||||
float dist = (float)sqrt((x - c) * (x - c) + (y - c) * (y - c));
|
|
||||||
|
|
||||||
float salpha = 1.0f - dist / c;
|
|
||||||
float xalpha = (float)x == c ? c : k / (float)fabs(x - c);
|
|
||||||
float yalpha = (float)y == c ? c : k / (float)fabs(y - c);
|
|
||||||
|
|
||||||
return max(0.0f, min(1.0f, i * salpha * 0.2f + salpha * xalpha * yalpha));
|
|
||||||
}
|
|
||||||
|
|
||||||
static GLFWcursor* load_frame(float t)
|
|
||||||
{
|
|
||||||
int i = 0, x, y;
|
|
||||||
const GLFWimage image = { SIZE, SIZE, buffer };
|
|
||||||
|
|
||||||
for (y = 0; y < image.width; y++)
|
|
||||||
{
|
|
||||||
for (x = 0; x < image.height; x++)
|
|
||||||
{
|
|
||||||
buffer[i++] = 255;
|
|
||||||
buffer[i++] = 255;
|
|
||||||
buffer[i++] = 255;
|
|
||||||
buffer[i++] = (unsigned char)(255 * star(x, y, t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return glfwCreateCursor(&image, image.width / 2, image.height / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
double t0, t1, frameTime = 0.0;
|
|
||||||
|
|
||||||
GLFWwindow* window;
|
|
||||||
GLFWcursor* frames[N];
|
|
||||||
|
|
||||||
if (!glfwInit())
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
|
|
||||||
window = glfwCreateWindow(640, 480, "Cursor animation", NULL, NULL);
|
|
||||||
|
|
||||||
if (!window)
|
|
||||||
{
|
|
||||||
glfwTerminate();
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwMakeContextCurrent(window);
|
|
||||||
glfwSwapInterval(1);
|
|
||||||
|
|
||||||
for (i = 0; i < N; i++)
|
|
||||||
frames[i] = load_frame(i / (float)N);
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
t0 = glfwGetTime();
|
|
||||||
|
|
||||||
while (!glfwWindowShouldClose(window))
|
|
||||||
{
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
glfwSetCursor(window, frames[i]);
|
|
||||||
glfwSwapBuffers(window);
|
|
||||||
glfwPollEvents();
|
|
||||||
|
|
||||||
t1 = glfwGetTime();
|
|
||||||
frameTime += t1 - t0;
|
|
||||||
t0 = t1;
|
|
||||||
|
|
||||||
while (frameTime > 1.0 / (double)N)
|
|
||||||
{
|
|
||||||
i = (i + 1) % N;
|
|
||||||
frameTime -= 1.0 / (double)N;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwTerminate();
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// Default window/context test
|
|
||||||
// Copyright (c) Camilla Berglund <elmindreda@elmindreda.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.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
//
|
|
||||||
// This test creates a windowed mode window with all window hints set to
|
|
||||||
// default values and then reports the actual attributes of the created
|
|
||||||
// window and context
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#define GLFW_INCLUDE_GLEXT
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int attrib;
|
|
||||||
const char* ext;
|
|
||||||
const char* name;
|
|
||||||
} AttribGL;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int attrib;
|
|
||||||
const char* name;
|
|
||||||
} AttribGLFW;
|
|
||||||
|
|
||||||
static AttribGL gl_attribs[] =
|
|
||||||
{
|
|
||||||
{ GL_RED_BITS, NULL, "red bits" },
|
|
||||||
{ GL_GREEN_BITS, NULL, "green bits" },
|
|
||||||
{ GL_BLUE_BITS, NULL, "blue bits" },
|
|
||||||
{ GL_ALPHA_BITS, NULL, "alpha bits" },
|
|
||||||
{ GL_DEPTH_BITS, NULL, "depth bits" },
|
|
||||||
{ GL_STENCIL_BITS, NULL, "stencil bits" },
|
|
||||||
{ GL_STEREO, NULL, "stereo" },
|
|
||||||
{ GL_SAMPLES_ARB, "GL_ARB_multisample", "FSAA samples" },
|
|
||||||
{ 0, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
static AttribGLFW glfw_attribs[] =
|
|
||||||
{
|
|
||||||
{ GLFW_CONTEXT_VERSION_MAJOR, "Context version major" },
|
|
||||||
{ GLFW_CONTEXT_VERSION_MINOR, "Context version minor" },
|
|
||||||
{ GLFW_OPENGL_FORWARD_COMPAT, "OpenGL forward compatible" },
|
|
||||||
{ GLFW_OPENGL_DEBUG_CONTEXT, "OpenGL debug context" },
|
|
||||||
{ GLFW_OPENGL_PROFILE, "OpenGL profile" },
|
|
||||||
{ 0, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
static void error_callback(int error, const char* description)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Error: %s\n", description);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
int i, width, height;
|
|
||||||
GLFWwindow* window;
|
|
||||||
|
|
||||||
glfwSetErrorCallback(error_callback);
|
|
||||||
|
|
||||||
if (!glfwInit())
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
|
|
||||||
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
|
|
||||||
|
|
||||||
window = glfwCreateWindow(640, 480, "Defaults", NULL, NULL);
|
|
||||||
if (!window)
|
|
||||||
{
|
|
||||||
glfwTerminate();
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwMakeContextCurrent(window);
|
|
||||||
glfwGetFramebufferSize(window, &width, &height);
|
|
||||||
|
|
||||||
printf("framebuffer size: %ix%i\n", width, height);
|
|
||||||
|
|
||||||
for (i = 0; glfw_attribs[i].name; i++)
|
|
||||||
{
|
|
||||||
printf("%s: %i\n",
|
|
||||||
glfw_attribs[i].name,
|
|
||||||
glfwGetWindowAttrib(window, glfw_attribs[i].attrib));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; gl_attribs[i].name; i++)
|
|
||||||
{
|
|
||||||
GLint value = 0;
|
|
||||||
|
|
||||||
if (gl_attribs[i].ext)
|
|
||||||
{
|
|
||||||
if (!glfwExtensionSupported(gl_attribs[i].ext))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
glGetIntegerv(gl_attribs[i].attrib, &value);
|
|
||||||
|
|
||||||
printf("%s: %i\n", gl_attribs[i].name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
|
||||||
window = NULL;
|
|
||||||
|
|
||||||
glfwTerminate();
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
+380
-158
@@ -1,5 +1,5 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// Version information dumper
|
// Context creation and information tool
|
||||||
// Copyright (c) Camilla Berglund <elmindreda@elmindreda.org>
|
// Copyright (c) Camilla Berglund <elmindreda@elmindreda.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
@@ -22,14 +22,13 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
//
|
|
||||||
// This test is a pale imitation of glxinfo(1), except not really
|
|
||||||
//
|
|
||||||
// It dumps GLFW and OpenGL version information
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
/* HACK: Explicitly include the glext.h shipping with GLFW, as this program uses
|
||||||
|
* many modern symbols not provided by the versions in some development
|
||||||
|
* environments (for example on OS X).
|
||||||
|
*/
|
||||||
#include <GL/glext.h>
|
#include <GL/glext.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -42,8 +41,8 @@
|
|||||||
#define strcasecmp(x, y) _stricmp(x, y)
|
#define strcasecmp(x, y) _stricmp(x, y)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define API_OPENGL "gl"
|
#define API_NAME_OPENGL "gl"
|
||||||
#define API_OPENGL_ES "es"
|
#define API_NAME_OPENGL_ES "es"
|
||||||
|
|
||||||
#define PROFILE_NAME_CORE "core"
|
#define PROFILE_NAME_CORE "core"
|
||||||
#define PROFILE_NAME_COMPAT "compat"
|
#define PROFILE_NAME_COMPAT "compat"
|
||||||
@@ -56,18 +55,44 @@
|
|||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
printf("Usage: glfwinfo [-h] [-a API] [-m MAJOR] [-n MINOR] [-d] [-l] [-f] [-p PROFILE] [-s STRATEGY] [-b BEHAVIOR]\n");
|
printf("Usage: glfwinfo [OPTION]...\n");
|
||||||
printf("Options:\n");
|
printf("Options:\n");
|
||||||
printf(" -a the client API to use (" API_OPENGL " or " API_OPENGL_ES ")\n");
|
printf(" -a, --client-api=API the client API to use ("
|
||||||
printf(" -b the release behavior to use (" BEHAVIOR_NAME_NONE " or " BEHAVIOR_NAME_FLUSH ")\n");
|
API_NAME_OPENGL " or "
|
||||||
printf(" -d request a debug context\n");
|
API_NAME_OPENGL_ES ")\n");
|
||||||
printf(" -f require a forward-compatible context\n");
|
printf(" -b, --behavior=BEHAVIOR the release behavior to use ("
|
||||||
printf(" -h show this help\n");
|
BEHAVIOR_NAME_NONE " or "
|
||||||
printf(" -l list all client API extensions after context creation\n");
|
BEHAVIOR_NAME_FLUSH ")\n");
|
||||||
printf(" -m the major number of the required client API version\n");
|
printf(" -d, --debug request a debug context\n");
|
||||||
printf(" -n the minor number of the required client API version\n");
|
printf(" -f, --forward require a forward-compatible context\n");
|
||||||
printf(" -p the OpenGL profile to use (" PROFILE_NAME_CORE " or " PROFILE_NAME_COMPAT ")\n");
|
printf(" -h, --help show this help\n");
|
||||||
printf(" -s the robustness strategy to use (" STRATEGY_NAME_NONE " or " STRATEGY_NAME_LOSE ")\n");
|
printf(" -l, --list-extensions list all client API extensions\n");
|
||||||
|
printf(" -m, --major=MAJOR the major number of the required "
|
||||||
|
"client API version\n");
|
||||||
|
printf(" -n, --minor=MINOR the minor number of the required "
|
||||||
|
"client API version\n");
|
||||||
|
printf(" -p, --profile=PROFILE the OpenGL profile to use ("
|
||||||
|
PROFILE_NAME_CORE " or "
|
||||||
|
PROFILE_NAME_COMPAT ")\n");
|
||||||
|
printf(" -s, --robustness=STRATEGY the robustness strategy to use ("
|
||||||
|
STRATEGY_NAME_NONE " or "
|
||||||
|
STRATEGY_NAME_LOSE ")\n");
|
||||||
|
printf(" -v, --version print version information\n");
|
||||||
|
printf(" --red-bits=N the number of red bits to request\n");
|
||||||
|
printf(" --green-bits=N the number of green bits to request\n");
|
||||||
|
printf(" --blue-bits=N the number of blue bits to request\n");
|
||||||
|
printf(" --alpha-bits=N the number of alpha bits to request\n");
|
||||||
|
printf(" --depth-bits=N the number of depth bits to request\n");
|
||||||
|
printf(" --stencil-bits=N the number of stencil bits to request\n");
|
||||||
|
printf(" --accum-red-bits=N the number of red bits to request\n");
|
||||||
|
printf(" --accum-green-bits=N the number of green bits to request\n");
|
||||||
|
printf(" --accum-blue-bits=N the number of blue bits to request\n");
|
||||||
|
printf(" --accum-alpha-bits=N the number of alpha bits to request\n");
|
||||||
|
printf(" --aux-buffers=N the number of aux buffers to request\n");
|
||||||
|
printf(" --samples=N the number of MSAA samples to request\n");
|
||||||
|
printf(" --stereo request stereo rendering\n");
|
||||||
|
printf(" --srgb request an sRGB capable framebuffer\n");
|
||||||
|
printf(" --singlebuffer request single-buffering\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void error_callback(int error, const char* description)
|
static void error_callback(int error, const char* description)
|
||||||
@@ -75,7 +100,7 @@ static void error_callback(int error, const char* description)
|
|||||||
fprintf(stderr, "Error: %s\n", description);
|
fprintf(stderr, "Error: %s\n", description);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* get_client_api_name(int api)
|
static const char* get_api_name(int api)
|
||||||
{
|
{
|
||||||
if (api == GLFW_OPENGL_API)
|
if (api == GLFW_OPENGL_API)
|
||||||
return "OpenGL";
|
return "OpenGL";
|
||||||
@@ -131,11 +156,12 @@ static void list_extensions(int api, int major, int minor)
|
|||||||
GLint count;
|
GLint count;
|
||||||
const GLubyte* extensions;
|
const GLubyte* extensions;
|
||||||
|
|
||||||
printf("%s context supported extensions:\n", get_client_api_name(api));
|
printf("%s context supported extensions:\n", get_api_name(api));
|
||||||
|
|
||||||
if (api == GLFW_OPENGL_API && major > 2)
|
if (api == GLFW_OPENGL_API && major > 2)
|
||||||
{
|
{
|
||||||
PFNGLGETSTRINGIPROC glGetStringi = (PFNGLGETSTRINGIPROC) glfwGetProcAddress("glGetStringi");
|
PFNGLGETSTRINGIPROC glGetStringi =
|
||||||
|
(PFNGLGETSTRINGIPROC) glfwGetProcAddress("glGetStringi");
|
||||||
if (!glGetStringi)
|
if (!glGetStringi)
|
||||||
{
|
{
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
@@ -167,16 +193,8 @@ static void list_extensions(int api, int major, int minor)
|
|||||||
static GLboolean valid_version(void)
|
static GLboolean valid_version(void)
|
||||||
{
|
{
|
||||||
int major, minor, revision;
|
int major, minor, revision;
|
||||||
|
|
||||||
glfwGetVersion(&major, &minor, &revision);
|
glfwGetVersion(&major, &minor, &revision);
|
||||||
|
|
||||||
printf("GLFW header version: %u.%u.%u\n",
|
|
||||||
GLFW_VERSION_MAJOR,
|
|
||||||
GLFW_VERSION_MINOR,
|
|
||||||
GLFW_VERSION_REVISION);
|
|
||||||
|
|
||||||
printf("GLFW library version: %u.%u.%u\n", major, minor, revision);
|
|
||||||
|
|
||||||
if (major != GLFW_VERSION_MAJOR)
|
if (major != GLFW_VERSION_MAJOR)
|
||||||
{
|
{
|
||||||
printf("*** ERROR: GLFW major version mismatch! ***\n");
|
printf("*** ERROR: GLFW major version mismatch! ***\n");
|
||||||
@@ -186,88 +204,64 @@ static GLboolean valid_version(void)
|
|||||||
if (minor != GLFW_VERSION_MINOR || revision != GLFW_VERSION_REVISION)
|
if (minor != GLFW_VERSION_MINOR || revision != GLFW_VERSION_REVISION)
|
||||||
printf("*** WARNING: GLFW version mismatch! ***\n");
|
printf("*** WARNING: GLFW version mismatch! ***\n");
|
||||||
|
|
||||||
printf("GLFW library version string: \"%s\"\n", glfwGetVersionString());
|
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void print_version(void)
|
||||||
|
{
|
||||||
|
int major, minor, revision;
|
||||||
|
glfwGetVersion(&major, &minor, &revision);
|
||||||
|
|
||||||
|
printf("GLFW header version: %u.%u.%u\n",
|
||||||
|
GLFW_VERSION_MAJOR,
|
||||||
|
GLFW_VERSION_MINOR,
|
||||||
|
GLFW_VERSION_REVISION);
|
||||||
|
printf("GLFW library version: %u.%u.%u\n", major, minor, revision);
|
||||||
|
printf("GLFW library version string: \"%s\"\n", glfwGetVersionString());
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int ch, api = 0, profile = 0, strategy = 0, behavior = 0, major = 1, minor = 0, revision;
|
int ch, api, major, minor, revision, profile;
|
||||||
GLboolean debug = GL_FALSE, forward = GL_FALSE, list = GL_FALSE;
|
GLint redbits, greenbits, bluebits, alphabits, depthbits, stencilbits;
|
||||||
GLint flags, mask;
|
GLboolean list = GL_FALSE;
|
||||||
GLFWwindow* window;
|
GLFWwindow* window;
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "a:b:dfhlm:n:p:s:")) != -1)
|
enum { API, BEHAVIOR, DEBUG, FORWARD, HELP, EXTENSIONS,
|
||||||
|
MAJOR, MINOR, PROFILE, ROBUSTNESS, VERSION,
|
||||||
|
REDBITS, GREENBITS, BLUEBITS, ALPHABITS, DEPTHBITS, STENCILBITS,
|
||||||
|
ACCUMREDBITS, ACCUMGREENBITS, ACCUMBLUEBITS, ACCUMALPHABITS,
|
||||||
|
AUXBUFFERS, SAMPLES, STEREO, SRGB, SINGLEBUFFER };
|
||||||
|
const struct option options[] =
|
||||||
{
|
{
|
||||||
switch (ch)
|
{ "behavior", 1, NULL, BEHAVIOR },
|
||||||
{
|
{ "client-api", 1, NULL, API },
|
||||||
case 'a':
|
{ "debug", 0, NULL, DEBUG },
|
||||||
if (strcasecmp(optarg, API_OPENGL) == 0)
|
{ "forward", 0, NULL, FORWARD },
|
||||||
api = GLFW_OPENGL_API;
|
{ "help", 0, NULL, HELP },
|
||||||
else if (strcasecmp(optarg, API_OPENGL_ES) == 0)
|
{ "list-extensions", 0, NULL, EXTENSIONS },
|
||||||
api = GLFW_OPENGL_ES_API;
|
{ "major", 1, NULL, MAJOR },
|
||||||
else
|
{ "minor", 1, NULL, MINOR },
|
||||||
{
|
{ "profile", 1, NULL, PROFILE },
|
||||||
usage();
|
{ "robustness", 1, NULL, ROBUSTNESS },
|
||||||
exit(EXIT_FAILURE);
|
{ "version", 0, NULL, VERSION },
|
||||||
}
|
{ "red-bits", 1, NULL, REDBITS },
|
||||||
break;
|
{ "green-bits", 1, NULL, GREENBITS },
|
||||||
case 'b':
|
{ "blue-bits", 1, NULL, BLUEBITS },
|
||||||
if (strcasecmp(optarg, BEHAVIOR_NAME_NONE) == 0)
|
{ "alpha-bits", 1, NULL, ALPHABITS },
|
||||||
behavior = GLFW_RELEASE_BEHAVIOR_NONE;
|
{ "depth-bits", 1, NULL, DEPTHBITS },
|
||||||
else if (strcasecmp(optarg, BEHAVIOR_NAME_FLUSH) == 0)
|
{ "stencil-bits", 1, NULL, STENCILBITS },
|
||||||
behavior = GLFW_RELEASE_BEHAVIOR_FLUSH;
|
{ "accum-red-bits", 1, NULL, ACCUMREDBITS },
|
||||||
else
|
{ "accum-green-bits", 1, NULL, ACCUMGREENBITS },
|
||||||
{
|
{ "accum-blue-bits", 1, NULL, ACCUMBLUEBITS },
|
||||||
usage();
|
{ "accum-alpha-bits", 1, NULL, ACCUMALPHABITS },
|
||||||
exit(EXIT_FAILURE);
|
{ "aux-buffers", 1, NULL, AUXBUFFERS },
|
||||||
}
|
{ "samples", 1, NULL, SAMPLES },
|
||||||
break;
|
{ "stereo", 0, NULL, STEREO },
|
||||||
case 'd':
|
{ "srgb", 0, NULL, SRGB },
|
||||||
debug = GL_TRUE;
|
{ "singlebuffer", 0, NULL, SINGLEBUFFER },
|
||||||
break;
|
{ NULL, 0, NULL, 0 }
|
||||||
case 'f':
|
};
|
||||||
forward = GL_TRUE;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
usage();
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
case 'l':
|
|
||||||
list = GL_TRUE;
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
major = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
minor = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
if (strcasecmp(optarg, PROFILE_NAME_CORE) == 0)
|
|
||||||
profile = GLFW_OPENGL_CORE_PROFILE;
|
|
||||||
else if (strcasecmp(optarg, PROFILE_NAME_COMPAT) == 0)
|
|
||||||
profile = GLFW_OPENGL_COMPAT_PROFILE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
usage();
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
if (strcasecmp(optarg, STRATEGY_NAME_NONE) == 0)
|
|
||||||
strategy = GLFW_NO_RESET_NOTIFICATION;
|
|
||||||
else if (strcasecmp(optarg, STRATEGY_NAME_LOSE) == 0)
|
|
||||||
strategy = GLFW_LOSE_CONTEXT_ON_RESET;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
usage();
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize GLFW and create window
|
// Initialize GLFW and create window
|
||||||
|
|
||||||
@@ -279,43 +273,192 @@ int main(int argc, char** argv)
|
|||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
if (major != 1 || minor != 0)
|
while ((ch = getopt_long(argc, argv, "a:b:dfhlm:n:p:s:v", options, NULL)) != -1)
|
||||||
{
|
{
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, major);
|
switch (ch)
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, minor);
|
{
|
||||||
|
case 'a':
|
||||||
|
case API:
|
||||||
|
if (strcasecmp(optarg, API_NAME_OPENGL) == 0)
|
||||||
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
|
||||||
|
else if (strcasecmp(optarg, API_NAME_OPENGL_ES) == 0)
|
||||||
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
usage();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
case BEHAVIOR:
|
||||||
|
if (strcasecmp(optarg, BEHAVIOR_NAME_NONE) == 0)
|
||||||
|
{
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_RELEASE_BEHAVIOR,
|
||||||
|
GLFW_RELEASE_BEHAVIOR_NONE);
|
||||||
|
}
|
||||||
|
else if (strcasecmp(optarg, BEHAVIOR_NAME_FLUSH) == 0)
|
||||||
|
{
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_RELEASE_BEHAVIOR,
|
||||||
|
GLFW_RELEASE_BEHAVIOR_FLUSH);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
usage();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
case DEBUG:
|
||||||
|
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
case FORWARD:
|
||||||
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
case HELP:
|
||||||
|
usage();
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
case 'l':
|
||||||
|
case EXTENSIONS:
|
||||||
|
list = GL_TRUE;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
case MAJOR:
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, atoi(optarg));
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
case MINOR:
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, atoi(optarg));
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
case PROFILE:
|
||||||
|
if (strcasecmp(optarg, PROFILE_NAME_CORE) == 0)
|
||||||
|
{
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE,
|
||||||
|
GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
}
|
||||||
|
else if (strcasecmp(optarg, PROFILE_NAME_COMPAT) == 0)
|
||||||
|
{
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE,
|
||||||
|
GLFW_OPENGL_COMPAT_PROFILE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
usage();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
case ROBUSTNESS:
|
||||||
|
if (strcasecmp(optarg, STRATEGY_NAME_NONE) == 0)
|
||||||
|
{
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS,
|
||||||
|
GLFW_NO_RESET_NOTIFICATION);
|
||||||
|
}
|
||||||
|
else if (strcasecmp(optarg, STRATEGY_NAME_LOSE) == 0)
|
||||||
|
{
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS,
|
||||||
|
GLFW_LOSE_CONTEXT_ON_RESET);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
usage();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
case VERSION:
|
||||||
|
print_version();
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
case REDBITS:
|
||||||
|
if (strcmp(optarg, "-") == 0)
|
||||||
|
glfwWindowHint(GLFW_RED_BITS, GLFW_DONT_CARE);
|
||||||
|
else
|
||||||
|
glfwWindowHint(GLFW_RED_BITS, atoi(optarg));
|
||||||
|
break;
|
||||||
|
case GREENBITS:
|
||||||
|
if (strcmp(optarg, "-") == 0)
|
||||||
|
glfwWindowHint(GLFW_GREEN_BITS, GLFW_DONT_CARE);
|
||||||
|
else
|
||||||
|
glfwWindowHint(GLFW_GREEN_BITS, atoi(optarg));
|
||||||
|
break;
|
||||||
|
case BLUEBITS:
|
||||||
|
if (strcmp(optarg, "-") == 0)
|
||||||
|
glfwWindowHint(GLFW_BLUE_BITS, GLFW_DONT_CARE);
|
||||||
|
else
|
||||||
|
glfwWindowHint(GLFW_BLUE_BITS, atoi(optarg));
|
||||||
|
break;
|
||||||
|
case ALPHABITS:
|
||||||
|
if (strcmp(optarg, "-") == 0)
|
||||||
|
glfwWindowHint(GLFW_ALPHA_BITS, GLFW_DONT_CARE);
|
||||||
|
else
|
||||||
|
glfwWindowHint(GLFW_ALPHA_BITS, atoi(optarg));
|
||||||
|
break;
|
||||||
|
case DEPTHBITS:
|
||||||
|
if (strcmp(optarg, "-") == 0)
|
||||||
|
glfwWindowHint(GLFW_DEPTH_BITS, GLFW_DONT_CARE);
|
||||||
|
else
|
||||||
|
glfwWindowHint(GLFW_DEPTH_BITS, atoi(optarg));
|
||||||
|
break;
|
||||||
|
case STENCILBITS:
|
||||||
|
if (strcmp(optarg, "-") == 0)
|
||||||
|
glfwWindowHint(GLFW_STENCIL_BITS, GLFW_DONT_CARE);
|
||||||
|
else
|
||||||
|
glfwWindowHint(GLFW_STENCIL_BITS, atoi(optarg));
|
||||||
|
break;
|
||||||
|
case ACCUMREDBITS:
|
||||||
|
if (strcmp(optarg, "-") == 0)
|
||||||
|
glfwWindowHint(GLFW_ACCUM_RED_BITS, GLFW_DONT_CARE);
|
||||||
|
else
|
||||||
|
glfwWindowHint(GLFW_ACCUM_RED_BITS, atoi(optarg));
|
||||||
|
break;
|
||||||
|
case ACCUMGREENBITS:
|
||||||
|
if (strcmp(optarg, "-") == 0)
|
||||||
|
glfwWindowHint(GLFW_ACCUM_GREEN_BITS, GLFW_DONT_CARE);
|
||||||
|
else
|
||||||
|
glfwWindowHint(GLFW_ACCUM_GREEN_BITS, atoi(optarg));
|
||||||
|
break;
|
||||||
|
case ACCUMBLUEBITS:
|
||||||
|
if (strcmp(optarg, "-") == 0)
|
||||||
|
glfwWindowHint(GLFW_ACCUM_BLUE_BITS, GLFW_DONT_CARE);
|
||||||
|
else
|
||||||
|
glfwWindowHint(GLFW_ACCUM_BLUE_BITS, atoi(optarg));
|
||||||
|
break;
|
||||||
|
case ACCUMALPHABITS:
|
||||||
|
if (strcmp(optarg, "-") == 0)
|
||||||
|
glfwWindowHint(GLFW_ACCUM_ALPHA_BITS, GLFW_DONT_CARE);
|
||||||
|
else
|
||||||
|
glfwWindowHint(GLFW_ACCUM_ALPHA_BITS, atoi(optarg));
|
||||||
|
break;
|
||||||
|
case AUXBUFFERS:
|
||||||
|
if (strcmp(optarg, "-") == 0)
|
||||||
|
glfwWindowHint(GLFW_AUX_BUFFERS, GLFW_DONT_CARE);
|
||||||
|
else
|
||||||
|
glfwWindowHint(GLFW_AUX_BUFFERS, atoi(optarg));
|
||||||
|
break;
|
||||||
|
case SAMPLES:
|
||||||
|
if (strcmp(optarg, "-") == 0)
|
||||||
|
glfwWindowHint(GLFW_SAMPLES, GLFW_DONT_CARE);
|
||||||
|
else
|
||||||
|
glfwWindowHint(GLFW_SAMPLES, atoi(optarg));
|
||||||
|
break;
|
||||||
|
case STEREO:
|
||||||
|
glfwWindowHint(GLFW_STEREO, GL_TRUE);
|
||||||
|
break;
|
||||||
|
case SRGB:
|
||||||
|
glfwWindowHint(GLFW_SRGB_CAPABLE, GL_TRUE);
|
||||||
|
break;
|
||||||
|
case SINGLEBUFFER:
|
||||||
|
glfwWindowHint(GLFW_DOUBLEBUFFER, GL_FALSE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (api != 0)
|
print_version();
|
||||||
glfwWindowHint(GLFW_CLIENT_API, api);
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
|
|
||||||
|
|
||||||
if (forward)
|
|
||||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
|
||||||
|
|
||||||
if (profile != 0)
|
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, profile);
|
|
||||||
|
|
||||||
if (strategy)
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS, strategy);
|
|
||||||
|
|
||||||
if (behavior)
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_RELEASE_BEHAVIOR, behavior);
|
|
||||||
|
|
||||||
glfwWindowHint(GLFW_RED_BITS, GLFW_DONT_CARE);
|
|
||||||
glfwWindowHint(GLFW_GREEN_BITS, GLFW_DONT_CARE);
|
|
||||||
glfwWindowHint(GLFW_BLUE_BITS, GLFW_DONT_CARE);
|
|
||||||
glfwWindowHint(GLFW_ALPHA_BITS, GLFW_DONT_CARE);
|
|
||||||
glfwWindowHint(GLFW_DEPTH_BITS, GLFW_DONT_CARE);
|
|
||||||
glfwWindowHint(GLFW_STENCIL_BITS, GLFW_DONT_CARE);
|
|
||||||
glfwWindowHint(GLFW_ACCUM_RED_BITS, GLFW_DONT_CARE);
|
|
||||||
glfwWindowHint(GLFW_ACCUM_GREEN_BITS, GLFW_DONT_CARE);
|
|
||||||
glfwWindowHint(GLFW_ACCUM_BLUE_BITS, GLFW_DONT_CARE);
|
|
||||||
glfwWindowHint(GLFW_ACCUM_ALPHA_BITS, GLFW_DONT_CARE);
|
|
||||||
glfwWindowHint(GLFW_AUX_BUFFERS, GLFW_DONT_CARE);
|
|
||||||
glfwWindowHint(GLFW_SAMPLES, GLFW_DONT_CARE);
|
|
||||||
glfwWindowHint(GLFW_SRGB_CAPABLE, GLFW_DONT_CARE);
|
|
||||||
|
|
||||||
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
|
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
|
||||||
|
|
||||||
@@ -334,13 +477,14 @@ int main(int argc, char** argv)
|
|||||||
major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR);
|
major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR);
|
||||||
minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR);
|
minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR);
|
||||||
revision = glfwGetWindowAttrib(window, GLFW_CONTEXT_REVISION);
|
revision = glfwGetWindowAttrib(window, GLFW_CONTEXT_REVISION);
|
||||||
|
profile = glfwGetWindowAttrib(window, GLFW_OPENGL_PROFILE);
|
||||||
|
|
||||||
printf("%s context version string: \"%s\"\n",
|
printf("%s context version string: \"%s\"\n",
|
||||||
get_client_api_name(api),
|
get_api_name(api),
|
||||||
glGetString(GL_VERSION));
|
glGetString(GL_VERSION));
|
||||||
|
|
||||||
printf("%s context version parsed by GLFW: %u.%u.%u\n",
|
printf("%s context version parsed by GLFW: %u.%u.%u\n",
|
||||||
get_client_api_name(api),
|
get_api_name(api),
|
||||||
major, minor, revision);
|
major, minor, revision);
|
||||||
|
|
||||||
// Report client API context properties
|
// Report client API context properties
|
||||||
@@ -349,8 +493,10 @@ int main(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
if (major >= 3)
|
if (major >= 3)
|
||||||
{
|
{
|
||||||
|
GLint flags;
|
||||||
|
|
||||||
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
|
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
|
||||||
printf("%s context flags (0x%08x):", get_client_api_name(api), flags);
|
printf("%s context flags (0x%08x):", get_api_name(api), flags);
|
||||||
|
|
||||||
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
|
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
|
||||||
printf(" forward-compatible");
|
printf(" forward-compatible");
|
||||||
@@ -360,65 +506,141 @@ int main(int argc, char** argv)
|
|||||||
printf(" robustness");
|
printf(" robustness");
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
|
|
||||||
printf("%s context flags parsed by GLFW:", get_client_api_name(api));
|
printf("%s context flags parsed by GLFW:", get_api_name(api));
|
||||||
|
|
||||||
if (glfwGetWindowAttrib(window, GLFW_OPENGL_FORWARD_COMPAT))
|
if (glfwGetWindowAttrib(window, GLFW_OPENGL_FORWARD_COMPAT))
|
||||||
printf(" forward-compatible");
|
printf(" forward-compatible");
|
||||||
if (glfwGetWindowAttrib(window, GLFW_OPENGL_DEBUG_CONTEXT))
|
if (glfwGetWindowAttrib(window, GLFW_OPENGL_DEBUG_CONTEXT))
|
||||||
printf(" debug");
|
printf(" debug");
|
||||||
if (glfwGetWindowAttrib(window, GLFW_CONTEXT_ROBUSTNESS) != GLFW_NO_ROBUSTNESS)
|
if (glfwGetWindowAttrib(window, GLFW_CONTEXT_ROBUSTNESS) == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||||
printf(" robustness");
|
printf(" robustness");
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (major > 3 || (major == 3 && minor >= 2))
|
if (major >= 4 || (major == 3 && minor >= 2))
|
||||||
{
|
{
|
||||||
int profile = glfwGetWindowAttrib(window, GLFW_OPENGL_PROFILE);
|
GLint mask;
|
||||||
|
|
||||||
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
|
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
|
||||||
|
|
||||||
printf("%s profile mask (0x%08x): %s\n",
|
printf("%s profile mask (0x%08x): %s\n",
|
||||||
get_client_api_name(api),
|
get_api_name(api),
|
||||||
mask,
|
mask,
|
||||||
get_profile_name_gl(mask));
|
get_profile_name_gl(mask));
|
||||||
|
|
||||||
printf("%s profile mask parsed by GLFW: %s\n",
|
printf("%s profile mask parsed by GLFW: %s\n",
|
||||||
get_client_api_name(api),
|
get_api_name(api),
|
||||||
get_profile_name_glfw(profile));
|
get_profile_name_glfw(profile));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glfwExtensionSupported("GL_ARB_robustness"))
|
if (glfwExtensionSupported("GL_ARB_robustness"))
|
||||||
{
|
{
|
||||||
int robustness;
|
const int robustness = glfwGetWindowAttrib(window, GLFW_CONTEXT_ROBUSTNESS);
|
||||||
GLint strategy;
|
GLint strategy;
|
||||||
glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
|
glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
|
||||||
|
|
||||||
printf("%s robustness strategy (0x%08x): %s\n",
|
printf("%s robustness strategy (0x%08x): %s\n",
|
||||||
get_client_api_name(api),
|
get_api_name(api),
|
||||||
strategy,
|
strategy,
|
||||||
get_strategy_name_gl(strategy));
|
get_strategy_name_gl(strategy));
|
||||||
|
|
||||||
robustness = glfwGetWindowAttrib(window, GLFW_CONTEXT_ROBUSTNESS);
|
|
||||||
|
|
||||||
printf("%s robustness strategy parsed by GLFW: %s\n",
|
printf("%s robustness strategy parsed by GLFW: %s\n",
|
||||||
get_client_api_name(api),
|
get_api_name(api),
|
||||||
get_strategy_name_glfw(robustness));
|
get_strategy_name_glfw(robustness));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%s context renderer string: \"%s\"\n",
|
printf("%s context renderer string: \"%s\"\n",
|
||||||
get_client_api_name(api),
|
get_api_name(api),
|
||||||
glGetString(GL_RENDERER));
|
glGetString(GL_RENDERER));
|
||||||
printf("%s context vendor string: \"%s\"\n",
|
printf("%s context vendor string: \"%s\"\n",
|
||||||
get_client_api_name(api),
|
get_api_name(api),
|
||||||
glGetString(GL_VENDOR));
|
glGetString(GL_VENDOR));
|
||||||
|
|
||||||
if (major > 1)
|
if (major >= 2)
|
||||||
{
|
{
|
||||||
printf("%s context shading language version: \"%s\"\n",
|
printf("%s context shading language version: \"%s\"\n",
|
||||||
get_client_api_name(api),
|
get_api_name(api),
|
||||||
glGetString(GL_SHADING_LANGUAGE_VERSION));
|
glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("Framebuffer:\n");
|
||||||
|
|
||||||
|
if (api == GLFW_OPENGL_API && profile == GLFW_OPENGL_CORE_PROFILE)
|
||||||
|
{
|
||||||
|
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC
|
||||||
|
glGetFramebufferAttachmentParameteriv =
|
||||||
|
(PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)
|
||||||
|
glfwGetProcAddress("glGetFramebufferAttachmentParameteriv");
|
||||||
|
if (!glGetFramebufferAttachmentParameteriv)
|
||||||
|
{
|
||||||
|
glfwTerminate();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
|
||||||
|
GL_BACK_LEFT,
|
||||||
|
GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE,
|
||||||
|
&redbits);
|
||||||
|
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
|
||||||
|
GL_BACK_LEFT,
|
||||||
|
GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE,
|
||||||
|
&greenbits);
|
||||||
|
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
|
||||||
|
GL_BACK_LEFT,
|
||||||
|
GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE,
|
||||||
|
&bluebits);
|
||||||
|
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
|
||||||
|
GL_BACK_LEFT,
|
||||||
|
GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
|
||||||
|
&alphabits);
|
||||||
|
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
|
||||||
|
GL_DEPTH,
|
||||||
|
GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE,
|
||||||
|
&depthbits);
|
||||||
|
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
|
||||||
|
GL_STENCIL,
|
||||||
|
GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
|
||||||
|
&stencilbits);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glGetIntegerv(GL_RED_BITS, &redbits);
|
||||||
|
glGetIntegerv(GL_GREEN_BITS, &greenbits);
|
||||||
|
glGetIntegerv(GL_BLUE_BITS, &bluebits);
|
||||||
|
glGetIntegerv(GL_ALPHA_BITS, &alphabits);
|
||||||
|
glGetIntegerv(GL_DEPTH_BITS, &depthbits);
|
||||||
|
glGetIntegerv(GL_STENCIL_BITS, &stencilbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" red: %u green: %u blue: %u alpha: %u depth: %u stencil: %u\n",
|
||||||
|
redbits, greenbits, bluebits, alphabits, depthbits, stencilbits);
|
||||||
|
|
||||||
|
if (api == GLFW_OPENGL_ES_API ||
|
||||||
|
glfwExtensionSupported("GL_ARB_multisample") ||
|
||||||
|
major > 1 || minor >= 3)
|
||||||
|
{
|
||||||
|
GLint samples, samplebuffers;
|
||||||
|
glGetIntegerv(GL_SAMPLES, &samples);
|
||||||
|
glGetIntegerv(GL_SAMPLE_BUFFERS, &samplebuffers);
|
||||||
|
|
||||||
|
printf(" samples: %u sample buffers: %u\n", samples, samplebuffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (api == GLFW_OPENGL_API && profile != GLFW_OPENGL_CORE_PROFILE)
|
||||||
|
{
|
||||||
|
GLint accumredbits, accumgreenbits, accumbluebits, accumalphabits;
|
||||||
|
GLint auxbuffers;
|
||||||
|
|
||||||
|
glGetIntegerv(GL_ACCUM_RED_BITS, &accumredbits);
|
||||||
|
glGetIntegerv(GL_ACCUM_GREEN_BITS, &accumgreenbits);
|
||||||
|
glGetIntegerv(GL_ACCUM_BLUE_BITS, &accumbluebits);
|
||||||
|
glGetIntegerv(GL_ACCUM_ALPHA_BITS, &accumalphabits);
|
||||||
|
glGetIntegerv(GL_AUX_BUFFERS, &auxbuffers);
|
||||||
|
|
||||||
|
printf(" accum red: %u accum green: %u accum blue: %u accum alpha: %u aux buffers: %u\n",
|
||||||
|
accumredbits, accumgreenbits, accumbluebits, accumalphabits, auxbuffers);
|
||||||
|
}
|
||||||
|
|
||||||
// Report client API extensions
|
// Report client API extensions
|
||||||
if (list)
|
if (list)
|
||||||
list_extensions(api, major, minor);
|
list_extensions(api, major, minor);
|
||||||
|
|||||||
@@ -99,6 +99,9 @@ static void window_iconify_callback(GLFWwindow* window, int iconified)
|
|||||||
static void window_refresh_callback(GLFWwindow* window)
|
static void window_refresh_callback(GLFWwindow* window)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|
||||||
|
printf("%0.2f Window refresh\n", glfwGetTime());
|
||||||
|
|
||||||
glfwGetFramebufferSize(window, &width, &height);
|
glfwGetFramebufferSize(window, &width, &height);
|
||||||
|
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
|
|||||||
+3
-3
@@ -83,7 +83,7 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
|
|||||||
|
|
||||||
static void list_modes(GLFWmonitor* monitor)
|
static void list_modes(GLFWmonitor* monitor)
|
||||||
{
|
{
|
||||||
int count, x, y, widthMM, heightMM, dpi, i;
|
int count, x, y, widthMM, heightMM, i;
|
||||||
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
||||||
const GLFWvidmode* modes = glfwGetVideoModes(monitor, &count);
|
const GLFWvidmode* modes = glfwGetVideoModes(monitor, &count);
|
||||||
|
|
||||||
@@ -96,8 +96,8 @@ static void list_modes(GLFWmonitor* monitor)
|
|||||||
printf("Current mode: %s\n", format_mode(mode));
|
printf("Current mode: %s\n", format_mode(mode));
|
||||||
printf("Virtual position: %i %i\n", x, y);
|
printf("Virtual position: %i %i\n", x, y);
|
||||||
|
|
||||||
dpi = (int) ((float) mode->width * 25.4f / (float) widthMM);
|
printf("Physical size: %i x %i mm (%0.2f dpi)\n",
|
||||||
printf("Physical size: %i x %i mm (%i dpi)\n", widthMM, heightMM, dpi);
|
widthMM, heightMM, mode->width * 25.4f / widthMM);
|
||||||
|
|
||||||
printf("Modes:\n");
|
printf("Modes:\n");
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// Full screen anti-aliasing test
|
// Multisample anti-aliasing test
|
||||||
// Copyright (c) Camilla Berglund <elmindreda@elmindreda.org>
|
// Copyright (c) Camilla Berglund <elmindreda@elmindreda.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
//
|
//
|
||||||
// This test renders two high contrast, slowly rotating quads, one aliased
|
// This test renders two high contrast, slowly rotating quads, one aliased
|
||||||
// and one (hopefully) anti-aliased, thus allowing for visual verification
|
// and one (hopefully) anti-aliased, thus allowing for visual verification
|
||||||
// of whether FSAA is indeed enabled
|
// of whether MSAA is indeed enabled
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
|
|||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
printf("Usage: fsaa [-h] [-s SAMPLES]\n");
|
printf("Usage: msaa [-h] [-s SAMPLES]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
@@ -92,9 +92,9 @@ int main(int argc, char** argv)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
if (samples)
|
if (samples)
|
||||||
printf("Requesting FSAA with %i samples\n", samples);
|
printf("Requesting MSAA with %i samples\n", samples);
|
||||||
else
|
else
|
||||||
printf("Requesting that FSAA not be available\n");
|
printf("Requesting that MSAA not be available\n");
|
||||||
|
|
||||||
glfwWindowHint(GLFW_SAMPLES, samples);
|
glfwWindowHint(GLFW_SAMPLES, samples);
|
||||||
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
|
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
|
||||||
@@ -124,9 +124,9 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
glGetIntegerv(GL_SAMPLES_ARB, &samples);
|
glGetIntegerv(GL_SAMPLES_ARB, &samples);
|
||||||
if (samples)
|
if (samples)
|
||||||
printf("Context reports FSAA is available with %i samples\n", samples);
|
printf("Context reports MSAA is available with %i samples\n", samples);
|
||||||
else
|
else
|
||||||
printf("Context reports FSAA is unavailable\n");
|
printf("Context reports MSAA is unavailable\n");
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glOrtho(0.f, 1.f, 0.f, 0.5f, 0.f, 1.f);
|
glOrtho(0.f, 1.f, 0.f, 0.5f, 0.f, 1.f);
|
||||||
-151
@@ -1,151 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// Cursor mode test
|
|
||||||
// Copyright (c) Camilla Berglund <elmindreda@elmindreda.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.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
//
|
|
||||||
// This test allows you to switch between the various cursor modes
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
static GLboolean reopen = GL_FALSE;
|
|
||||||
static double cursor_x;
|
|
||||||
static double cursor_y;
|
|
||||||
|
|
||||||
static void error_callback(int error, const char* description)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Error: %s\n", description);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cursor_position_callback(GLFWwindow* window, double x, double y)
|
|
||||||
{
|
|
||||||
printf("%0.3f: Cursor position: %f %f (%f %f)\n",
|
|
||||||
glfwGetTime(),
|
|
||||||
x, y, x - cursor_x, y - cursor_y);
|
|
||||||
|
|
||||||
cursor_x = x;
|
|
||||||
cursor_y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
|
||||||
{
|
|
||||||
if (action != GLFW_PRESS)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (key)
|
|
||||||
{
|
|
||||||
case GLFW_KEY_D:
|
|
||||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
|
||||||
printf("(( cursor is disabled ))\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GLFW_KEY_H:
|
|
||||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
|
||||||
printf("(( cursor is hidden ))\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GLFW_KEY_N:
|
|
||||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
|
||||||
printf("(( cursor is normal ))\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GLFW_KEY_R:
|
|
||||||
reopen = GL_TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
|
||||||
{
|
|
||||||
glViewport(0, 0, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GLFWwindow* open_window(void)
|
|
||||||
{
|
|
||||||
GLFWwindow* window = glfwCreateWindow(640, 480, "Peter Detector", NULL, NULL);
|
|
||||||
if (!window)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
glfwMakeContextCurrent(window);
|
|
||||||
glfwSwapInterval(1);
|
|
||||||
|
|
||||||
glfwGetCursorPos(window, &cursor_x, &cursor_y);
|
|
||||||
printf("Cursor position: %f %f\n", cursor_x, cursor_y);
|
|
||||||
|
|
||||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
|
||||||
glfwSetCursorPosCallback(window, cursor_position_callback);
|
|
||||||
glfwSetKeyCallback(window, key_callback);
|
|
||||||
|
|
||||||
return window;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
GLFWwindow* window;
|
|
||||||
|
|
||||||
glfwSetErrorCallback(error_callback);
|
|
||||||
|
|
||||||
if (!glfwInit())
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
|
|
||||||
window = open_window();
|
|
||||||
if (!window)
|
|
||||||
{
|
|
||||||
glfwTerminate();
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
glClearColor(0.f, 0.f, 0.f, 0.f);
|
|
||||||
|
|
||||||
while (!glfwWindowShouldClose(window))
|
|
||||||
{
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
|
|
||||||
glfwSwapBuffers(window);
|
|
||||||
glfwWaitEvents();
|
|
||||||
|
|
||||||
if (reopen)
|
|
||||||
{
|
|
||||||
glfwDestroyWindow(window);
|
|
||||||
window = open_window();
|
|
||||||
if (!window)
|
|
||||||
{
|
|
||||||
glfwTerminate();
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
reopen = GL_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Workaround for an issue with msvcrt and mintty
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwTerminate();
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
+14
-1
@@ -122,6 +122,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
int width, height;
|
||||||
GLFWmonitor* monitor = NULL;
|
GLFWmonitor* monitor = NULL;
|
||||||
|
|
||||||
if (count % 2 == 0)
|
if (count % 2 == 0)
|
||||||
@@ -131,7 +132,19 @@ int main(int argc, char** argv)
|
|||||||
monitor = monitors[rand() % monitorCount];
|
monitor = monitors[rand() % monitorCount];
|
||||||
}
|
}
|
||||||
|
|
||||||
window = open_window(640, 480, monitor);
|
if (monitor)
|
||||||
|
{
|
||||||
|
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
||||||
|
width = mode->width;
|
||||||
|
height = mode->height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
width = 640;
|
||||||
|
height = 480;
|
||||||
|
}
|
||||||
|
|
||||||
|
window = open_window(width, height, monitor);
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
|
|||||||
+88
-6
@@ -34,15 +34,28 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "getopt.h"
|
||||||
|
|
||||||
|
static GLboolean swap_tear;
|
||||||
static int swap_interval;
|
static int swap_interval;
|
||||||
static double frame_rate;
|
static double frame_rate;
|
||||||
|
|
||||||
|
static void usage(void)
|
||||||
|
{
|
||||||
|
printf("Usage: iconify [-h] [-f]\n");
|
||||||
|
printf("Options:\n");
|
||||||
|
printf(" -f create full screen window\n");
|
||||||
|
printf(" -h show this help\n");
|
||||||
|
}
|
||||||
|
|
||||||
static void update_window_title(GLFWwindow* window)
|
static void update_window_title(GLFWwindow* window)
|
||||||
{
|
{
|
||||||
char title[256];
|
char title[256];
|
||||||
|
|
||||||
sprintf(title, "Tearing detector (interval %i, %0.1f Hz)",
|
sprintf(title, "Tearing detector (interval %i%s, %0.1f Hz)",
|
||||||
swap_interval, frame_rate);
|
swap_interval,
|
||||||
|
(swap_tear && swap_interval < 0) ? " (swap tear)" : "",
|
||||||
|
frame_rate);
|
||||||
|
|
||||||
glfwSetWindowTitle(window, title);
|
glfwSetWindowTitle(window, title);
|
||||||
}
|
}
|
||||||
@@ -66,23 +79,90 @@ static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
|||||||
|
|
||||||
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||||
{
|
{
|
||||||
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
|
if (action != GLFW_PRESS)
|
||||||
set_swap_interval(window, 1 - swap_interval);
|
return;
|
||||||
|
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case GLFW_KEY_UP:
|
||||||
|
{
|
||||||
|
if (swap_interval + 1 > swap_interval)
|
||||||
|
set_swap_interval(window, swap_interval + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GLFW_KEY_DOWN:
|
||||||
|
{
|
||||||
|
if (swap_tear)
|
||||||
|
{
|
||||||
|
if (swap_interval - 1 < swap_interval)
|
||||||
|
set_swap_interval(window, swap_interval - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (swap_interval - 1 >= 0)
|
||||||
|
set_swap_interval(window, swap_interval - 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GLFW_KEY_ESCAPE:
|
||||||
|
glfwSetWindowShouldClose(window, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
int ch, width, height;
|
||||||
float position;
|
float position;
|
||||||
unsigned long frame_count = 0;
|
unsigned long frame_count = 0;
|
||||||
double last_time, current_time;
|
double last_time, current_time;
|
||||||
|
GLboolean fullscreen = GL_FALSE;
|
||||||
|
GLFWmonitor* monitor = NULL;
|
||||||
GLFWwindow* window;
|
GLFWwindow* window;
|
||||||
|
|
||||||
|
while ((ch = getopt(argc, argv, "fh")) != -1)
|
||||||
|
{
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case 'h':
|
||||||
|
usage();
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
fullscreen = GL_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glfwSetErrorCallback(error_callback);
|
glfwSetErrorCallback(error_callback);
|
||||||
|
|
||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
window = glfwCreateWindow(640, 480, "", NULL, NULL);
|
if (fullscreen)
|
||||||
|
{
|
||||||
|
const GLFWvidmode* mode;
|
||||||
|
|
||||||
|
monitor = glfwGetPrimaryMonitor();
|
||||||
|
mode = glfwGetVideoMode(monitor);
|
||||||
|
|
||||||
|
glfwWindowHint(GLFW_RED_BITS, mode->redBits);
|
||||||
|
glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
|
||||||
|
glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
|
||||||
|
glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
|
||||||
|
|
||||||
|
width = mode->width;
|
||||||
|
height = mode->height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
width = 640;
|
||||||
|
height = 480;
|
||||||
|
}
|
||||||
|
|
||||||
|
window = glfwCreateWindow(width, height, "", monitor, NULL);
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
@@ -94,6 +174,8 @@ int main(void)
|
|||||||
|
|
||||||
last_time = glfwGetTime();
|
last_time = glfwGetTime();
|
||||||
frame_rate = 0.0;
|
frame_rate = 0.0;
|
||||||
|
swap_tear = (glfwExtensionSupported("WGL_EXT_swap_control_tear") ||
|
||||||
|
glfwExtensionSupported("GLX_EXT_swap_control_tear"));
|
||||||
|
|
||||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||||
glfwSetKeyCallback(window, key_callback);
|
glfwSetKeyCallback(window, key_callback);
|
||||||
|
|||||||
+31
-11
@@ -32,12 +32,23 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
static const char* titles[4] =
|
static const char* titles[] =
|
||||||
{
|
{
|
||||||
"Foo",
|
"Red",
|
||||||
"Bar",
|
"Green",
|
||||||
"Baz",
|
"Blue",
|
||||||
"Quux"
|
"Yellow"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct
|
||||||
|
{
|
||||||
|
float r, g, b;
|
||||||
|
} colors[] =
|
||||||
|
{
|
||||||
|
{ 0.95f, 0.32f, 0.11f },
|
||||||
|
{ 0.50f, 0.80f, 0.16f },
|
||||||
|
{ 0.f, 0.68f, 0.94f },
|
||||||
|
{ 0.98f, 0.74f, 0.04f }
|
||||||
};
|
};
|
||||||
|
|
||||||
static void error_callback(int error, const char* description)
|
static void error_callback(int error, const char* description)
|
||||||
@@ -47,15 +58,26 @@ static void error_callback(int error, const char* description)
|
|||||||
|
|
||||||
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||||
{
|
{
|
||||||
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
|
if (action != GLFW_PRESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case GLFW_KEY_SPACE:
|
||||||
{
|
{
|
||||||
int xpos, ypos;
|
int xpos, ypos;
|
||||||
glfwGetWindowPos(window, &xpos, &ypos);
|
glfwGetWindowPos(window, &xpos, &ypos);
|
||||||
glfwSetWindowPos(window, xpos, ypos);
|
glfwSetWindowPos(window, xpos, ypos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GLFW_KEY_ESCAPE:
|
||||||
|
glfwSetWindowShouldClose(window, GL_TRUE);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
GLboolean running = GL_TRUE;
|
GLboolean running = GL_TRUE;
|
||||||
@@ -66,6 +88,7 @@ int main(void)
|
|||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
glfwWindowHint(GLFW_DECORATED, GL_FALSE);
|
||||||
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
|
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
@@ -82,10 +105,7 @@ int main(void)
|
|||||||
glfwSetKeyCallback(windows[i], key_callback);
|
glfwSetKeyCallback(windows[i], key_callback);
|
||||||
|
|
||||||
glfwMakeContextCurrent(windows[i]);
|
glfwMakeContextCurrent(windows[i]);
|
||||||
glClearColor((GLclampf) (i & 1),
|
glClearColor(colors[i].r, colors[i].g, colors[i].b, 1.f);
|
||||||
(GLclampf) (i >> 1),
|
|
||||||
i ? 0.f : 1.f,
|
|
||||||
0.f);
|
|
||||||
|
|
||||||
glfwGetWindowFrameSize(windows[i], &left, &top, &right, &bottom);
|
glfwGetWindowFrameSize(windows[i], &left, &top, &right, &bottom);
|
||||||
glfwSetWindowPos(windows[i],
|
glfwSetWindowPos(windows[i],
|
||||||
|
|||||||
Reference in New Issue
Block a user