diff --git a/docs/CODEOWNERS b/.github/CODEOWNERS similarity index 100% rename from docs/CODEOWNERS rename to .github/CODEOWNERS diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d87ae8d1..7f798851 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,8 +31,8 @@ jobs: - name: Build shared library run: cmake --build build-shared --parallel - build-linux-wayland-clang: - name: Wayland (Linux, Clang) + build-linux-full-clang: + name: X11+Wayland (Linux, Clang) runs-on: ubuntu-latest env: CC: clang @@ -42,38 +42,15 @@ jobs: - name: Install dependencies run: | sudo apt update - sudo apt install wayland-protocols libwayland-dev libxkbcommon-dev + sudo apt install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxext-dev wayland-protocols libwayland-dev libxkbcommon-dev - name: Configure static library - run: cmake -S . -B build-static -D GLFW_USE_WAYLAND=ON + run: cmake -S . -B build-static -D GLFW_BUILD_WAYLAND=ON - name: Build static library run: cmake --build build-static --parallel - name: Configure shared library - run: cmake -S . -B build-shared -D GLFW_USE_WAYLAND=ON -D BUILD_SHARED_LIBS=ON - - name: Build shared library - run: cmake --build build-shared --parallel - - build-linux-null-clang: - name: Null (Linux, Clang) - runs-on: ubuntu-latest - env: - CC: clang - CFLAGS: -Werror - steps: - - uses: actions/checkout@v2 - - name: Install dependencies - run: | - sudo apt update - sudo apt install libosmesa6-dev - - - name: Configure static library - run: cmake -S . -B build-static -D GLFW_USE_OSMESA=ON - - name: Build static library - run: cmake --build build-static --parallel - - - name: Configure shared library - run: cmake -S . -B build-shared -D GLFW_USE_OSMESA=ON -D BUILD_SHARED_LIBS=ON + run: cmake -S . -B build-shared -D GLFW_BUILD_WAYLAND=ON -D BUILD_SHARED_LIBS=ON - name: Build shared library run: cmake --build build-shared --parallel @@ -96,8 +73,8 @@ jobs: - name: Build shared library run: cmake --build build-shared --parallel - build-windows-win32-vs2019: - name: Win32 (Windows, VS2019) + build-windows-win32-vs2022: + name: Win32 (Windows, VS2022) runs-on: windows-latest env: CFLAGS: /WX @@ -105,12 +82,12 @@ jobs: - uses: actions/checkout@v2 - name: Configure static library - run: cmake -S . -B build-static -G "Visual Studio 16 2019" + run: cmake -S . -B build-static -G "Visual Studio 17 2022" - name: Build static library run: cmake --build build-static --parallel - name: Configure shared library - run: cmake -S . -B build-shared -G "Visual Studio 16 2019" -D BUILD_SHARED_LIBS=ON + run: cmake -S . -B build-shared -G "Visual Studio 17 2022" -D BUILD_SHARED_LIBS=ON - name: Build shared library run: cmake --build build-shared --parallel diff --git a/CMakeLists.txt b/CMakeLists.txt index e255863b..f5e538bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,17 +27,22 @@ option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" ${GLFW_STANDALONE}) option(GLFW_BUILD_TESTS "Build the GLFW test programs" ${GLFW_STANDALONE}) option(GLFW_BUILD_DOCS "Build the GLFW documentation" ON) option(GLFW_INSTALL "Generate installation target" ON) -option(GLFW_VULKAN_STATIC "Assume the Vulkan loader is linked with the application" OFF) include(GNUInstallDirs) include(CMakeDependentOption) -cmake_dependent_option(GLFW_USE_OSMESA "Use OSMesa for offscreen context creation" OFF - "UNIX" OFF) +if (GLFW_USE_OSMESA) + message(FATAL_ERROR "GLFW_USE_OSMESA has been removed; set the GLFW_PLATFORM init hint") +endif() + +cmake_dependent_option(GLFW_BUILD_WIN32 "Build support for Win32" ON "WIN32" OFF) +cmake_dependent_option(GLFW_BUILD_COCOA "Build support for Cocoa" ON "APPLE" OFF) +cmake_dependent_option(GLFW_BUILD_X11 "Build support for X11" ON "UNIX;NOT APPLE" OFF) +cmake_dependent_option(GLFW_BUILD_WAYLAND "Build support for Wayland" + "${GLFW_USE_WAYLAND}" "UNIX;NOT APPLE" OFF) + cmake_dependent_option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF "WIN32" OFF) -cmake_dependent_option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF - "UNIX;NOT APPLE" OFF) cmake_dependent_option(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC runtime library DLL" ON "MSVC" OFF) @@ -54,22 +59,6 @@ else() set(GLFW_BUILD_SHARED_LIBRARY ${BUILD_SHARED_LIBS}) endif() -if (UNIX AND GLFW_BUILD_SHARED_LIBRARY) - # On Unix-like systems, shared libraries can use the soname system. - set(GLFW_LIB_NAME glfw) -else() - set(GLFW_LIB_NAME glfw3) -endif() - -if (GLFW_VULKAN_STATIC) - if (GLFW_BUILD_SHARED_LIBRARY) - # If you absolutely must do this, remove this line and add the Vulkan - # loader static library via the CMAKE_SHARED_LINKER_FLAGS - message(FATAL_ERROR "You are trying to link the Vulkan loader static library into the GLFW shared library") - endif() - set(_GLFW_VULKAN_STATIC 1) -endif() - list(APPEND CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules") find_package(Threads REQUIRED) @@ -79,6 +68,22 @@ if (GLFW_BUILD_DOCS) find_package(Doxygen) endif() +#-------------------------------------------------------------------- +# Report backend selection +#-------------------------------------------------------------------- +if (GLFW_BUILD_WIN32) + message(STATUS "Including Win32 support") +endif() +if (GLFW_BUILD_COCOA) + message(STATUS "Including Cocoa support") +endif() +if (GLFW_BUILD_WAYLAND) + message(STATUS "Including Wayland support") +endif() +if (GLFW_BUILD_X11) + message(STATUS "Including X11 support") +endif() + #-------------------------------------------------------------------- # Apply Microsoft C runtime library option # This is here because it also applies to tests and examples @@ -104,169 +109,6 @@ if (MSVC AND NOT USE_MSVC_RUNTIME_LIBRARY_DLL) endif() endif() -#-------------------------------------------------------------------- -# Detect and select backend APIs -#-------------------------------------------------------------------- -if (GLFW_USE_WAYLAND) - set(_GLFW_WAYLAND 1) - message(STATUS "Using Wayland for window creation") -elseif (GLFW_USE_OSMESA) - set(_GLFW_OSMESA 1) - message(STATUS "Using OSMesa for headless context creation") -elseif (WIN32) - set(_GLFW_WIN32 1) - message(STATUS "Using Win32 for window creation") -elseif (APPLE) - set(_GLFW_COCOA 1) - message(STATUS "Using Cocoa for window creation") -elseif (UNIX) - set(_GLFW_X11 1) - message(STATUS "Using X11 for window creation") -else() - message(FATAL_ERROR "No supported platform was detected") -endif() - -#-------------------------------------------------------------------- -# Find and add Unix math and time libraries -#-------------------------------------------------------------------- -if (UNIX AND NOT APPLE) - find_library(RT_LIBRARY rt) - mark_as_advanced(RT_LIBRARY) - if (RT_LIBRARY) - list(APPEND glfw_LIBRARIES "${RT_LIBRARY}") - list(APPEND glfw_PKG_LIBS "-lrt") - endif() - - find_library(MATH_LIBRARY m) - mark_as_advanced(MATH_LIBRARY) - if (MATH_LIBRARY) - list(APPEND glfw_LIBRARIES "${MATH_LIBRARY}") - list(APPEND glfw_PKG_LIBS "-lm") - endif() - - if (CMAKE_DL_LIBS) - list(APPEND glfw_LIBRARIES "${CMAKE_DL_LIBS}") - list(APPEND glfw_PKG_LIBS "-l${CMAKE_DL_LIBS}") - endif() -endif() - -#-------------------------------------------------------------------- -# Use Win32 for window creation -#-------------------------------------------------------------------- -if (_GLFW_WIN32) - - list(APPEND glfw_PKG_LIBS "-lgdi32") - - if (GLFW_USE_HYBRID_HPG) - set(_GLFW_USE_HYBRID_HPG 1) - endif() -endif() - -#-------------------------------------------------------------------- -# Use X11 for window creation -#-------------------------------------------------------------------- -if (_GLFW_X11) - - find_package(X11 REQUIRED) - - # Set up library and include paths - list(APPEND glfw_INCLUDE_DIRS "${X11_X11_INCLUDE_PATH}") - - # Check for XRandR (modern resolution switching and gamma control) - if (NOT X11_Xrandr_INCLUDE_PATH) - message(FATAL_ERROR "RandR headers not found; install libxrandr development package") - endif() - - # Check for Xinerama (legacy multi-monitor support) - if (NOT X11_Xinerama_INCLUDE_PATH) - message(FATAL_ERROR "Xinerama headers not found; install libxinerama development package") - endif() - - # Check for Xkb (X keyboard extension) - if (NOT X11_Xkb_INCLUDE_PATH) - message(FATAL_ERROR "XKB headers not found; install X11 development package") - endif() - - # Check for Xcursor (cursor creation from RGBA images) - if (NOT X11_Xcursor_INCLUDE_PATH) - message(FATAL_ERROR "Xcursor headers not found; install libxcursor development package") - endif() - - # Check for XInput (modern HID input) - if (NOT X11_Xi_INCLUDE_PATH) - message(FATAL_ERROR "XInput headers not found; install libxi development package") - endif() - - # Check for X Shape (custom window input shape) - if (NOT X11_Xshape_INCLUDE_PATH) - message(FATAL_ERROR "X Shape headers not found; install libxext development package") - endif() -endif() - -#-------------------------------------------------------------------- -# Use Wayland for window creation -#-------------------------------------------------------------------- -if (_GLFW_WAYLAND) - - include(FindPkgConfig) - pkg_check_modules(Wayland REQUIRED - wayland-client>=0.2.7 - wayland-cursor>=0.2.7 - wayland-egl>=0.2.7 - xkbcommon) - - list(APPEND glfw_INCLUDE_DIRS "${Wayland_INCLUDE_DIRS}") - - include(CheckIncludeFiles) - include(CheckFunctionExists) - check_include_files(xkbcommon/xkbcommon-compose.h HAVE_XKBCOMMON_COMPOSE_H) - check_function_exists(memfd_create HAVE_MEMFD_CREATE) - - if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") - find_package(EpollShim) - if (EPOLLSHIM_FOUND) - list(APPEND glfw_INCLUDE_DIRS "${EPOLLSHIM_INCLUDE_DIRS}") - list(APPEND glfw_LIBRARIES "${EPOLLSHIM_LIBRARIES}") - endif() - endif() -endif() - -#-------------------------------------------------------------------- -# Use Cocoa for window creation and NSOpenGL for context creation -#-------------------------------------------------------------------- -if (_GLFW_COCOA) - - list(APPEND glfw_LIBRARIES - "-framework Cocoa" - "-framework IOKit" - "-framework CoreFoundation") - - set(glfw_PKG_DEPS "") - set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation") -endif() - -#-------------------------------------------------------------------- -# Add the Vulkan loader as a dependency if necessary -#-------------------------------------------------------------------- -if (GLFW_VULKAN_STATIC) - list(APPEND glfw_PKG_DEPS "vulkan") -endif() - -#-------------------------------------------------------------------- -# Export GLFW library dependencies -#-------------------------------------------------------------------- -foreach(arg ${glfw_PKG_DEPS}) - string(APPEND deps " ${arg}") -endforeach() -foreach(arg ${glfw_PKG_LIBS}) - string(APPEND libs " ${arg}") -endforeach() - -set(GLFW_PKG_CONFIG_REQUIRES_PRIVATE "${deps}" CACHE INTERNAL - "GLFW pkg-config Requires.private") -set(GLFW_PKG_CONFIG_LIBS_PRIVATE "${libs}" CACHE INTERNAL - "GLFW pkg-config Libs.private") - #-------------------------------------------------------------------- # Create generated files #-------------------------------------------------------------------- @@ -283,8 +125,6 @@ write_basic_package_version_file(src/glfw3ConfigVersion.cmake VERSION ${GLFW_VERSION} COMPATIBILITY SameMajorVersion) -configure_file(CMake/glfw3.pc.in src/glfw3.pc @ONLY) - #-------------------------------------------------------------------- # Add subdirectories #-------------------------------------------------------------------- diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md new file mode 100644 index 00000000..110ed4cd --- /dev/null +++ b/CONTRIBUTORS.md @@ -0,0 +1,265 @@ +# Acknowledgements + +GLFW exists because people around the world donated their time and lent their +skills. This list only includes contributions to the main repository and +excludes other invaluable contributions like language bindings and text and +video tutorials. + + - Bobyshev Alexander + - Laurent Aphecetche + - Matt Arsenault + - ashishgamedev + - David Avedissian + - Luca Bacci + - Keith Bauer + - John Bartholomew + - Coşku Baş + - Niklas Behrens + - Andrew Belt + - Nevyn Bengtsson + - Niklas Bergström + - Denis Bernard + - BiBi + - Doug Binks + - blanco + - Waris Boonyasiriwat + - Kyle Brenneman + - Rok Breulj + - TheBrokenRail + - Kai Burjack + - Martin Capitanio + - Nicolas Caramelli + - David Carlier + - Arturo Castro + - Chi-kwan Chan + - TheChocolateOre + - Ali Chraghi + - Joseph Chua + - Ian Clarkson + - Michał Cichoń + - Lambert Clara + - Anna Clarke + - Josh Codd + - Yaron Cohen-Tal + - Omar Cornut + - Andrew Corrigan + - Bailey Cosier + - Noel Cower + - CuriouserThing + - Jason Daly + - danhambleton + - Jarrod Davis + - Olivier Delannoy + - Paul R. Deppe + - Michael Dickens + - Роман Донченко + - Mario Dorn + - Wolfgang Draxinger + - Jonathan Dummer + - Ralph Eastwood + - Fredrik Ehnbom + - Robin Eklind + - Jan Ekström + - Siavash Eliasi + - Ahmad Fatoum + - Nikita Fediuchin + - Felipe Ferreira + - Michael Fogleman + - Jason Francis + - Gerald Franz + - Mário Freitas + - GeO4d + - Marcus Geelnard + - ghuser404 + - Charles Giessen + - Ryan C. Gordon + - Stephen Gowen + - Kovid Goyal + - Kevin Grandemange + - Eloi Marín Gratacós + - Stefan Gustavson + - Andrew Gutekanst + - Stephen Gutekanst + - Jonathan Hale + - hdf89shfdfs + - Sylvain Hellegouarch + - Björn Hempel + - Matthew Henry + - heromyth + - Lucas Hinderberger + - Paul Holden + - Hajime Hoshi + - Warren Hu + - Charles Huber + - Brent Huisman + - illustris + - InKryption + - IntellectualKitty + - Aaron Jacobs + - JannikGM + - Erik S. V. Jansson + - jjYBdx4IL + - Toni Jovanoski + - Arseny Kapoulkine + - Cem Karan + - Osman Keskin + - Koray Kilinc + - Josh Kilmer + - Byunghoon Kim + - Cameron King + - Peter Knut + - Christoph Kubisch + - Yuri Kunde Schlesner + - Rokas Kupstys + - Konstantin Käfer + - Eric Larson + - Francis Lecavalier + - Jong Won Lee + - Robin Leffmann + - Glenn Lewis + - Shane Liesegang + - Anders Lindqvist + - Leon Linhart + - Marco Lizza + - Eyal Lotem + - Aaron Loucks + - Luflosi + - lukect + - Tristam MacDonald + - Hans Mackowiak + - Ramiro Magno + - Дмитри Малышев + - Zbigniew Mandziejewicz + - Adam Marcus + - Célestin Marot + - Kyle McDonald + - David V. McKay + - David Medlock + - Bryce Mehring + - Jonathan Mercier + - Marcel Metz + - Liam Middlebrook + - Ave Milia + - Jonathan Miller + - Kenneth Miller + - Bruce Mitchener + - Jack Moffitt + - Ravi Mohan + - Jeff Molofee + - Alexander Monakov + - Pierre Morel + - Jon Morton + - Pierre Moulon + - Martins Mozeiko + - Pascal Muetschard + - James Murphy + - Julian Møller + - ndogxj + - F. Nedelec + - n3rdopolis + - Kristian Nielsen + - Joel Niemelä + - Kamil Nowakowski + - onox + - Denis Ovod + - Ozzy + - Andri Pálsson + - luz paz + - Peoro + - Braden Pellett + - Christopher Pelloux + - Michael Pennington + - Arturo J. Pérez + - Vladimir Perminov + - Olivier Perret + - Anthony Pesch + - Orson Peters + - Emmanuel Gil Peyrot + - Cyril Pichard + - Pilzschaf + - Keith Pitt + - Stanislav Podgorskiy + - Konstantin Podsvirov + - Nathan Poirier + - Alexandre Pretyman + - Pablo Prietz + - przemekmirek + - pthom + - Martin Pulec + - Guillaume Racicot + - Christian Rauch + - Philip Rideout + - Eddie Ringle + - Max Risuhin + - Joe Roback + - Jorge Rodriguez + - Jari Ronkainen + - Luca Rood + - Ed Ropple + - Aleksey Rybalkin + - Mikko Rytkönen + - Riku Salminen + - Brandon Schaefer + - Sebastian Schuberth + - Christian Sdunek + - Matt Sealey + - Steve Sexton + - Arkady Shapkin + - Ali Sherief + - Yoshiki Shibukawa + - Dmitri Shuralyov + - Joao da Silva + - Daniel Sieger + - Daniel Skorupski + - Slemmie + - Anthony Smith + - Bradley Smith + - Cliff Smolinsky + - Patrick Snape + - Erlend Sogge Heggen + - Olivier Sohn + - Julian Squires + - Johannes Stein + - Pontus Stenetorp + - Michael Stocker + - Justin Stoecker + - Elviss Strazdins + - Paul Sultana + - Nathan Sweet + - TTK-Bandit + - Jared Tiala + - Sergey Tikhomirov + - Arthur Tombs + - TronicLabs + - Ioannis Tsakpinis + - Samuli Tuomola + - Matthew Turner + - urraka + - Elias Vanderstuyft + - Stef Velzel + - Jari Vetoniemi + - Ricardo Vieira + - Nicholas Vitovitch + - Simon Voordouw + - Corentin Wallez + - Torsten Walluhn + - Patrick Walton + - Xo Wang + - Andre Weissflog + - Jay Weisskopf + - Frank Wille + - Andy Williams + - Joel Winarske + - Richard A. Wilkes + - Tatsuya Yatagawa + - Ryogo Yoshimura + - Lukas Zanner + - Andrey Zholos + - Aihui Zhu + - Santi Zupancic + - Jonas Ådahl + - Lasse Öörni + - Leonard König + - All the unmentioned and anonymous contributors in the GLFW community, for bug + reports, patches, feedback, testing and encouragement + diff --git a/README.md b/README.md index 0e075ee3..8b4a1546 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,11 @@ you have used GLFW 2 in the past, there is a [transition guide](https://www.glfw.org/docs/latest/moving.html) for moving to the GLFW 3 API. +GLFW exists because of the contributions of [many people](CONTRIBUTORS.md) +around the world, whether by reporting bugs, providing community support, adding +features, reviewing or testing code, debugging, proofreading docs, suggesting +features or fixing bugs. + ## Compiling GLFW @@ -116,9 +121,17 @@ information on what to include when reporting a bug. ## Changelog + - Added `GLFW_PLATFORM` init hint for runtime platform selection (#1958) + - Added `GLFW_ANY_PLATFORM`, `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, + `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` and `GLFW_PLATFORM_NULL` symbols to + specify the desired platform (#1958) + - Added `glfwGetPlatform` function to query what platform was selected (#1655,#1958) + - Added `glfwPlatformSupported` function to query if a platform is supported + (#1655,#1958) - Added `glfwInitAllocator` for setting a custom memory allocator (#544,#1628,#1947) - Added `GLFWallocator` struct and `GLFWallocatefun`, `GLFWreallocatefun` and `GLFWdeallocatefun` types (#544,#1628,#1947) + - Added `glfwInitVulkanLoader` for using a non-default Vulkan loader (#1374,#1890) - Added `GLFW_RESIZE_NWSE_CURSOR`, `GLFW_RESIZE_NESW_CURSOR`, `GLFW_RESIZE_ALL_CURSOR` and `GLFW_NOT_ALLOWED_CURSOR` cursor shapes (#427) - Added `GLFW_RESIZE_EW_CURSOR` alias for `GLFW_HRESIZE_CURSOR` (#427) @@ -126,12 +139,24 @@ information on what to include when reporting a bug. - Added `GLFW_POINTING_HAND_CURSOR` alias for `GLFW_HAND_CURSOR` (#427) - Added `GLFW_MOUSE_PASSTHROUGH` window hint for letting mouse input pass through the window (#1236,#1568) + - Added `GLFW_CURSOR_CAPTURED` cursor mode to confine the cursor to the window + content area (#58) + - Added `GLFW_POSITION_X` and `GLFW_POSITION_Y` window hints for initial position + (#1603,#1747) + - Added `GLFW_ANY_POSITION` hint value for letting the window manager choose (#1603,#1747) + - Added `GLFW_PLATFORM_UNAVAILABLE` error for platform detection failures (#1958) - Added `GLFW_FEATURE_UNAVAILABLE` error for platform limitations (#1692) - Added `GLFW_FEATURE_UNIMPLEMENTED` error for incomplete backends (#1692) + - Added `GLFW_WAYLAND_APP_ID` window hint string for Wayland app\_id selection + (#2121,#2122) - Added `GLFW_ANGLE_PLATFORM_TYPE` init hint and `GLFW_ANGLE_PLATFORM_TYPE_*` values to select ANGLE backend (#1380) - Added `GLFW_X11_XCB_VULKAN_SURFACE` init hint for selecting X11 Vulkan surface extension (#1793) + - Added `GLFW_NATIVE_INCLUDE_NONE` for disabling inclusion of native headers (#1348) + - Added `GLFW_BUILD_WIN32` CMake option for enabling Win32 support (#1958) + - Added `GLFW_BUILD_COCOA` CMake option for enabling Cocoa support (#1958) + - Added `GLFW_BUILD_X11` CMake option for enabling X11 support (#1958) - Added `GLFW_LIBRARY_TYPE` CMake variable for overriding the library type (#279,#1307,#1497,#1574,#1928) - Added `GLFW_PKG_CONFIG_REQUIRES_PRIVATE` and `GLFW_PKG_CONFIG_LIBS_PRIVATE` CMake @@ -139,7 +164,11 @@ information on what to include when reporting a bug. - Made joystick subsystem initialize at first use (#1284,#1646) - Made `GLFW_DOUBLEBUFFER` a read-only window attribute - Updated the minimum required CMake version to 3.1 + - Updated gamepad mappings from upstream - Disabled tests and examples by default when built as a CMake subdirectory + - Renamed `GLFW_USE_WAYLAND` CMake option to `GLFW_BUILD_WAYLAND` (#1958) + - Removed `GLFW_USE_OSMESA` CMake option enabling the Null platform (#1958) + - Removed CMake generated configuration header - Bugfix: The CMake config-file package used an absolute path and was not relocatable (#1470) - Bugfix: Video modes with a duplicate screen area were discarded (#1555,#1556) @@ -150,9 +179,14 @@ information on what to include when reporting a bug. - Bugfix: Buffers were swapped at creation on single-buffered windows (#1873) - Bugfix: Gamepad mapping updates could spam `GLFW_INVALID_VALUE` due to incompatible controllers sharing hardware ID (#1763) + - Bugfix: Native access functions for context handles did not check that the API matched + - Bugfix: `glfwMakeContextCurrent` would access TLS slot before initialization + - Bugfix: `glfwSetGammaRamp` could emit `GLFW_INVALID_VALUE` before initialization + - Bugfix: `glfwGetJoystickUserPointer` returned `NULL` during disconnection (#2092) - [Win32] Added the `GLFW_WIN32_KEYBOARD_MENU` window hint for enabling access to the window menu - [Win32] Added a version info resource to the GLFW DLL + - [Win32] Made hidden helper window use its own window class - [Win32] Disabled framebuffer transparency on Windows 7 when DWM windows are opaque (#1512) - [Win32] Bugfix: `GLFW_INCLUDE_VULKAN` plus `VK_USE_PLATFORM_WIN32_KHR` caused @@ -180,12 +214,28 @@ information on what to include when reporting a bug. later (#1783,#1796) - [Win32] Bugfix: Compilation with LLVM for Windows failed (#1807,#1824,#1874) - [Win32] Bugfix: The foreground lock timeout was overridden, ignoring the user + - [Win32] Bugfix: Content scale queries could fail silently (#1615) + - [Win32] Bugfix: Content scales could have garbage values if monitor was recently + disconnected (#1615) + - [Win32] Bugfix: A window created maximized and undecorated would cover the whole + monitor (#1806) + - [Win32] Bugfix: The default restored window position was lost when creating a maximized + window + - [Win32] Bugfix: `glfwMaximizeWindow` would make a hidden window visible + - [Win32] Bugfix: `Alt+PrtSc` would emit `GLFW_KEY_UNKNOWN` and a different + scancode than `PrtSc` (#1993) + - [Win32] Bugfix: `GLFW_KEY_PAUSE` scancode from `glfwGetKeyScancode` did not + match event scancode (#1993) + - [Win32] Bugfix: Instance-local operations used executable instance (#469,#1296,#1395) + - [Win32] Bugfix: The OSMesa library was not unloaded on termination + - [Win32] Bugfix: Right shift emitted `GLFW_KEY_UNKNOWN` when using a CJK IME (#2050) - [Cocoa] Added support for `VK_EXT_metal_surface` (#1619) - [Cocoa] Added locating the Vulkan loader at runtime in an application bundle - [Cocoa] Moved main menu creation to GLFW initialization time (#1649) - [Cocoa] Changed `EGLNativeWindowType` from `NSView` to `CALayer` (#1169) - [Cocoa] Changed F13 key to report Print Screen for cross-platform consistency (#1786) + - [Cocoa] Disabled macOS fullscreen when `GLFW_RESIZABLE` is false - [Cocoa] Removed dependency on the CoreVideo framework - [Cocoa] Bugfix: `glfwSetWindowSize` used a bottom-left anchor point (#1553) - [Cocoa] Bugfix: Window remained on screen after destruction until event poll @@ -200,7 +250,7 @@ information on what to include when reporting a bug. could leak memory - [Cocoa] Bugfix: Objective-C files were compiled as C with CMake 3.19 (#1787) - [Cocoa] Bugfix: Duplicate video modes were not filtered out (#1830) - - [Cocoa] Bugfix: Menubar was not clickable on macOS 10.15+ until it lost and + - [Cocoa] Bugfix: Menu bar was not clickable on macOS 10.15+ until it lost and regained focus (#1648,#1802) - [Cocoa] Bugfix: Monitor name query could segfault on macOS 11 (#1809,#1833) - [Cocoa] Bugfix: The install name of the installed dylib was relative (#1504) @@ -208,6 +258,17 @@ information on what to include when reporting a bug. related events were emitted - [Cocoa] Bugfix: Moving the cursor programmatically would freeze it for a fraction of a second (#1962) + - [Cocoa] Bugfix: `kIOMasterPortDefault` was deprecated in macOS 12.0 (#1980) + - [Cocoa] Bugfix: `kUTTypeURL` was deprecated in macOS 12.0 (#2003) + - [Cocoa] Bugfix: A connected Apple AirPlay would emit a useless error (#1791) + - [Cocoa] Bugfix: The EGL and OSMesa libraries were not unloaded on termination + - [Cocoa] Bugfix: `GLFW_MAXIMIZED` was always true when `GLFW_RESIZABLE` was false + - [Cocoa] Bugfix: Changing `GLFW_DECORATED` in macOS fullscreen would abort + application (#1886) + - [Cocoa] Bugfix: Setting a monitor from macOS fullscreen would abort + application (#2110) + - [Cocoa] Bugfix: The Vulkan loader was not loaded from the `Frameworks` bundle + subdirectory (#2113,#2120) - [X11] Bugfix: The CMake files did not check for the XInput headers (#1480) - [X11] Bugfix: Key names were not updated when the keyboard layout changed (#1462,#1528) @@ -230,13 +291,32 @@ information on what to include when reporting a bug. - [X11] Bugfix: XKB path used keysyms instead of physical locations for non-printable keys (#1598) - [X11] Bugfix: Function keys were mapped to `GLFW_KEY_UNKNOWN` for some layout - combinaitons (#1598) + combinations (#1598) - [X11] Bugfix: Keys pressed simultaneously with others were not always reported (#1112,#1415,#1472,#1616) - [X11] Bugfix: Some window attributes were not applied on leaving fullscreen (#1863) - [X11] Bugfix: Changing `GLFW_FLOATING` could leak memory + - [X11] Bugfix: Icon pixel format conversion worked only by accident, relying on + undefined behavior (#1986) + - [X11] Bugfix: Dynamic loading on OpenBSD failed due to soname differences + - [X11] Bugfix: Waiting for events would fail if file descriptor was too large + (#2024) + - [X11] Bugfix: Joystick events could lead to busy-waiting (#1872) + - [X11] Bugfix: `glfwWaitEvents*` did not continue for joystick events + - [X11] Bugfix: `glfwPostEmptyEvent` could be ignored due to race condition + (#379,#1281,#1285,#2033) + - [X11] Bugfix: Dynamic loading on NetBSD failed due to soname differences + - [X11] Bugfix: Left shift of int constant relied on undefined behavior (#1951) + - [X11] Bugfix: The OSMesa libray was not unloaded on termination + - [X11] Bugfix: A malformed response during selection transfer could cause a segfault + - [X11] Bugfix: Some calls would reset Xlib to the default error handler (#2108) - [Wayland] Added dynamic loading of all Wayland libraries + - [Wayland] Added support for key names via xkbcommon + - [Wayland] Added support for file path drop events (#2040) + - [Wayland] Added support for more human-readable monitor names where available + - [Wayland] Disabled alpha channel for opaque windows on systems lacking + `EGL_EXT_present_opaque` (#1895) - [Wayland] Removed support for `wl_shell` (#1443) - [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432) - [Wayland] Bugfix: `CLOCK_MONOTONIC` was not correctly enabled @@ -244,13 +324,68 @@ information on what to include when reporting a bug. - [Wayland] Bugfix: Retrieving partial framebuffer size would segfault - [Wayland] Bugfix: Scrolling offsets were inverted compared to other platforms (#1463) - - [Wayland] Bugfix: Client-Side Decorations were destroyed in the wrong worder + - [Wayland] Bugfix: Client-Side Decorations were destroyed in the wrong order (#1798) - [Wayland] Bugfix: Monitors physical size could report zero (#1784,#1792) - [Wayland] Bugfix: Some keys were not repeating in Wayland (#1908) - [Wayland] Bugfix: Non-arrow cursors are offset from the hotspot (#1706,#1899) + - [Wayland] Bugfix: The `O_CLOEXEC` flag was not defined on FreeBSD + - [Wayland] Bugfix: Key repeat could lead to a race condition (#1710) + - [Wayland] Bugfix: Activating a window would emit two input focus events + - [Wayland] Bugfix: Disable key repeat mechanism when window loses input focus + - [Wayland] Bugfix: Window hiding and showing did not work (#1492,#1731) + - [Wayland] Bugfix: A key being repeated was not released when window lost focus + - [Wayland] Bugfix: Showing a hidden window did not emit a window refresh event + - [Wayland] Bugfix: Full screen window creation did not ignore `GLFW_VISIBLE` + - [Wayland] Bugfix: Some keys were reported as wrong key or `GLFW_KEY_UNKNOWN` + - [Wayland] Bugfix: Text input did not repeat along with key repeat + - [Wayland] Bugfix: `glfwPostEmptyEvent` sometimes had no effect (#1520,#1521) + - [Wayland] Bugfix: `glfwSetClipboardString` would fail if set to result of + `glfwGetClipboardString` + - [Wayland] Bugfix: Data source creation error would cause double free at termination + - [Wayland] Bugfix: Partial writes of clipboard string would cause beginning to repeat + - [Wayland] Bugfix: Some errors would cause clipboard string transfer to hang + - [Wayland] Bugfix: Drag and drop data was misinterpreted as clipboard string + - [Wayland] Bugfix: MIME type matching was not performed for clipboard string + - [Wayland] Bugfix: The OSMesa library was not unloaded on termination + - [Wayland] Bugfix: `glfwCreateWindow` could emit `GLFW_FEATURE_UNAVAILABLE` + - [Wayland] Bugfix: Lock key modifier bits were only set when lock keys were pressed + - [Wayland] Bugfix: A window leaving full screen mode would be iconified (#1995) + - [Wayland] Bugfix: A window leaving full screen mode ignored its desired size + - [Wayland] Bugfix: `glfwSetWindowMonitor` did not update windowed mode size + - [Wayland] Bugfix: `glfwRestoreWindow` would make a full screen window windowed + - [Wayland] Bugfix: A window maximized or restored by the user would enter an + inconsistent state + - [Wayland] Bugfix: Window maximization events were not emitted + - [Wayland] Bugfix: `glfwRestoreWindow` assumed it was always in windowed mode + - [Wayland] Bugfix: `glfwSetWindowSize` would resize a full screen window + - [Wayland] Bugfix: A window content scale event would be emitted every time + the window resized + - [Wayland] Bugfix: If `glfwInit` failed it would close stdin + - [Wayland] Bugfix: Manual resizing with fallback decorations behaved erratically + (#1991,#2115,#2127) + - [Wayland] Bugfix: Size limits included frame size for fallback decorations + - [Wayland] Bugfix: Updating `GLFW_DECORATED` had no effect on server-side + decorations + - [Wayland] Bugfix: A monitor would be reported as connected again if its scale + changed + - [Wayland] Bugfix: `glfwTerminate` would segfault if any monitor had changed + scale + - [Wayland] Bugfix: Window content scale events were not emitted when monitor + scale changed + - [Wayland] Bugfix: `glfwSetWindowAspectRatio` reported an error instead of + applying the specified ratio + - [Wayland] Bugfix: `GLFW_MAXIMIZED` window hint had no effect + - [Wayland] Bugfix: `glfwRestoreWindow` had no effect before first show + - [Wayland] Bugfix: Hiding and then showing a window caused program abort on + wlroots compositors (#1268) + - [Wayland] Bugfix: `GLFW_DECORATED` was ignored when showing a window with XDG + decorations + - [Wayland] Bugfix: Connecting a mouse after `glfwInit` would segfault (#1450) - [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled + - [Linux] Bugfix: Joysticks without buttons were ignored (#2042,#2043) + - [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072) - [NSGL] Removed enforcement of forward-compatible flag for core contexts - [NSGL] Bugfix: `GLFW_COCOA_RETINA_FRAMEBUFFER` had no effect on newer macOS versions (#1442) @@ -261,7 +396,10 @@ information on what to include when reporting a bug. (#442) - [EGL] Added ANGLE backend selection via `EGL_ANGLE_platform_angle` extension (#1380) + [EGL] Added loading of glvnd `libOpenGL.so.0` where available for OpenGL - [EGL] Bugfix: The `GLFW_DOUBLEBUFFER` context attribute was ignored (#1843) + - [GLX] Added loading of glvnd `libGLX.so.0` where available + - [GLX] Bugfix: Context creation failed if GLX 1.4 was not exported by GLX library ## Contact @@ -280,226 +418,3 @@ request, please file it in the Finally, if you're interested in helping out with the development of GLFW or porting it to your favorite platform, join us on the forum, GitHub or IRC. - -## Acknowledgements - -GLFW exists because people around the world donated their time and lent their -skills. - - - Bobyshev Alexander - - Laurent Aphecetche - - Matt Arsenault - - ashishgamedev - - David Avedissian - - Keith Bauer - - John Bartholomew - - Coşku Baş - - Niklas Behrens - - Andrew Belt - - Nevyn Bengtsson - - Niklas Bergström - - Denis Bernard - - Doug Binks - - blanco - - Waris Boonyasiriwat - - Kyle Brenneman - - Rok Breulj - - Kai Burjack - - Martin Capitanio - - Nicolas Caramelli - - David Carlier - - Arturo Castro - - Chi-kwan Chan - - Joseph Chua - - Ian Clarkson - - Michał Cichoń - - Lambert Clara - - Anna Clarke - - Yaron Cohen-Tal - - Omar Cornut - - Andrew Corrigan - - Bailey Cosier - - Noel Cower - - CuriouserThing - - Jason Daly - - Jarrod Davis - - Olivier Delannoy - - Paul R. Deppe - - Michael Dickens - - Роман Донченко - - Mario Dorn - - Wolfgang Draxinger - - Jonathan Dummer - - Ralph Eastwood - - Fredrik Ehnbom - - Robin Eklind - - Siavash Eliasi - - Ahmad Fatoum - - Felipe Ferreira - - Michael Fogleman - - Gerald Franz - - Mário Freitas - - GeO4d - - Marcus Geelnard - - Charles Giessen - - Ryan C. Gordon - - Stephen Gowen - - Kovid Goyal - - Eloi Marín Gratacós - - Stefan Gustavson - - Jonathan Hale - - hdf89shfdfs - - Sylvain Hellegouarch - - Matthew Henry - - heromyth - - Lucas Hinderberger - - Paul Holden - - Warren Hu - - Charles Huber - - IntellectualKitty - - Aaron Jacobs - - Erik S. V. Jansson - - Toni Jovanoski - - Arseny Kapoulkine - - Cem Karan - - Osman Keskin - - Koray Kilinc - - Josh Kilmer - - Byunghoon Kim - - Cameron King - - Peter Knut - - Christoph Kubisch - - Yuri Kunde Schlesner - - Rokas Kupstys - - Konstantin Käfer - - Eric Larson - - Francis Lecavalier - - Jong Won Lee - - Robin Leffmann - - Glenn Lewis - - Shane Liesegang - - Anders Lindqvist - - Leon Linhart - - Marco Lizza - - Eyal Lotem - - Aaron Loucks - - Luflosi - - lukect - - Tristam MacDonald - - Hans Mackowiak - - Дмитри Малышев - - Zbigniew Mandziejewicz - - Adam Marcus - - Célestin Marot - - Kyle McDonald - - David V. McKay - - David Medlock - - Bryce Mehring - - Jonathan Mercier - - Marcel Metz - - Liam Middlebrook - - Ave Milia - - Jonathan Miller - - Kenneth Miller - - Bruce Mitchener - - Jack Moffitt - - Jeff Molofee - - Alexander Monakov - - Pierre Morel - - Jon Morton - - Pierre Moulon - - Martins Mozeiko - - Julian Møller - - ndogxj - - n3rdopolis - - Kristian Nielsen - - Kamil Nowakowski - - onox - - Denis Ovod - - Ozzy - - Andri Pálsson - - Peoro - - Braden Pellett - - Christopher Pelloux - - Arturo J. Pérez - - Vladimir Perminov - - Anthony Pesch - - Orson Peters - - Emmanuel Gil Peyrot - - Cyril Pichard - - Keith Pitt - - Stanislav Podgorskiy - - Konstantin Podsvirov - - Nathan Poirier - - Alexandre Pretyman - - Pablo Prietz - - przemekmirek - - pthom - - Guillaume Racicot - - Philip Rideout - - Eddie Ringle - - Max Risuhin - - Jorge Rodriguez - - Luca Rood - - Ed Ropple - - Aleksey Rybalkin - - Mikko Rytkönen - - Riku Salminen - - Brandon Schaefer - - Sebastian Schuberth - - Christian Sdunek - - Matt Sealey - - Steve Sexton - - Arkady Shapkin - - Ali Sherief - - Yoshiki Shibukawa - - Dmitri Shuralyov - - Daniel Skorupski - - Anthony Smith - - Bradley Smith - - Cliff Smolinsky - - Patrick Snape - - Erlend Sogge Heggen - - Julian Squires - - Johannes Stein - - Pontus Stenetorp - - Michael Stocker - - Justin Stoecker - - Elviss Strazdins - - Paul Sultana - - Nathan Sweet - - TTK-Bandit - - Jared Tiala - - Sergey Tikhomirov - - Arthur Tombs - - Ioannis Tsakpinis - - Samuli Tuomola - - Matthew Turner - - urraka - - Elias Vanderstuyft - - Stef Velzel - - Jari Vetoniemi - - Ricardo Vieira - - Nicholas Vitovitch - - Simon Voordouw - - Corentin Wallez - - Torsten Walluhn - - Patrick Walton - - Xo Wang - - Jay Weisskopf - - Frank Wille - - Andy Williams - - Joel Winarske - - Richard A. Wilkes - - Tatsuya Yatagawa - - Ryogo Yoshimura - - Lukas Zanner - - Andrey Zholos - - Aihui Zhu - - Santi Zupancic - - Jonas Ådahl - - Lasse Öörni - - Leonard König - - All the unmentioned and anonymous contributors in the GLFW community, for bug - reports, patches, feedback, testing and encouragement - diff --git a/deps/glad/vulkan.h b/deps/glad/vulkan.h index 9e78dad9..469ffe5e 100644 --- a/deps/glad/vulkan.h +++ b/deps/glad/vulkan.h @@ -1,12 +1,12 @@ /** - * Loader generated by glad 2.0.0-beta on Wed Aug 25 21:20:29 2021 + * Loader generated by glad 2.0.0-beta on Thu Jul 7 20:52:04 2022 * * Generator: C/C++ * Specification: vk - * Extensions: 3 + * Extensions: 4 * * APIs: - * - vulkan=1.1 + * - vulkan=1.3 * * Options: * - ALIAS = False @@ -18,10 +18,10 @@ * - ON_DEMAND = False * * Commandline: - * --api='vulkan=1.1' --extensions='VK_EXT_debug_report,VK_KHR_surface,VK_KHR_swapchain' c --header-only + * --api='vulkan=1.3' --extensions='VK_EXT_debug_report,VK_KHR_portability_enumeration,VK_KHR_surface,VK_KHR_swapchain' c --header-only * * Online: - * http://glad.sh/#api=vulkan%3D1.1&extensions=VK_EXT_debug_report%2CVK_KHR_surface%2CVK_KHR_swapchain&generator=c&options=HEADER_ONLY + * http://glad.sh/#api=vulkan%3D1.3&extensions=VK_EXT_debug_report%2CVK_KHR_portability_enumeration%2CVK_KHR_surface%2CVK_KHR_swapchain&generator=c&options=HEADER_ONLY * */ @@ -162,21 +162,25 @@ typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apipro #define VK_ATTACHMENT_UNUSED (~0U) #define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report" -#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 9 +#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 10 #define VK_FALSE 0 +#define VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME "VK_KHR_portability_enumeration" +#define VK_KHR_PORTABILITY_ENUMERATION_SPEC_VERSION 1 #define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface" #define VK_KHR_SURFACE_SPEC_VERSION 25 #define VK_KHR_SWAPCHAIN_EXTENSION_NAME "VK_KHR_swapchain" #define VK_KHR_SWAPCHAIN_SPEC_VERSION 70 -#define VK_LOD_CLAMP_NONE 1000.0f +#define VK_LOD_CLAMP_NONE 1000.0F #define VK_LUID_SIZE 8 #define VK_MAX_DESCRIPTION_SIZE 256 #define VK_MAX_DEVICE_GROUP_SIZE 32 +#define VK_MAX_DRIVER_INFO_SIZE 256 +#define VK_MAX_DRIVER_NAME_SIZE 256 #define VK_MAX_EXTENSION_NAME_SIZE 256 #define VK_MAX_MEMORY_HEAPS 16 #define VK_MAX_MEMORY_TYPES 32 #define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256 -#define VK_QUEUE_FAMILY_EXTERNAL (~0U-1) +#define VK_QUEUE_FAMILY_EXTERNAL (~1U) #define VK_QUEUE_FAMILY_IGNORED (~0U) #define VK_REMAINING_ARRAY_LAYERS (~0U) #define VK_REMAINING_MIP_LEVELS (~0U) @@ -190,7 +194,7 @@ typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apipro /* File: vk_platform.h */ /* */ /* -** Copyright (c) 2014-2020 The Khronos Group Inc. +** Copyright 2014-2022 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 */ @@ -230,7 +234,7 @@ extern "C" #define VKAPI_CALL __stdcall #define VKAPI_PTR VKAPI_CALL #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7 - #error "Vulkan isn't supported for the 'armeabi' NDK ABI" + #error "Vulkan is not supported for the 'armeabi' NDK ABI" #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE) /* On Android 32-bit ARM targets, Vulkan functions use the "hardfloat" */ /* calling convention, i.e. float parameters are passed in registers. This */ @@ -246,7 +250,9 @@ extern "C" #define VKAPI_PTR #endif -#include +#if !defined(VK_NO_STDDEF_H) + #include +#endif /* !defined(VK_NO_STDDEF_H) */ #if !defined(VK_NO_STDINT_H) #if defined(_MSC_VER) && (_MSC_VER < 1600) @@ -268,43 +274,64 @@ extern "C" #endif /* __cplusplus */ #endif - +/* DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead. */ #define VK_MAKE_VERSION(major, minor, patch) \ ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) - +/* DEPRECATED: This define is deprecated. VK_API_VERSION_MAJOR should be used instead. */ #define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22) - -#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff) - -#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff) - +/* DEPRECATED: This define is deprecated. VK_API_VERSION_MINOR should be used instead. */ +#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU) +/* DEPRECATED: This define is deprecated. VK_API_VERSION_PATCH should be used instead. */ +#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) +#define VK_MAKE_API_VERSION(variant, major, minor, patch) \ + ((((uint32_t)(variant)) << 29) | (((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) +#define VK_API_VERSION_VARIANT(version) ((uint32_t)(version) >> 29) +#define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22) & 0x7FU) +#define VK_API_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU) +#define VK_API_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) /* DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead. */ /*#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 0) // Patch version should always be set to 0 */ - /* Vulkan 1.0 version number */ -#define VK_API_VERSION_1_0 VK_MAKE_VERSION(1, 0, 0)/* Patch version should always be set to 0 */ - +#define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)/* Patch version should always be set to 0 */ /* Vulkan 1.1 version number */ -#define VK_API_VERSION_1_1 VK_MAKE_VERSION(1, 1, 0)/* Patch version should always be set to 0 */ - +#define VK_API_VERSION_1_1 VK_MAKE_API_VERSION(0, 1, 1, 0)/* Patch version should always be set to 0 */ +/* Vulkan 1.2 version number */ +#define VK_API_VERSION_1_2 VK_MAKE_API_VERSION(0, 1, 2, 0)/* Patch version should always be set to 0 */ +/* Vulkan 1.3 version number */ +#define VK_API_VERSION_1_3 VK_MAKE_API_VERSION(0, 1, 3, 0)/* Patch version should always be set to 0 */ /* Version of this file */ -#define VK_HEADER_VERSION 152 - +#define VK_HEADER_VERSION 220 /* Complete version of this file */ -#define VK_HEADER_VERSION_COMPLETE VK_MAKE_VERSION(1, 2, VK_HEADER_VERSION) - +#define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 3, VK_HEADER_VERSION) #define VK_DEFINE_HANDLE(object) typedef struct object##_T* object; - -#if !defined(VK_DEFINE_NON_DISPATCHABLE_HANDLE) -#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) +#ifndef VK_USE_64_BIT_PTR_DEFINES + #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) + #define VK_USE_64_BIT_PTR_DEFINES 1 + #else + #define VK_USE_64_BIT_PTR_DEFINES 0 + #endif +#endif +#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE + #if (VK_USE_64_BIT_PTR_DEFINES==1) + #if (defined(__cplusplus) && (__cplusplus >= 201103L)) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L)) + #define VK_NULL_HANDLE nullptr + #else + #define VK_NULL_HANDLE ((void*)0) + #endif + #else + #define VK_NULL_HANDLE 0ULL + #endif +#endif +#ifndef VK_NULL_HANDLE + #define VK_NULL_HANDLE 0 +#endif +#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE + #if (VK_USE_64_BIT_PTR_DEFINES==1) #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object; -#else + #else #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object; + #endif #endif -#endif - -#define VK_NULL_HANDLE 0 - @@ -314,76 +341,48 @@ extern "C" VK_DEFINE_HANDLE(VkInstance) - VK_DEFINE_HANDLE(VkPhysicalDevice) - VK_DEFINE_HANDLE(VkDevice) - VK_DEFINE_HANDLE(VkQueue) - VK_DEFINE_HANDLE(VkCommandBuffer) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeviceMemory) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBuffer) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferView) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImage) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImageView) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderModule) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipeline) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineLayout) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSampler) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSetLayout) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFence) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkEvent) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkQueryPool) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFramebuffer) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkRenderPass) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineCache) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplate) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSamplerYcbcrConversion) - +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPrivateDataSlot) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR) - VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT) - typedef enum VkAttachmentLoadOp { VK_ATTACHMENT_LOAD_OP_LOAD = 0, VK_ATTACHMENT_LOAD_OP_CLEAR = 1, - VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2 + VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2, + VK_ATTACHMENT_LOAD_OP_MAX_ENUM = 0x7FFFFFFF } VkAttachmentLoadOp; - typedef enum VkAttachmentStoreOp { VK_ATTACHMENT_STORE_OP_STORE = 0, - VK_ATTACHMENT_STORE_OP_DONT_CARE = 1 + VK_ATTACHMENT_STORE_OP_DONT_CARE = 1, + VK_ATTACHMENT_STORE_OP_NONE = 1000301000, + VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF } VkAttachmentStoreOp; - typedef enum VkBlendFactor { VK_BLEND_FACTOR_ZERO = 0, VK_BLEND_FACTOR_ONE = 1, @@ -403,47 +402,63 @@ typedef enum VkBlendFactor { VK_BLEND_FACTOR_SRC1_COLOR = 15, VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR = 16, VK_BLEND_FACTOR_SRC1_ALPHA = 17, - VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18 + VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18, + VK_BLEND_FACTOR_MAX_ENUM = 0x7FFFFFFF } VkBlendFactor; - typedef enum VkBlendOp { VK_BLEND_OP_ADD = 0, VK_BLEND_OP_SUBTRACT = 1, VK_BLEND_OP_REVERSE_SUBTRACT = 2, VK_BLEND_OP_MIN = 3, - VK_BLEND_OP_MAX = 4 + VK_BLEND_OP_MAX = 4, + VK_BLEND_OP_MAX_ENUM = 0x7FFFFFFF } VkBlendOp; - typedef enum VkBorderColor { VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0, VK_BORDER_COLOR_INT_TRANSPARENT_BLACK = 1, VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2, VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3, VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4, - VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5 + VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5, + VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF } VkBorderColor; - - - - +typedef enum VkFramebufferCreateFlagBits { + VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT = 1, + VK_FRAMEBUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkFramebufferCreateFlagBits; typedef enum VkPipelineCacheHeaderVersion { - VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1 + VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1, + VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF } VkPipelineCacheHeaderVersion; - - - - +typedef enum VkPipelineCacheCreateFlagBits { + VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT = 1, + VK_PIPELINE_CACHE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCacheCreateFlagBits; +typedef enum VkPipelineShaderStageCreateFlagBits { + VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT = 1, + VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT = 2, + VK_PIPELINE_SHADER_STAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineShaderStageCreateFlagBits; +typedef enum VkDescriptorSetLayoutCreateFlagBits { + VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT = 2, + VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorSetLayoutCreateFlagBits; +typedef enum VkInstanceCreateFlagBits { + VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR = 1, + VK_INSTANCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkInstanceCreateFlagBits; typedef enum VkDeviceQueueCreateFlagBits { - VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT = 1 + VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT = 1, + VK_DEVICE_QUEUE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkDeviceQueueCreateFlagBits; - typedef enum VkBufferCreateFlagBits { VK_BUFFER_CREATE_SPARSE_BINDING_BIT = 1, VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 2, VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 4, - VK_BUFFER_CREATE_PROTECTED_BIT = 8 + VK_BUFFER_CREATE_PROTECTED_BIT = 8, + VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 16, + VK_BUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkBufferCreateFlagBits; - typedef enum VkBufferUsageFlagBits { VK_BUFFER_USAGE_TRANSFER_SRC_BIT = 1, VK_BUFFER_USAGE_TRANSFER_DST_BIT = 2, @@ -453,16 +468,17 @@ typedef enum VkBufferUsageFlagBits { VK_BUFFER_USAGE_STORAGE_BUFFER_BIT = 32, VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 64, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 128, - VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 256 + VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 256, + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT = 131072, + VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkBufferUsageFlagBits; - typedef enum VkColorComponentFlagBits { VK_COLOR_COMPONENT_R_BIT = 1, VK_COLOR_COMPONENT_G_BIT = 2, VK_COLOR_COMPONENT_B_BIT = 4, - VK_COLOR_COMPONENT_A_BIT = 8 + VK_COLOR_COMPONENT_A_BIT = 8, + VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkColorComponentFlagBits; - typedef enum VkComponentSwizzle { VK_COMPONENT_SWIZZLE_IDENTITY = 0, VK_COMPONENT_SWIZZLE_ZERO = 1, @@ -470,34 +486,34 @@ typedef enum VkComponentSwizzle { VK_COMPONENT_SWIZZLE_R = 3, VK_COMPONENT_SWIZZLE_G = 4, VK_COMPONENT_SWIZZLE_B = 5, - VK_COMPONENT_SWIZZLE_A = 6 + VK_COMPONENT_SWIZZLE_A = 6, + VK_COMPONENT_SWIZZLE_MAX_ENUM = 0x7FFFFFFF } VkComponentSwizzle; - typedef enum VkCommandPoolCreateFlagBits { VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 1, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 2, - VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 4 + VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 4, + VK_COMMAND_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkCommandPoolCreateFlagBits; - typedef enum VkCommandPoolResetFlagBits { - VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 1 + VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 1, + VK_COMMAND_POOL_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkCommandPoolResetFlagBits; - typedef enum VkCommandBufferResetFlagBits { - VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 1 + VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 1, + VK_COMMAND_BUFFER_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkCommandBufferResetFlagBits; - typedef enum VkCommandBufferLevel { VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0, - VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1 + VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1, + VK_COMMAND_BUFFER_LEVEL_MAX_ENUM = 0x7FFFFFFF } VkCommandBufferLevel; - typedef enum VkCommandBufferUsageFlagBits { VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 1, VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 2, - VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 4 + VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 4, + VK_COMMAND_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkCommandBufferUsageFlagBits; - typedef enum VkCompareOp { VK_COMPARE_OP_NEVER = 0, VK_COMPARE_OP_LESS = 1, @@ -506,16 +522,16 @@ typedef enum VkCompareOp { VK_COMPARE_OP_GREATER = 4, VK_COMPARE_OP_NOT_EQUAL = 5, VK_COMPARE_OP_GREATER_OR_EQUAL = 6, - VK_COMPARE_OP_ALWAYS = 7 + VK_COMPARE_OP_ALWAYS = 7, + VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF } VkCompareOp; - typedef enum VkCullModeFlagBits { VK_CULL_MODE_NONE = 0, VK_CULL_MODE_FRONT_BIT = 1, VK_CULL_MODE_BACK_BIT = 2, - VK_CULL_MODE_FRONT_AND_BACK = 0x00000003 + VK_CULL_MODE_FRONT_AND_BACK = 0x00000003, + VK_CULL_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkCullModeFlagBits; - typedef enum VkDescriptorType { VK_DESCRIPTOR_TYPE_SAMPLER = 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1, @@ -527,9 +543,10 @@ typedef enum VkDescriptorType { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, - VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10 + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, + VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK = 1000138000, + VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF } VkDescriptorType; - typedef enum VkDynamicState { VK_DYNAMIC_STATE_VIEWPORT = 0, VK_DYNAMIC_STATE_SCISSOR = 1, @@ -539,19 +556,34 @@ typedef enum VkDynamicState { VK_DYNAMIC_STATE_DEPTH_BOUNDS = 5, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK = 6, VK_DYNAMIC_STATE_STENCIL_WRITE_MASK = 7, - VK_DYNAMIC_STATE_STENCIL_REFERENCE = 8 + VK_DYNAMIC_STATE_STENCIL_REFERENCE = 8, + VK_DYNAMIC_STATE_CULL_MODE = 1000267000, + VK_DYNAMIC_STATE_FRONT_FACE = 1000267001, + VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY = 1000267002, + VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT = 1000267003, + VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT = 1000267004, + VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE = 1000267005, + VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE = 1000267006, + VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE = 1000267007, + VK_DYNAMIC_STATE_DEPTH_COMPARE_OP = 1000267008, + VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE = 1000267009, + VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE = 1000267010, + VK_DYNAMIC_STATE_STENCIL_OP = 1000267011, + VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE = 1000377001, + VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE = 1000377002, + VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE = 1000377004, + VK_DYNAMIC_STATE_MAX_ENUM = 0x7FFFFFFF } VkDynamicState; - typedef enum VkFenceCreateFlagBits { - VK_FENCE_CREATE_SIGNALED_BIT = 1 + VK_FENCE_CREATE_SIGNALED_BIT = 1, + VK_FENCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkFenceCreateFlagBits; - typedef enum VkPolygonMode { VK_POLYGON_MODE_FILL = 0, VK_POLYGON_MODE_LINE = 1, - VK_POLYGON_MODE_POINT = 2 + VK_POLYGON_MODE_POINT = 2, + VK_POLYGON_MODE_MAX_ENUM = 0x7FFFFFFF } VkPolygonMode; - typedef enum VkFormat { VK_FORMAT_UNDEFINED = 0, VK_FORMAT_R4G4_UNORM_PACK8 = 1, @@ -771,9 +803,29 @@ typedef enum VkFormat { VK_FORMAT_G16_B16R16_2PLANE_420_UNORM = 1000156030, VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM = 1000156031, VK_FORMAT_G16_B16R16_2PLANE_422_UNORM = 1000156032, - VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM = 1000156033 + VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM = 1000156033, + VK_FORMAT_G8_B8R8_2PLANE_444_UNORM = 1000330000, + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16 = 1000330001, + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16 = 1000330002, + VK_FORMAT_G16_B16R16_2PLANE_444_UNORM = 1000330003, + VK_FORMAT_A4R4G4B4_UNORM_PACK16 = 1000340000, + VK_FORMAT_A4B4G4R4_UNORM_PACK16 = 1000340001, + VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK = 1000066000, + VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK = 1000066001, + VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK = 1000066002, + VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK = 1000066003, + VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK = 1000066004, + VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK = 1000066005, + VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK = 1000066006, + VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK = 1000066007, + VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK = 1000066008, + VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK = 1000066009, + VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK = 1000066010, + VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK = 1000066011, + VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK = 1000066012, + VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK = 1000066013, + VK_FORMAT_MAX_ENUM = 0x7FFFFFFF } VkFormat; - typedef enum VkFormatFeatureFlagBits { VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 1, VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT = 2, @@ -796,14 +848,15 @@ typedef enum VkFormatFeatureFlagBits { VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 1048576, VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 2097152, VK_FORMAT_FEATURE_DISJOINT_BIT = 4194304, - VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 8388608 + VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 8388608, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 65536, + VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkFormatFeatureFlagBits; - typedef enum VkFrontFace { VK_FRONT_FACE_COUNTER_CLOCKWISE = 0, - VK_FRONT_FACE_CLOCKWISE = 1 + VK_FRONT_FACE_CLOCKWISE = 1, + VK_FRONT_FACE_MAX_ENUM = 0x7FFFFFFF } VkFrontFace; - typedef enum VkImageAspectFlagBits { VK_IMAGE_ASPECT_COLOR_BIT = 1, VK_IMAGE_ASPECT_DEPTH_BIT = 2, @@ -811,9 +864,10 @@ typedef enum VkImageAspectFlagBits { VK_IMAGE_ASPECT_METADATA_BIT = 8, VK_IMAGE_ASPECT_PLANE_0_BIT = 16, VK_IMAGE_ASPECT_PLANE_1_BIT = 32, - VK_IMAGE_ASPECT_PLANE_2_BIT = 64 + VK_IMAGE_ASPECT_PLANE_2_BIT = 64, + VK_IMAGE_ASPECT_NONE = 0, + VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkImageAspectFlagBits; - typedef enum VkImageCreateFlagBits { VK_IMAGE_CREATE_SPARSE_BINDING_BIT = 1, VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT = 2, @@ -826,9 +880,9 @@ typedef enum VkImageCreateFlagBits { VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT = 128, VK_IMAGE_CREATE_EXTENDED_USAGE_BIT = 256, VK_IMAGE_CREATE_PROTECTED_BIT = 2048, - VK_IMAGE_CREATE_DISJOINT_BIT = 512 + VK_IMAGE_CREATE_DISJOINT_BIT = 512, + VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkImageCreateFlagBits; - typedef enum VkImageLayout { VK_IMAGE_LAYOUT_UNDEFINED = 0, VK_IMAGE_LAYOUT_GENERAL = 1, @@ -841,20 +895,26 @@ typedef enum VkImageLayout { VK_IMAGE_LAYOUT_PREINITIALIZED = 8, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002 + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL = 1000241000, + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL = 1000241001, + VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL = 1000241002, + VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL = 1000241003, + VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL = 1000314000, + VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL = 1000314001, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002, + VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF } VkImageLayout; - typedef enum VkImageTiling { VK_IMAGE_TILING_OPTIMAL = 0, - VK_IMAGE_TILING_LINEAR = 1 + VK_IMAGE_TILING_LINEAR = 1, + VK_IMAGE_TILING_MAX_ENUM = 0x7FFFFFFF } VkImageTiling; - typedef enum VkImageType { VK_IMAGE_TYPE_1D = 0, VK_IMAGE_TYPE_2D = 1, - VK_IMAGE_TYPE_3D = 2 + VK_IMAGE_TYPE_3D = 2, + VK_IMAGE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkImageType; - typedef enum VkImageUsageFlagBits { VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 1, VK_IMAGE_USAGE_TRANSFER_DST_BIT = 2, @@ -863,10 +923,9 @@ typedef enum VkImageUsageFlagBits { VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 16, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 32, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 64, - VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 128 + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 128, + VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkImageUsageFlagBits; - - typedef enum VkImageViewType { VK_IMAGE_VIEW_TYPE_1D = 0, VK_IMAGE_VIEW_TYPE_2D = 1, @@ -874,19 +933,19 @@ typedef enum VkImageViewType { VK_IMAGE_VIEW_TYPE_CUBE = 3, VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4, VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5, - VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6 + VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6, + VK_IMAGE_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF } VkImageViewType; - typedef enum VkSharingMode { VK_SHARING_MODE_EXCLUSIVE = 0, - VK_SHARING_MODE_CONCURRENT = 1 + VK_SHARING_MODE_CONCURRENT = 1, + VK_SHARING_MODE_MAX_ENUM = 0x7FFFFFFF } VkSharingMode; - typedef enum VkIndexType { VK_INDEX_TYPE_UINT16 = 0, - VK_INDEX_TYPE_UINT32 = 1 + VK_INDEX_TYPE_UINT32 = 1, + VK_INDEX_TYPE_MAX_ENUM = 0x7FFFFFFF } VkIndexType; - typedef enum VkLogicOp { VK_LOGIC_OP_CLEAR = 0, VK_LOGIC_OP_AND = 1, @@ -903,14 +962,14 @@ typedef enum VkLogicOp { VK_LOGIC_OP_COPY_INVERTED = 12, VK_LOGIC_OP_OR_INVERTED = 13, VK_LOGIC_OP_NAND = 14, - VK_LOGIC_OP_SET = 15 + VK_LOGIC_OP_SET = 15, + VK_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF } VkLogicOp; - typedef enum VkMemoryHeapFlagBits { VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 1, - VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 2 + VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 2, + VK_MEMORY_HEAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkMemoryHeapFlagBits; - typedef enum VkAccessFlagBits { VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 1, VK_ACCESS_INDEX_READ_BIT = 2, @@ -928,40 +987,43 @@ typedef enum VkAccessFlagBits { VK_ACCESS_HOST_READ_BIT = 8192, VK_ACCESS_HOST_WRITE_BIT = 16384, VK_ACCESS_MEMORY_READ_BIT = 32768, - VK_ACCESS_MEMORY_WRITE_BIT = 65536 + VK_ACCESS_MEMORY_WRITE_BIT = 65536, + VK_ACCESS_NONE = 0, + VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkAccessFlagBits; - typedef enum VkMemoryPropertyFlagBits { VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 1, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 2, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 4, VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 8, VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 16, - VK_MEMORY_PROPERTY_PROTECTED_BIT = 32 + VK_MEMORY_PROPERTY_PROTECTED_BIT = 32, + VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkMemoryPropertyFlagBits; - typedef enum VkPhysicalDeviceType { VK_PHYSICAL_DEVICE_TYPE_OTHER = 0, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2, VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3, - VK_PHYSICAL_DEVICE_TYPE_CPU = 4 + VK_PHYSICAL_DEVICE_TYPE_CPU = 4, + VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkPhysicalDeviceType; - typedef enum VkPipelineBindPoint { VK_PIPELINE_BIND_POINT_GRAPHICS = 0, - VK_PIPELINE_BIND_POINT_COMPUTE = 1 + VK_PIPELINE_BIND_POINT_COMPUTE = 1, + VK_PIPELINE_BIND_POINT_MAX_ENUM = 0x7FFFFFFF } VkPipelineBindPoint; - typedef enum VkPipelineCreateFlagBits { VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 1, VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 2, VK_PIPELINE_CREATE_DERIVATIVE_BIT = 4, VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 8, VK_PIPELINE_CREATE_DISPATCH_BASE_BIT = 16, - VK_PIPELINE_CREATE_DISPATCH_BASE = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT + VK_PIPELINE_CREATE_DISPATCH_BASE = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT, + VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT = 256, + VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT = 512, + VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkPipelineCreateFlagBits; - typedef enum VkPrimitiveTopology { VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0, VK_PRIMITIVE_TOPOLOGY_LINE_LIST = 1, @@ -973,13 +1035,13 @@ typedef enum VkPrimitiveTopology { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY = 7, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9, - VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10 + VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10, + VK_PRIMITIVE_TOPOLOGY_MAX_ENUM = 0x7FFFFFFF } VkPrimitiveTopology; - typedef enum VkQueryControlFlagBits { - VK_QUERY_CONTROL_PRECISE_BIT = 1 + VK_QUERY_CONTROL_PRECISE_BIT = 1, + VK_QUERY_CONTROL_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkQueryControlFlagBits; - typedef enum VkQueryPipelineStatisticFlagBits { VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT = 1, VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT = 2, @@ -991,35 +1053,35 @@ typedef enum VkQueryPipelineStatisticFlagBits { VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT = 128, VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 256, VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 512, - VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 1024 + VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 1024, + VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkQueryPipelineStatisticFlagBits; - typedef enum VkQueryResultFlagBits { VK_QUERY_RESULT_64_BIT = 1, VK_QUERY_RESULT_WAIT_BIT = 2, VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 4, - VK_QUERY_RESULT_PARTIAL_BIT = 8 + VK_QUERY_RESULT_PARTIAL_BIT = 8, + VK_QUERY_RESULT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkQueryResultFlagBits; - typedef enum VkQueryType { VK_QUERY_TYPE_OCCLUSION = 0, VK_QUERY_TYPE_PIPELINE_STATISTICS = 1, - VK_QUERY_TYPE_TIMESTAMP = 2 + VK_QUERY_TYPE_TIMESTAMP = 2, + VK_QUERY_TYPE_MAX_ENUM = 0x7FFFFFFF } VkQueryType; - typedef enum VkQueueFlagBits { VK_QUEUE_GRAPHICS_BIT = 1, VK_QUEUE_COMPUTE_BIT = 2, VK_QUEUE_TRANSFER_BIT = 4, VK_QUEUE_SPARSE_BINDING_BIT = 8, - VK_QUEUE_PROTECTED_BIT = 16 + VK_QUEUE_PROTECTED_BIT = 16, + VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkQueueFlagBits; - typedef enum VkSubpassContents { VK_SUBPASS_CONTENTS_INLINE = 0, - VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1 + VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1, + VK_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF } VkSubpassContents; - typedef enum VkResult { VK_SUCCESS = 0, VK_NOT_READY = 1, @@ -1042,13 +1104,16 @@ typedef enum VkResult { VK_ERROR_UNKNOWN = -13, VK_ERROR_OUT_OF_POOL_MEMORY = -1000069000, VK_ERROR_INVALID_EXTERNAL_HANDLE = -1000072003, + VK_ERROR_FRAGMENTATION = -1000161000, + VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS = -1000257000, + VK_PIPELINE_COMPILE_REQUIRED = 1000297000, VK_ERROR_SURFACE_LOST_KHR = -1000000000, VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001, VK_SUBOPTIMAL_KHR = 1000001003, VK_ERROR_OUT_OF_DATE_KHR = -1000001004, - VK_ERROR_VALIDATION_FAILED_EXT = -1000011001 + VK_ERROR_VALIDATION_FAILED_EXT = -1000011001, + VK_RESULT_MAX_ENUM = 0x7FFFFFFF } VkResult; - typedef enum VkShaderStageFlagBits { VK_SHADER_STAGE_VERTEX_BIT = 1, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT = 2, @@ -1057,20 +1122,20 @@ typedef enum VkShaderStageFlagBits { VK_SHADER_STAGE_FRAGMENT_BIT = 16, VK_SHADER_STAGE_COMPUTE_BIT = 32, VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F, - VK_SHADER_STAGE_ALL = 0x7FFFFFFF + VK_SHADER_STAGE_ALL = 0x7FFFFFFF, + VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkShaderStageFlagBits; - typedef enum VkSparseMemoryBindFlagBits { - VK_SPARSE_MEMORY_BIND_METADATA_BIT = 1 + VK_SPARSE_MEMORY_BIND_METADATA_BIT = 1, + VK_SPARSE_MEMORY_BIND_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkSparseMemoryBindFlagBits; - typedef enum VkStencilFaceFlagBits { VK_STENCIL_FACE_FRONT_BIT = 1, VK_STENCIL_FACE_BACK_BIT = 2, VK_STENCIL_FACE_FRONT_AND_BACK = 0x00000003, - VK_STENCIL_FRONT_AND_BACK = VK_STENCIL_FACE_FRONT_AND_BACK + VK_STENCIL_FRONT_AND_BACK = VK_STENCIL_FACE_FRONT_AND_BACK, + VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkStencilFaceFlagBits; - typedef enum VkStencilOp { VK_STENCIL_OP_KEEP = 0, VK_STENCIL_OP_ZERO = 1, @@ -1079,9 +1144,9 @@ typedef enum VkStencilOp { VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4, VK_STENCIL_OP_INVERT = 5, VK_STENCIL_OP_INCREMENT_AND_WRAP = 6, - VK_STENCIL_OP_DECREMENT_AND_WRAP = 7 + VK_STENCIL_OP_DECREMENT_AND_WRAP = 7, + VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF } VkStencilOp; - typedef enum VkStructureType { VK_STRUCTURE_TYPE_APPLICATION_INFO = 0, VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1, @@ -1199,6 +1264,108 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT = 1000168001, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES = 1000063000, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES = 49, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES = 50, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES = 51, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES = 52, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO = 1000147000, + VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2 = 1000109000, + VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2 = 1000109001, + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2 = 1000109002, + VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2 = 1000109003, + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2 = 1000109004, + VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO = 1000109005, + VK_STRUCTURE_TYPE_SUBPASS_END_INFO = 1000109006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES = 1000177000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES = 1000196000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES = 1000180000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES = 1000082000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES = 1000197000, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO = 1000161000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES = 1000161001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES = 1000161002, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO = 1000161003, + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT = 1000161004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES = 1000199000, + VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE = 1000199001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES = 1000221000, + VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO = 1000246000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES = 1000130000, + VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO = 1000130001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES = 1000211000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES = 1000108000, + VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO = 1000108001, + VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO = 1000108002, + VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO = 1000108003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES = 1000253000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES = 1000175000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES = 1000241000, + VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT = 1000241001, + VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT = 1000241002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES = 1000261000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES = 1000207000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES = 1000207001, + VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO = 1000207002, + VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO = 1000207003, + VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO = 1000207004, + VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO = 1000207005, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES = 1000257000, + VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO = 1000244001, + VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO = 1000257002, + VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO = 1000257003, + VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO = 1000257004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES = 53, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES = 54, + VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO = 1000192000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES = 1000215000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES = 1000245000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES = 1000276000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES = 1000295000, + VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO = 1000295001, + VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO = 1000295002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES = 1000297000, + VK_STRUCTURE_TYPE_MEMORY_BARRIER_2 = 1000314000, + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2 = 1000314001, + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 = 1000314002, + VK_STRUCTURE_TYPE_DEPENDENCY_INFO = 1000314003, + VK_STRUCTURE_TYPE_SUBMIT_INFO_2 = 1000314004, + VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO = 1000314005, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO = 1000314006, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES = 1000314007, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES = 1000325000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES = 1000335000, + VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2 = 1000337000, + VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2 = 1000337001, + VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2 = 1000337002, + VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2 = 1000337003, + VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2 = 1000337004, + VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2 = 1000337005, + VK_STRUCTURE_TYPE_BUFFER_COPY_2 = 1000337006, + VK_STRUCTURE_TYPE_IMAGE_COPY_2 = 1000337007, + VK_STRUCTURE_TYPE_IMAGE_BLIT_2 = 1000337008, + VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2 = 1000337009, + VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2 = 1000337010, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES = 1000225000, + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO = 1000225001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES = 1000225002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES = 1000138000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES = 1000138001, + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK = 1000138002, + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO = 1000138003, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES = 1000066000, + VK_STRUCTURE_TYPE_RENDERING_INFO = 1000044000, + VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO = 1000044001, + VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO = 1000044002, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES = 1000044003, + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO = 1000044004, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES = 1000280000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES = 1000280001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES = 1000281001, + VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3 = 1000360000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES = 1000413000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES = 1000413001, + VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS = 1000413002, + VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS = 1000413003, VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000, VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001, VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007, @@ -1208,43 +1375,44 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR = 1000060011, VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR = 1000060012, VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT = 1000011000, - VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT + VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, + VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkStructureType; - typedef enum VkSystemAllocationScope { VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT = 1, VK_SYSTEM_ALLOCATION_SCOPE_CACHE = 2, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE = 3, - VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4 + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4, + VK_SYSTEM_ALLOCATION_SCOPE_MAX_ENUM = 0x7FFFFFFF } VkSystemAllocationScope; - typedef enum VkInternalAllocationType { - VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0 + VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0, + VK_INTERNAL_ALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF } VkInternalAllocationType; - typedef enum VkSamplerAddressMode { VK_SAMPLER_ADDRESS_MODE_REPEAT = 0, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3 + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3, + VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4, + VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF } VkSamplerAddressMode; - typedef enum VkFilter { VK_FILTER_NEAREST = 0, - VK_FILTER_LINEAR = 1 + VK_FILTER_LINEAR = 1, + VK_FILTER_MAX_ENUM = 0x7FFFFFFF } VkFilter; - typedef enum VkSamplerMipmapMode { VK_SAMPLER_MIPMAP_MODE_NEAREST = 0, - VK_SAMPLER_MIPMAP_MODE_LINEAR = 1 + VK_SAMPLER_MIPMAP_MODE_LINEAR = 1, + VK_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF } VkSamplerMipmapMode; - typedef enum VkVertexInputRate { VK_VERTEX_INPUT_RATE_VERTEX = 0, - VK_VERTEX_INPUT_RATE_INSTANCE = 1 + VK_VERTEX_INPUT_RATE_INSTANCE = 1, + VK_VERTEX_INPUT_RATE_MAX_ENUM = 0x7FFFFFFF } VkVertexInputRate; - typedef enum VkPipelineStageFlagBits { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 1, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT = 2, @@ -1262,15 +1430,16 @@ typedef enum VkPipelineStageFlagBits { VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT = 8192, VK_PIPELINE_STAGE_HOST_BIT = 16384, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 32768, - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 65536 + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 65536, + VK_PIPELINE_STAGE_NONE = 0, + VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkPipelineStageFlagBits; - typedef enum VkSparseImageFormatFlagBits { VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 1, VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT = 2, - VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT = 4 + VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT = 4, + VK_SPARSE_IMAGE_FORMAT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkSparseImageFormatFlagBits; - typedef enum VkSampleCountFlagBits { VK_SAMPLE_COUNT_1_BIT = 1, VK_SAMPLE_COUNT_2_BIT = 2, @@ -1278,23 +1447,24 @@ typedef enum VkSampleCountFlagBits { VK_SAMPLE_COUNT_8_BIT = 8, VK_SAMPLE_COUNT_16_BIT = 16, VK_SAMPLE_COUNT_32_BIT = 32, - VK_SAMPLE_COUNT_64_BIT = 64 + VK_SAMPLE_COUNT_64_BIT = 64, + VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkSampleCountFlagBits; - typedef enum VkAttachmentDescriptionFlagBits { - VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 1 + VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 1, + VK_ATTACHMENT_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkAttachmentDescriptionFlagBits; - typedef enum VkDescriptorPoolCreateFlagBits { - VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 1 + VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 1, + VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT = 2, + VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkDescriptorPoolCreateFlagBits; - typedef enum VkDependencyFlagBits { VK_DEPENDENCY_BY_REGION_BIT = 1, VK_DEPENDENCY_DEVICE_GROUP_BIT = 4, - VK_DEPENDENCY_VIEW_LOCAL_BIT = 2 + VK_DEPENDENCY_VIEW_LOCAL_BIT = 2, + VK_DEPENDENCY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkDependencyFlagBits; - typedef enum VkObjectType { VK_OBJECT_TYPE_UNKNOWN = 0, VK_OBJECT_TYPE_INSTANCE = 1, @@ -1324,41 +1494,253 @@ typedef enum VkObjectType { VK_OBJECT_TYPE_COMMAND_POOL = 25, VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000, VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000, + VK_OBJECT_TYPE_PRIVATE_DATA_SLOT = 1000295000, VK_OBJECT_TYPE_SURFACE_KHR = 1000000000, VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000, - VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000 + VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000, + VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF } VkObjectType; - +typedef enum VkEventCreateFlagBits { + VK_EVENT_CREATE_DEVICE_ONLY_BIT = 1, + VK_EVENT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkEventCreateFlagBits; typedef enum VkDescriptorUpdateTemplateType { - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0 + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0, + VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkDescriptorUpdateTemplateType; - - typedef enum VkPointClippingBehavior { VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES = 0, - VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY = 1 + VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY = 1, + VK_POINT_CLIPPING_BEHAVIOR_MAX_ENUM = 0x7FFFFFFF } VkPointClippingBehavior; +typedef enum VkResolveModeFlagBits { + VK_RESOLVE_MODE_NONE = 0, + VK_RESOLVE_MODE_SAMPLE_ZERO_BIT = 1, + VK_RESOLVE_MODE_AVERAGE_BIT = 2, + VK_RESOLVE_MODE_MIN_BIT = 4, + VK_RESOLVE_MODE_MAX_BIT = 8, + VK_RESOLVE_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkResolveModeFlagBits; +typedef enum VkDescriptorBindingFlagBits { + VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT = 1, + VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT = 2, + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT = 4, + VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT = 8, + VK_DESCRIPTOR_BINDING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkDescriptorBindingFlagBits; +typedef enum VkSemaphoreType { + VK_SEMAPHORE_TYPE_BINARY = 0, + VK_SEMAPHORE_TYPE_TIMELINE = 1, + VK_SEMAPHORE_TYPE_MAX_ENUM = 0x7FFFFFFF +} VkSemaphoreType; +typedef enum VkPipelineCreationFeedbackFlagBits { + VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT = 1, + VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT, + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT = 2, + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT, + VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT = 4, + VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT, + VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkPipelineCreationFeedbackFlagBits; +typedef enum VkSemaphoreWaitFlagBits { + VK_SEMAPHORE_WAIT_ANY_BIT = 1, + VK_SEMAPHORE_WAIT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSemaphoreWaitFlagBits; +typedef enum VkToolPurposeFlagBits { + VK_TOOL_PURPOSE_VALIDATION_BIT = 1, + VK_TOOL_PURPOSE_VALIDATION_BIT_EXT = VK_TOOL_PURPOSE_VALIDATION_BIT, + VK_TOOL_PURPOSE_PROFILING_BIT = 2, + VK_TOOL_PURPOSE_PROFILING_BIT_EXT = VK_TOOL_PURPOSE_PROFILING_BIT, + VK_TOOL_PURPOSE_TRACING_BIT = 4, + VK_TOOL_PURPOSE_TRACING_BIT_EXT = VK_TOOL_PURPOSE_TRACING_BIT, + VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT = 8, + VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT_EXT = VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT, + VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT = 16, + VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT_EXT = VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT, + VK_TOOL_PURPOSE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkToolPurposeFlagBits; +typedef uint64_t VkAccessFlagBits2; +static const VkAccessFlagBits2 VK_ACCESS_2_NONE = 0; +static const VkAccessFlagBits2 VK_ACCESS_2_NONE_KHR = 0; +static const VkAccessFlagBits2 VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT = 1; +static const VkAccessFlagBits2 VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR = 1; +static const VkAccessFlagBits2 VK_ACCESS_2_INDEX_READ_BIT = 2; +static const VkAccessFlagBits2 VK_ACCESS_2_INDEX_READ_BIT_KHR = 2; +static const VkAccessFlagBits2 VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT = 4; +static const VkAccessFlagBits2 VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR = 4; +static const VkAccessFlagBits2 VK_ACCESS_2_UNIFORM_READ_BIT = 8; +static const VkAccessFlagBits2 VK_ACCESS_2_UNIFORM_READ_BIT_KHR = 8; +static const VkAccessFlagBits2 VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT = 16; +static const VkAccessFlagBits2 VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR = 16; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_READ_BIT = 32; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_READ_BIT_KHR = 32; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_WRITE_BIT = 64; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_WRITE_BIT_KHR = 64; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT = 128; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR = 128; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT = 256; +static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR = 256; +static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 512; +static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR = 512; +static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 1024; +static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR = 1024; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_READ_BIT = 2048; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_READ_BIT_KHR = 2048; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_WRITE_BIT = 4096; +static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR = 4096; +static const VkAccessFlagBits2 VK_ACCESS_2_HOST_READ_BIT = 8192; +static const VkAccessFlagBits2 VK_ACCESS_2_HOST_READ_BIT_KHR = 8192; +static const VkAccessFlagBits2 VK_ACCESS_2_HOST_WRITE_BIT = 16384; +static const VkAccessFlagBits2 VK_ACCESS_2_HOST_WRITE_BIT_KHR = 16384; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_READ_BIT = 32768; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_READ_BIT_KHR = 32768; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_WRITE_BIT = 65536; +static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_WRITE_BIT_KHR = 65536; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_SAMPLED_READ_BIT = 4294967296; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_SAMPLED_READ_BIT_KHR = 4294967296; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_READ_BIT = 8589934592; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_READ_BIT_KHR = 8589934592; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT = 17179869184; +static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT_KHR = 17179869184; +typedef uint64_t VkPipelineStageFlagBits2; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_NONE = 0; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_NONE_KHR = 0; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT = 1; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR = 1; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT = 2; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR = 2; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT = 4; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR = 4; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT = 8; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR = 8; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT = 16; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR = 16; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT = 32; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR = 32; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT = 64; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR = 64; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT = 128; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR = 128; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT = 256; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR = 256; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT = 512; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR = 512; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT = 1024; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR = 1024; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT = 2048; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR = 2048; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT = 4096; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR = 4096; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFER_BIT = 4096; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR = 4096; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT = 8192; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR = 8192; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_HOST_BIT = 16384; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_HOST_BIT_KHR = 16384; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT = 32768; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT_KHR = 32768; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT = 65536; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR = 65536; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COPY_BIT = 4294967296; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COPY_BIT_KHR = 4294967296; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RESOLVE_BIT = 8589934592; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR = 8589934592; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BLIT_BIT = 17179869184; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BLIT_BIT_KHR = 17179869184; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLEAR_BIT = 34359738368; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR = 34359738368; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT = 68719476736; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR = 68719476736; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT = 137438953472; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR = 137438953472; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT = 274877906944; +static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT_KHR = 274877906944; +typedef uint64_t VkFormatFeatureFlagBits2; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT = 1; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT_KHR = 1; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT = 2; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT_KHR = 2; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT = 4; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT_KHR = 4; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT = 8; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR = 8; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT = 16; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT_KHR = 16; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 32; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT_KHR = 32; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT = 64; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT_KHR = 64; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT = 128; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT_KHR = 128; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT = 256; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT_KHR = 256; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT = 512; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT_KHR = 512; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_SRC_BIT = 1024; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_SRC_BIT_KHR = 1024; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_DST_BIT = 2048; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_DST_BIT_KHR = 2048; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 4096; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT_KHR = 4096; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT = 8192; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT = 8192; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT = 16384; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT_KHR = 16384; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT = 32768; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT_KHR = 32768; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 65536; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT_KHR = 65536; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT = 131072; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = 131072; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT = 262144; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR = 262144; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT = 524288; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR = 524288; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 1048576; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR = 1048576; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 2097152; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR = 2097152; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DISJOINT_BIT = 4194304; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DISJOINT_BIT_KHR = 4194304; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT = 8388608; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT_KHR = 8388608; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT = 2147483648; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT_KHR = 2147483648; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT = 4294967296; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR = 4294967296; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT = 8589934592; +static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR = 8589934592; + +typedef enum VkRenderingFlagBits { + VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT = 1, + VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT, + VK_RENDERING_SUSPENDING_BIT = 2, + VK_RENDERING_SUSPENDING_BIT_KHR = VK_RENDERING_SUSPENDING_BIT, + VK_RENDERING_RESUMING_BIT = 4, + VK_RENDERING_RESUMING_BIT_KHR = VK_RENDERING_RESUMING_BIT, + VK_RENDERING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkRenderingFlagBits; typedef enum VkColorSpaceKHR { VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0, - VK_COLORSPACE_SRGB_NONLINEAR_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR + VK_COLORSPACE_SRGB_NONLINEAR_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, + VK_COLOR_SPACE_MAX_ENUM_KHR = 0x7FFFFFFF } VkColorSpaceKHR; - typedef enum VkCompositeAlphaFlagBitsKHR { VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 1, VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 2, VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 4, - VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 8 + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 8, + VK_COMPOSITE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkCompositeAlphaFlagBitsKHR; - typedef enum VkPresentModeKHR { VK_PRESENT_MODE_IMMEDIATE_KHR = 0, VK_PRESENT_MODE_MAILBOX_KHR = 1, VK_PRESENT_MODE_FIFO_KHR = 2, - VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3 + VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3, + VK_PRESENT_MODE_MAX_ENUM_KHR = 0x7FFFFFFF } VkPresentModeKHR; - typedef enum VkSurfaceTransformFlagBitsKHR { VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 1, VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 2, @@ -1368,17 +1750,17 @@ typedef enum VkSurfaceTransformFlagBitsKHR { VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR = 32, VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 64, VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 128, - VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 256 + VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 256, + VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkSurfaceTransformFlagBitsKHR; - typedef enum VkDebugReportFlagBitsEXT { VK_DEBUG_REPORT_INFORMATION_BIT_EXT = 1, VK_DEBUG_REPORT_WARNING_BIT_EXT = 2, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT = 4, VK_DEBUG_REPORT_ERROR_BIT_EXT = 8, - VK_DEBUG_REPORT_DEBUG_BIT_EXT = 16 + VK_DEBUG_REPORT_DEBUG_BIT_EXT = 16, + VK_DEBUG_REPORT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF } VkDebugReportFlagBitsEXT; - typedef enum VkDebugReportObjectTypeEXT { VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT = 0, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT = 1, @@ -1415,9 +1797,9 @@ typedef enum VkDebugReportObjectTypeEXT { VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33, VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000, - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000 + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000, + VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF } VkDebugReportObjectTypeEXT; - typedef enum VkExternalMemoryHandleTypeFlagBits { VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT = 1, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT = 2, @@ -1425,72 +1807,74 @@ typedef enum VkExternalMemoryHandleTypeFlagBits { VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT = 8, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT = 16, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT = 32, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT = 64 + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT = 64, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkExternalMemoryHandleTypeFlagBits; - typedef enum VkExternalMemoryFeatureFlagBits { VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT = 1, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT = 2, - VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT = 4 + VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT = 4, + VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkExternalMemoryFeatureFlagBits; - typedef enum VkExternalSemaphoreHandleTypeFlagBits { VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT = 1, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 2, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 4, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT = 8, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D11_FENCE_BIT = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT, - VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 16 + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 16, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkExternalSemaphoreHandleTypeFlagBits; - typedef enum VkExternalSemaphoreFeatureFlagBits { VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT = 1, - VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT = 2 + VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT = 2, + VK_EXTERNAL_SEMAPHORE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkExternalSemaphoreFeatureFlagBits; - typedef enum VkSemaphoreImportFlagBits { - VK_SEMAPHORE_IMPORT_TEMPORARY_BIT = 1 + VK_SEMAPHORE_IMPORT_TEMPORARY_BIT = 1, + VK_SEMAPHORE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkSemaphoreImportFlagBits; - typedef enum VkExternalFenceHandleTypeFlagBits { VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT = 1, VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 2, VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 4, - VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT = 8 + VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT = 8, + VK_EXTERNAL_FENCE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkExternalFenceHandleTypeFlagBits; - typedef enum VkExternalFenceFeatureFlagBits { VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT = 1, - VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT = 2 + VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT = 2, + VK_EXTERNAL_FENCE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkExternalFenceFeatureFlagBits; - typedef enum VkFenceImportFlagBits { - VK_FENCE_IMPORT_TEMPORARY_BIT = 1 + VK_FENCE_IMPORT_TEMPORARY_BIT = 1, + VK_FENCE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkFenceImportFlagBits; - typedef enum VkPeerMemoryFeatureFlagBits { VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT = 1, VK_PEER_MEMORY_FEATURE_COPY_DST_BIT = 2, VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT = 4, - VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT = 8 + VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT = 8, + VK_PEER_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkPeerMemoryFeatureFlagBits; - typedef enum VkMemoryAllocateFlagBits { - VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 1 + VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 1, + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT = 2, + VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 4, + VK_MEMORY_ALLOCATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkMemoryAllocateFlagBits; - typedef enum VkDeviceGroupPresentModeFlagBitsKHR { VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR = 1, VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR = 2, VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR = 4, - VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 8 + VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 8, + VK_DEVICE_GROUP_PRESENT_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkDeviceGroupPresentModeFlagBitsKHR; - typedef enum VkSwapchainCreateFlagBitsKHR { VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 1, - VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 2 + VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 2, + VK_SWAPCHAIN_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF } VkSwapchainCreateFlagBitsKHR; - typedef enum VkSubgroupFeatureFlagBits { VK_SUBGROUP_FEATURE_BASIC_BIT = 1, VK_SUBGROUP_FEATURE_VOTE_BIT = 2, @@ -1499,71 +1883,109 @@ typedef enum VkSubgroupFeatureFlagBits { VK_SUBGROUP_FEATURE_SHUFFLE_BIT = 16, VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT = 32, VK_SUBGROUP_FEATURE_CLUSTERED_BIT = 64, - VK_SUBGROUP_FEATURE_QUAD_BIT = 128 + VK_SUBGROUP_FEATURE_QUAD_BIT = 128, + VK_SUBGROUP_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkSubgroupFeatureFlagBits; - typedef enum VkTessellationDomainOrigin { VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT = 0, - VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1 + VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1, + VK_TESSELLATION_DOMAIN_ORIGIN_MAX_ENUM = 0x7FFFFFFF } VkTessellationDomainOrigin; - typedef enum VkSamplerYcbcrModelConversion { VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY = 0, VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY = 1, VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709 = 2, VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 = 3, - VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 = 4 + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 = 4, + VK_SAMPLER_YCBCR_MODEL_CONVERSION_MAX_ENUM = 0x7FFFFFFF } VkSamplerYcbcrModelConversion; - typedef enum VkSamplerYcbcrRange { VK_SAMPLER_YCBCR_RANGE_ITU_FULL = 0, - VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1 + VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1, + VK_SAMPLER_YCBCR_RANGE_MAX_ENUM = 0x7FFFFFFF } VkSamplerYcbcrRange; - typedef enum VkChromaLocation { VK_CHROMA_LOCATION_COSITED_EVEN = 0, - VK_CHROMA_LOCATION_MIDPOINT = 1 + VK_CHROMA_LOCATION_MIDPOINT = 1, + VK_CHROMA_LOCATION_MAX_ENUM = 0x7FFFFFFF } VkChromaLocation; - +typedef enum VkSamplerReductionMode { + VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE = 0, + VK_SAMPLER_REDUCTION_MODE_MIN = 1, + VK_SAMPLER_REDUCTION_MODE_MAX = 2, + VK_SAMPLER_REDUCTION_MODE_MAX_ENUM = 0x7FFFFFFF +} VkSamplerReductionMode; +typedef enum VkShaderFloatControlsIndependence { + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY = 0, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL = 1, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE = 2, + VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_MAX_ENUM = 0x7FFFFFFF +} VkShaderFloatControlsIndependence; +typedef enum VkSubmitFlagBits { + VK_SUBMIT_PROTECTED_BIT = 1, + VK_SUBMIT_PROTECTED_BIT_KHR = VK_SUBMIT_PROTECTED_BIT, + VK_SUBMIT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VkSubmitFlagBits; typedef enum VkVendorId { VK_VENDOR_ID_VIV = 0x10001, VK_VENDOR_ID_VSI = 0x10002, VK_VENDOR_ID_KAZAN = 0x10003, VK_VENDOR_ID_CODEPLAY = 0x10004, - VK_VENDOR_ID_MESA = 0x10005 + VK_VENDOR_ID_MESA = 0x10005, + VK_VENDOR_ID_POCL = 0x10006, + VK_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF } VkVendorId; - +typedef enum VkDriverId { + VK_DRIVER_ID_AMD_PROPRIETARY = 1, + VK_DRIVER_ID_AMD_OPEN_SOURCE = 2, + VK_DRIVER_ID_MESA_RADV = 3, + VK_DRIVER_ID_NVIDIA_PROPRIETARY = 4, + VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS = 5, + VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA = 6, + VK_DRIVER_ID_IMAGINATION_PROPRIETARY = 7, + VK_DRIVER_ID_QUALCOMM_PROPRIETARY = 8, + VK_DRIVER_ID_ARM_PROPRIETARY = 9, + VK_DRIVER_ID_GOOGLE_SWIFTSHADER = 10, + VK_DRIVER_ID_GGP_PROPRIETARY = 11, + VK_DRIVER_ID_BROADCOM_PROPRIETARY = 12, + VK_DRIVER_ID_MESA_LLVMPIPE = 13, + VK_DRIVER_ID_MOLTENVK = 14, + VK_DRIVER_ID_COREAVI_PROPRIETARY = 15, + VK_DRIVER_ID_JUICE_PROPRIETARY = 16, + VK_DRIVER_ID_VERISILICON_PROPRIETARY = 17, + VK_DRIVER_ID_MESA_TURNIP = 18, + VK_DRIVER_ID_MESA_V3DV = 19, + VK_DRIVER_ID_MESA_PANVK = 20, + VK_DRIVER_ID_SAMSUNG_PROPRIETARY = 21, + VK_DRIVER_ID_MESA_VENUS = 22, + VK_DRIVER_ID_MESA_DOZEN = 23, + VK_DRIVER_ID_MAX_ENUM = 0x7FFFFFFF +} VkDriverId; typedef void (VKAPI_PTR *PFN_vkInternalAllocationNotification)( void* pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope); - typedef void (VKAPI_PTR *PFN_vkInternalFreeNotification)( void* pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope); - typedef void* (VKAPI_PTR *PFN_vkReallocationFunction)( void* pUserData, void* pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope); - typedef void* (VKAPI_PTR *PFN_vkAllocationFunction)( void* pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope); - typedef void (VKAPI_PTR *PFN_vkFreeFunction)( void* pUserData, void* pMemory); - typedef void (VKAPI_PTR *PFN_vkVoidFunction)(void); - typedef struct VkBaseOutStructure { VkStructureType sType; struct VkBaseOutStructure * pNext; @@ -1721,6 +2143,14 @@ typedef struct VkStencilOpState { uint32_t reference; } VkStencilOpState; +typedef struct VkPipelineCacheHeaderVersionOne { + uint32_t headerSize; + VkPipelineCacheHeaderVersion headerVersion; + uint32_t vendorID; + uint32_t deviceID; + uint8_t pipelineCacheUUID [ VK_UUID_SIZE ]; +} VkPipelineCacheHeaderVersionOne; + typedef struct VkCommandBufferAllocateInfo { VkStructureType sType; const void * pNext; @@ -1787,6 +2217,28 @@ typedef struct VkPresentInfoKHR { VkResult * pResults; } VkPresentInfoKHR; +typedef struct VkDevicePrivateDataCreateInfo { + VkStructureType sType; + const void * pNext; + uint32_t privateDataSlotRequestCount; +} VkDevicePrivateDataCreateInfo; + +typedef struct VkConformanceVersion { + uint8_t major; + uint8_t minor; + uint8_t subminor; + uint8_t patch; +} VkConformanceVersion; + +typedef struct VkPhysicalDeviceDriverProperties { + VkStructureType sType; + void * pNext; + VkDriverId driverID; + char driverName [ VK_MAX_DRIVER_NAME_SIZE ]; + char driverInfo [ VK_MAX_DRIVER_INFO_SIZE ]; + VkConformanceVersion conformanceVersion; +} VkPhysicalDeviceDriverProperties; + typedef struct VkPhysicalDeviceExternalImageFormatInfo { VkStructureType sType; const void * pNext; @@ -1939,7 +2391,7 @@ typedef struct VkImageSparseMemoryRequirementsInfo2 { typedef struct VkPhysicalDevicePointClippingProperties { VkStructureType sType; void * pNext; - VkPointClippingBehavior pointClippingBehavior; + VkPointClippingBehavior pointClippingBehavior; } VkPhysicalDevicePointClippingProperties; typedef struct VkMemoryDedicatedAllocateInfo { @@ -1979,168 +2431,268 @@ typedef struct VkSamplerYcbcrConversionImageFormatProperties { uint32_t combinedImageSamplerDescriptorCount; } VkSamplerYcbcrConversionImageFormatProperties; +typedef struct VkSamplerReductionModeCreateInfo { + VkStructureType sType; + const void * pNext; + VkSamplerReductionMode reductionMode; +} VkSamplerReductionModeCreateInfo; + +typedef struct VkPhysicalDeviceInlineUniformBlockProperties { + VkStructureType sType; + void * pNext; + uint32_t maxInlineUniformBlockSize; + uint32_t maxPerStageDescriptorInlineUniformBlocks; + uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks; + uint32_t maxDescriptorSetInlineUniformBlocks; + uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks; +} VkPhysicalDeviceInlineUniformBlockProperties; + +typedef struct VkWriteDescriptorSetInlineUniformBlock { + VkStructureType sType; + const void * pNext; + uint32_t dataSize; + const void * pData; +} VkWriteDescriptorSetInlineUniformBlock; + +typedef struct VkDescriptorPoolInlineUniformBlockCreateInfo { + VkStructureType sType; + const void * pNext; + uint32_t maxInlineUniformBlockBindings; +} VkDescriptorPoolInlineUniformBlockCreateInfo; + +typedef struct VkImageFormatListCreateInfo { + VkStructureType sType; + const void * pNext; + uint32_t viewFormatCount; + const VkFormat * pViewFormats; +} VkImageFormatListCreateInfo; + +typedef struct VkDescriptorSetVariableDescriptorCountAllocateInfo { + VkStructureType sType; + const void * pNext; + uint32_t descriptorSetCount; + const uint32_t * pDescriptorCounts; +} VkDescriptorSetVariableDescriptorCountAllocateInfo; + +typedef struct VkDescriptorSetVariableDescriptorCountLayoutSupport { + VkStructureType sType; + void * pNext; + uint32_t maxVariableDescriptorCount; +} VkDescriptorSetVariableDescriptorCountLayoutSupport; + +typedef struct VkSubpassBeginInfo { + VkStructureType sType; + const void * pNext; + VkSubpassContents contents; +} VkSubpassBeginInfo; + +typedef struct VkSubpassEndInfo { + VkStructureType sType; + const void * pNext; +} VkSubpassEndInfo; + +typedef struct VkPhysicalDeviceTimelineSemaphoreProperties { + VkStructureType sType; + void * pNext; + uint64_t maxTimelineSemaphoreValueDifference; +} VkPhysicalDeviceTimelineSemaphoreProperties; + +typedef struct VkSemaphoreTypeCreateInfo { + VkStructureType sType; + const void * pNext; + VkSemaphoreType semaphoreType; + uint64_t initialValue; +} VkSemaphoreTypeCreateInfo; + +typedef struct VkTimelineSemaphoreSubmitInfo { + VkStructureType sType; + const void * pNext; + uint32_t waitSemaphoreValueCount; + const uint64_t * pWaitSemaphoreValues; + uint32_t signalSemaphoreValueCount; + const uint64_t * pSignalSemaphoreValues; +} VkTimelineSemaphoreSubmitInfo; + +typedef struct VkSemaphoreSignalInfo { + VkStructureType sType; + const void * pNext; + VkSemaphore semaphore; + uint64_t value; +} VkSemaphoreSignalInfo; + +typedef struct VkBufferDeviceAddressInfo { + VkStructureType sType; + const void * pNext; + VkBuffer buffer; +} VkBufferDeviceAddressInfo; + +typedef struct VkBufferOpaqueCaptureAddressCreateInfo { + VkStructureType sType; + const void * pNext; + uint64_t opaqueCaptureAddress; +} VkBufferOpaqueCaptureAddressCreateInfo; + +typedef struct VkRenderPassAttachmentBeginInfo { + VkStructureType sType; + const void * pNext; + uint32_t attachmentCount; + const VkImageView * pAttachments; +} VkRenderPassAttachmentBeginInfo; + +typedef struct VkAttachmentReferenceStencilLayout { + VkStructureType sType; + void * pNext; + VkImageLayout stencilLayout; +} VkAttachmentReferenceStencilLayout; + +typedef struct VkAttachmentDescriptionStencilLayout { + VkStructureType sType; + void * pNext; + VkImageLayout stencilInitialLayout; + VkImageLayout stencilFinalLayout; +} VkAttachmentDescriptionStencilLayout; + +typedef struct VkPipelineShaderStageRequiredSubgroupSizeCreateInfo { + VkStructureType sType; + void * pNext; + uint32_t requiredSubgroupSize; +} VkPipelineShaderStageRequiredSubgroupSizeCreateInfo; + +typedef struct VkMemoryOpaqueCaptureAddressAllocateInfo { + VkStructureType sType; + const void * pNext; + uint64_t opaqueCaptureAddress; +} VkMemoryOpaqueCaptureAddressAllocateInfo; + +typedef struct VkDeviceMemoryOpaqueCaptureAddressInfo { + VkStructureType sType; + const void * pNext; + VkDeviceMemory memory; +} VkDeviceMemoryOpaqueCaptureAddressInfo; + +typedef struct VkCommandBufferSubmitInfo { + VkStructureType sType; + const void * pNext; + VkCommandBuffer commandBuffer; + uint32_t deviceMask; +} VkCommandBufferSubmitInfo; + +typedef struct VkPipelineRenderingCreateInfo { + VkStructureType sType; + const void * pNext; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat * pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; +} VkPipelineRenderingCreateInfo; + +typedef struct VkRenderingAttachmentInfo { + VkStructureType sType; + const void * pNext; + VkImageView imageView; + VkImageLayout imageLayout; + VkResolveModeFlagBits resolveMode; + VkImageView resolveImageView; + VkImageLayout resolveImageLayout; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkClearValue clearValue; +} VkRenderingAttachmentInfo; + typedef uint32_t VkSampleMask; - typedef uint32_t VkBool32; - typedef uint32_t VkFlags; - +typedef uint64_t VkFlags64; typedef uint64_t VkDeviceSize; - typedef uint64_t VkDeviceAddress; - typedef VkFlags VkFramebufferCreateFlags; - typedef VkFlags VkQueryPoolCreateFlags; - typedef VkFlags VkRenderPassCreateFlags; - typedef VkFlags VkSamplerCreateFlags; - typedef VkFlags VkPipelineLayoutCreateFlags; - typedef VkFlags VkPipelineCacheCreateFlags; - typedef VkFlags VkPipelineDepthStencilStateCreateFlags; - typedef VkFlags VkPipelineDynamicStateCreateFlags; - typedef VkFlags VkPipelineColorBlendStateCreateFlags; - typedef VkFlags VkPipelineMultisampleStateCreateFlags; - typedef VkFlags VkPipelineRasterizationStateCreateFlags; - typedef VkFlags VkPipelineViewportStateCreateFlags; - typedef VkFlags VkPipelineTessellationStateCreateFlags; - typedef VkFlags VkPipelineInputAssemblyStateCreateFlags; - typedef VkFlags VkPipelineVertexInputStateCreateFlags; - typedef VkFlags VkPipelineShaderStageCreateFlags; - typedef VkFlags VkDescriptorSetLayoutCreateFlags; - typedef VkFlags VkBufferViewCreateFlags; - typedef VkFlags VkInstanceCreateFlags; - typedef VkFlags VkDeviceCreateFlags; - typedef VkFlags VkDeviceQueueCreateFlags; - typedef VkFlags VkQueueFlags; - typedef VkFlags VkMemoryPropertyFlags; - typedef VkFlags VkMemoryHeapFlags; - typedef VkFlags VkAccessFlags; - typedef VkFlags VkBufferUsageFlags; - typedef VkFlags VkBufferCreateFlags; - typedef VkFlags VkShaderStageFlags; - typedef VkFlags VkImageUsageFlags; - typedef VkFlags VkImageCreateFlags; - typedef VkFlags VkImageViewCreateFlags; - typedef VkFlags VkPipelineCreateFlags; - typedef VkFlags VkColorComponentFlags; - typedef VkFlags VkFenceCreateFlags; - typedef VkFlags VkSemaphoreCreateFlags; - typedef VkFlags VkFormatFeatureFlags; - typedef VkFlags VkQueryControlFlags; - typedef VkFlags VkQueryResultFlags; - typedef VkFlags VkShaderModuleCreateFlags; - typedef VkFlags VkEventCreateFlags; - typedef VkFlags VkCommandPoolCreateFlags; - typedef VkFlags VkCommandPoolResetFlags; - typedef VkFlags VkCommandBufferResetFlags; - typedef VkFlags VkCommandBufferUsageFlags; - typedef VkFlags VkQueryPipelineStatisticFlags; - typedef VkFlags VkMemoryMapFlags; - typedef VkFlags VkImageAspectFlags; - typedef VkFlags VkSparseMemoryBindFlags; - typedef VkFlags VkSparseImageFormatFlags; - typedef VkFlags VkSubpassDescriptionFlags; - typedef VkFlags VkPipelineStageFlags; - typedef VkFlags VkSampleCountFlags; - typedef VkFlags VkAttachmentDescriptionFlags; - typedef VkFlags VkStencilFaceFlags; - typedef VkFlags VkCullModeFlags; - typedef VkFlags VkDescriptorPoolCreateFlags; - typedef VkFlags VkDescriptorPoolResetFlags; - typedef VkFlags VkDependencyFlags; - typedef VkFlags VkSubgroupFeatureFlags; - +typedef VkFlags VkPrivateDataSlotCreateFlags; typedef VkFlags VkDescriptorUpdateTemplateCreateFlags; - +typedef VkFlags VkPipelineCreationFeedbackFlags; +typedef VkFlags VkSemaphoreWaitFlags; +typedef VkFlags64 VkAccessFlags2; +typedef VkFlags64 VkPipelineStageFlags2; +typedef VkFlags64 VkFormatFeatureFlags2; +typedef VkFlags VkRenderingFlags; typedef VkFlags VkCompositeAlphaFlagsKHR; - typedef VkFlags VkSurfaceTransformFlagsKHR; - typedef VkFlags VkSwapchainCreateFlagsKHR; - typedef VkFlags VkPeerMemoryFeatureFlags; - typedef VkFlags VkMemoryAllocateFlags; - typedef VkFlags VkDeviceGroupPresentModeFlagsKHR; - typedef VkFlags VkDebugReportFlagsEXT; - typedef VkFlags VkCommandPoolTrimFlags; - typedef VkFlags VkExternalMemoryHandleTypeFlags; - typedef VkFlags VkExternalMemoryFeatureFlags; - typedef VkFlags VkExternalSemaphoreHandleTypeFlags; - typedef VkFlags VkExternalSemaphoreFeatureFlags; - typedef VkFlags VkSemaphoreImportFlags; - typedef VkFlags VkExternalFenceHandleTypeFlags; - typedef VkFlags VkExternalFenceFeatureFlags; - typedef VkFlags VkFenceImportFlags; - +typedef VkFlags VkDescriptorBindingFlags; +typedef VkFlags VkResolveModeFlags; +typedef VkFlags VkToolPurposeFlags; +typedef VkFlags VkSubmitFlags; typedef VkBool32 (VKAPI_PTR *PFN_vkDebugReportCallbackEXT)( VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, @@ -2150,7 +2702,6 @@ typedef VkBool32 (VKAPI_PTR *PFN_vkDebugReportCallbackEXT)( const char* pLayerPrefix, const char* pMessage, void* pUserData); - typedef struct VkDeviceQueueCreateInfo { VkStructureType sType; const void * pNext; @@ -2192,8 +2743,8 @@ typedef struct VkMemoryRequirements { } VkMemoryRequirements; typedef struct VkSparseImageFormatProperties { - VkImageAspectFlags aspectMask; - VkExtent3D imageGranularity; + VkImageAspectFlags aspectMask; + VkExtent3D imageGranularity; VkSparseImageFormatFlags flags; } VkSparseImageFormatProperties; @@ -2842,11 +3393,11 @@ typedef struct VkPhysicalDeviceFeatures { } VkPhysicalDeviceFeatures; typedef struct VkPhysicalDeviceSparseProperties { - VkBool32 residencyStandard2DBlockShape; - VkBool32 residencyStandard2DMultisampleBlockShape; - VkBool32 residencyStandard3DBlockShape; - VkBool32 residencyAlignedMipSize; - VkBool32 residencyNonResidentStrict; + VkBool32 residencyStandard2DBlockShape; + VkBool32 residencyStandard2DMultisampleBlockShape; + VkBool32 residencyStandard3DBlockShape; + VkBool32 residencyAlignedMipSize; + VkBool32 residencyNonResidentStrict; } VkPhysicalDeviceSparseProperties; typedef struct VkPhysicalDeviceLimits { @@ -2905,28 +3456,28 @@ typedef struct VkPhysicalDeviceLimits { uint32_t maxComputeWorkGroupCount [3]; uint32_t maxComputeWorkGroupInvocations; uint32_t maxComputeWorkGroupSize [3]; - uint32_t subPixelPrecisionBits; - uint32_t subTexelPrecisionBits; - uint32_t mipmapPrecisionBits; + uint32_t subPixelPrecisionBits; + uint32_t subTexelPrecisionBits; + uint32_t mipmapPrecisionBits; uint32_t maxDrawIndexedIndexValue; uint32_t maxDrawIndirectCount; float maxSamplerLodBias; float maxSamplerAnisotropy; uint32_t maxViewports; uint32_t maxViewportDimensions [2]; - float viewportBoundsRange [2]; - uint32_t viewportSubPixelBits; - size_t minMemoryMapAlignment; - VkDeviceSize minTexelBufferOffsetAlignment; - VkDeviceSize minUniformBufferOffsetAlignment; - VkDeviceSize minStorageBufferOffsetAlignment; + float viewportBoundsRange [2]; + uint32_t viewportSubPixelBits; + size_t minMemoryMapAlignment; + VkDeviceSize minTexelBufferOffsetAlignment; + VkDeviceSize minUniformBufferOffsetAlignment; + VkDeviceSize minStorageBufferOffsetAlignment; int32_t minTexelOffset; uint32_t maxTexelOffset; int32_t minTexelGatherOffset; uint32_t maxTexelGatherOffset; float minInterpolationOffset; float maxInterpolationOffset; - uint32_t subPixelInterpolationOffsetBits; + uint32_t subPixelInterpolationOffsetBits; uint32_t maxFramebufferWidth; uint32_t maxFramebufferHeight; uint32_t maxFramebufferLayers; @@ -2941,21 +3492,21 @@ typedef struct VkPhysicalDeviceLimits { VkSampleCountFlags sampledImageStencilSampleCounts; VkSampleCountFlags storageImageSampleCounts; uint32_t maxSampleMaskWords; - VkBool32 timestampComputeAndGraphics; - float timestampPeriod; + VkBool32 timestampComputeAndGraphics; + float timestampPeriod; uint32_t maxClipDistances; uint32_t maxCullDistances; uint32_t maxCombinedClipAndCullDistances; uint32_t discreteQueuePriorities; - float pointSizeRange [2]; - float lineWidthRange [2]; - float pointSizeGranularity; - float lineWidthGranularity; - VkBool32 strictLines; - VkBool32 standardSampleLocations; - VkDeviceSize optimalBufferCopyOffsetAlignment; - VkDeviceSize optimalBufferCopyRowPitchAlignment; - VkDeviceSize nonCoherentAtomSize; + float pointSizeRange [2]; + float lineWidthRange [2]; + float pointSizeGranularity; + float lineWidthGranularity; + VkBool32 strictLines; + VkBool32 standardSampleLocations; + VkDeviceSize optimalBufferCopyOffsetAlignment; + VkDeviceSize optimalBufferCopyRowPitchAlignment; + VkDeviceSize nonCoherentAtomSize; } VkPhysicalDeviceLimits; typedef struct VkSemaphoreCreateInfo { @@ -2977,7 +3528,7 @@ typedef struct VkFramebufferCreateInfo { VkStructureType sType; const void * pNext; VkFramebufferCreateFlags flags; - VkRenderPass renderPass; + VkRenderPass renderPass; uint32_t attachmentCount; const VkImageView * pAttachments; uint32_t width; @@ -3039,6 +3590,18 @@ typedef struct VkDebugReportCallbackCreateInfoEXT { void * pUserData; } VkDebugReportCallbackCreateInfoEXT; +typedef struct VkPrivateDataSlotCreateInfo { + VkStructureType sType; + const void * pNext; + VkPrivateDataSlotCreateFlags flags; +} VkPrivateDataSlotCreateInfo; + +typedef struct VkPhysicalDevicePrivateDataFeatures { + VkStructureType sType; + void * pNext; + VkBool32 privateData; +} VkPhysicalDevicePrivateDataFeatures; + typedef struct VkPhysicalDeviceFeatures2 { VkStructureType sType; void * pNext; @@ -3070,13 +3633,13 @@ typedef struct VkPhysicalDeviceImageFormatInfo2 { typedef struct VkQueueFamilyProperties2 { VkStructureType sType; void * pNext; - VkQueueFamilyProperties queueFamilyProperties; + VkQueueFamilyProperties queueFamilyProperties; } VkQueueFamilyProperties2; typedef struct VkSparseImageFormatProperties2 { VkStructureType sType; void * pNext; - VkSparseImageFormatProperties properties; + VkSparseImageFormatProperties properties; } VkSparseImageFormatProperties2; typedef struct VkPhysicalDeviceSparseImageFormatInfo2 { @@ -3127,11 +3690,11 @@ typedef struct VkExternalBufferProperties { typedef struct VkPhysicalDeviceIDProperties { VkStructureType sType; void * pNext; - uint8_t deviceUUID [ VK_UUID_SIZE ]; - uint8_t driverUUID [ VK_UUID_SIZE ]; - uint8_t deviceLUID [ VK_LUID_SIZE ]; - uint32_t deviceNodeMask; - VkBool32 deviceLUIDValid; + uint8_t deviceUUID [ VK_UUID_SIZE ]; + uint8_t driverUUID [ VK_UUID_SIZE ]; + uint8_t deviceLUID [ VK_LUID_SIZE ]; + uint32_t deviceNodeMask; + VkBool32 deviceLUIDValid; } VkPhysicalDeviceIDProperties; typedef struct VkExternalMemoryImageCreateInfo { @@ -3221,7 +3784,7 @@ typedef struct VkBindImageMemoryInfo { typedef struct VkDeviceGroupPresentCapabilitiesKHR { VkStructureType sType; - const void * pNext; + void * pNext; uint32_t presentMask [ VK_MAX_DEVICE_GROUP_SIZE ]; VkDeviceGroupPresentModeFlagsKHR modes; } VkDeviceGroupPresentCapabilitiesKHR; @@ -3270,12 +3833,31 @@ typedef struct VkPhysicalDevice16BitStorageFeatures { typedef struct VkPhysicalDeviceSubgroupProperties { VkStructureType sType; void * pNext; - uint32_t subgroupSize; + uint32_t subgroupSize; VkShaderStageFlags supportedStages; VkSubgroupFeatureFlags supportedOperations; VkBool32 quadOperationsInAllStages; } VkPhysicalDeviceSubgroupProperties; +typedef struct VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures { + VkStructureType sType; + void * pNext; + VkBool32 shaderSubgroupExtendedTypes; +} VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures; + +typedef struct VkDeviceBufferMemoryRequirements { + VkStructureType sType; + const void * pNext; + const VkBufferCreateInfo * pCreateInfo; +} VkDeviceBufferMemoryRequirements; + +typedef struct VkDeviceImageMemoryRequirements { + VkStructureType sType; + const void * pNext; + const VkImageCreateInfo * pCreateInfo; + VkImageAspectFlagBits planeAspect; +} VkDeviceImageMemoryRequirements; + typedef struct VkMemoryRequirements2 { VkStructureType sType; void * pNext; @@ -3346,6 +3928,20 @@ typedef struct VkDeviceQueueInfo2 { uint32_t queueIndex; } VkDeviceQueueInfo2; +typedef struct VkPhysicalDeviceSamplerFilterMinmaxProperties { + VkStructureType sType; + void * pNext; + VkBool32 filterMinmaxSingleComponentFormats; + VkBool32 filterMinmaxImageComponentMapping; +} VkPhysicalDeviceSamplerFilterMinmaxProperties; + +typedef struct VkPhysicalDeviceInlineUniformBlockFeatures { + VkStructureType sType; + void * pNext; + VkBool32 inlineUniformBlock; + VkBool32 descriptorBindingInlineUniformBlockUpdateAfterBind; +} VkPhysicalDeviceInlineUniformBlockFeatures; + typedef struct VkPhysicalDeviceMaintenance3Properties { VkStructureType sType; void * pNext; @@ -3353,6 +3949,18 @@ typedef struct VkPhysicalDeviceMaintenance3Properties { VkDeviceSize maxMemoryAllocationSize; } VkPhysicalDeviceMaintenance3Properties; +typedef struct VkPhysicalDeviceMaintenance4Features { + VkStructureType sType; + void * pNext; + VkBool32 maintenance4; +} VkPhysicalDeviceMaintenance4Features; + +typedef struct VkPhysicalDeviceMaintenance4Properties { + VkStructureType sType; + void * pNext; + VkDeviceSize maxBufferSize; +} VkPhysicalDeviceMaintenance4Properties; + typedef struct VkDescriptorSetLayoutSupport { VkStructureType sType; void * pNext; @@ -3367,6 +3975,839 @@ typedef struct VkPhysicalDeviceShaderDrawParametersFeatures { typedef struct VkPhysicalDeviceShaderDrawParametersFeatures VkPhysicalDeviceShaderDrawParameterFeatures; +typedef struct VkPhysicalDeviceShaderFloat16Int8Features { + VkStructureType sType; + void * pNext; + VkBool32 shaderFloat16; + VkBool32 shaderInt8; +} VkPhysicalDeviceShaderFloat16Int8Features; + +typedef struct VkPhysicalDeviceFloatControlsProperties { + VkStructureType sType; + void * pNext; + VkShaderFloatControlsIndependence denormBehaviorIndependence; + VkShaderFloatControlsIndependence roundingModeIndependence; + VkBool32 shaderSignedZeroInfNanPreserveFloat16; + VkBool32 shaderSignedZeroInfNanPreserveFloat32; + VkBool32 shaderSignedZeroInfNanPreserveFloat64; + VkBool32 shaderDenormPreserveFloat16; + VkBool32 shaderDenormPreserveFloat32; + VkBool32 shaderDenormPreserveFloat64; + VkBool32 shaderDenormFlushToZeroFloat16; + VkBool32 shaderDenormFlushToZeroFloat32; + VkBool32 shaderDenormFlushToZeroFloat64; + VkBool32 shaderRoundingModeRTEFloat16; + VkBool32 shaderRoundingModeRTEFloat32; + VkBool32 shaderRoundingModeRTEFloat64; + VkBool32 shaderRoundingModeRTZFloat16; + VkBool32 shaderRoundingModeRTZFloat32; + VkBool32 shaderRoundingModeRTZFloat64; +} VkPhysicalDeviceFloatControlsProperties; + +typedef struct VkPhysicalDeviceHostQueryResetFeatures { + VkStructureType sType; + void * pNext; + VkBool32 hostQueryReset; +} VkPhysicalDeviceHostQueryResetFeatures; + +typedef struct VkPhysicalDeviceDescriptorIndexingFeatures { + VkStructureType sType; + void * pNext; + VkBool32 shaderInputAttachmentArrayDynamicIndexing; + VkBool32 shaderUniformTexelBufferArrayDynamicIndexing; + VkBool32 shaderStorageTexelBufferArrayDynamicIndexing; + VkBool32 shaderUniformBufferArrayNonUniformIndexing; + VkBool32 shaderSampledImageArrayNonUniformIndexing; + VkBool32 shaderStorageBufferArrayNonUniformIndexing; + VkBool32 shaderStorageImageArrayNonUniformIndexing; + VkBool32 shaderInputAttachmentArrayNonUniformIndexing; + VkBool32 shaderUniformTexelBufferArrayNonUniformIndexing; + VkBool32 shaderStorageTexelBufferArrayNonUniformIndexing; + VkBool32 descriptorBindingUniformBufferUpdateAfterBind; + VkBool32 descriptorBindingSampledImageUpdateAfterBind; + VkBool32 descriptorBindingStorageImageUpdateAfterBind; + VkBool32 descriptorBindingStorageBufferUpdateAfterBind; + VkBool32 descriptorBindingUniformTexelBufferUpdateAfterBind; + VkBool32 descriptorBindingStorageTexelBufferUpdateAfterBind; + VkBool32 descriptorBindingUpdateUnusedWhilePending; + VkBool32 descriptorBindingPartiallyBound; + VkBool32 descriptorBindingVariableDescriptorCount; + VkBool32 runtimeDescriptorArray; +} VkPhysicalDeviceDescriptorIndexingFeatures; + +typedef struct VkPhysicalDeviceDescriptorIndexingProperties { + VkStructureType sType; + void * pNext; + uint32_t maxUpdateAfterBindDescriptorsInAllPools; + VkBool32 shaderUniformBufferArrayNonUniformIndexingNative; + VkBool32 shaderSampledImageArrayNonUniformIndexingNative; + VkBool32 shaderStorageBufferArrayNonUniformIndexingNative; + VkBool32 shaderStorageImageArrayNonUniformIndexingNative; + VkBool32 shaderInputAttachmentArrayNonUniformIndexingNative; + VkBool32 robustBufferAccessUpdateAfterBind; + VkBool32 quadDivergentImplicitLod; + uint32_t maxPerStageDescriptorUpdateAfterBindSamplers; + uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers; + uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages; + uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments; + uint32_t maxPerStageUpdateAfterBindResources; + uint32_t maxDescriptorSetUpdateAfterBindSamplers; + uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers; + uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers; + uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindSampledImages; + uint32_t maxDescriptorSetUpdateAfterBindStorageImages; + uint32_t maxDescriptorSetUpdateAfterBindInputAttachments; +} VkPhysicalDeviceDescriptorIndexingProperties; + +typedef struct VkDescriptorSetLayoutBindingFlagsCreateInfo { + VkStructureType sType; + const void * pNext; + uint32_t bindingCount; + const VkDescriptorBindingFlags * pBindingFlags; +} VkDescriptorSetLayoutBindingFlagsCreateInfo; + +typedef struct VkAttachmentDescription2 { + VkStructureType sType; + const void * pNext; + VkAttachmentDescriptionFlags flags; + VkFormat format; + VkSampleCountFlagBits samples; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkAttachmentLoadOp stencilLoadOp; + VkAttachmentStoreOp stencilStoreOp; + VkImageLayout initialLayout; + VkImageLayout finalLayout; +} VkAttachmentDescription2; + +typedef struct VkAttachmentReference2 { + VkStructureType sType; + const void * pNext; + uint32_t attachment; + VkImageLayout layout; + VkImageAspectFlags aspectMask; +} VkAttachmentReference2; + +typedef struct VkSubpassDescription2 { + VkStructureType sType; + const void * pNext; + VkSubpassDescriptionFlags flags; + VkPipelineBindPoint pipelineBindPoint; + uint32_t viewMask; + uint32_t inputAttachmentCount; + const VkAttachmentReference2 * pInputAttachments; + uint32_t colorAttachmentCount; + const VkAttachmentReference2 * pColorAttachments; + const VkAttachmentReference2 * pResolveAttachments; + const VkAttachmentReference2 * pDepthStencilAttachment; + uint32_t preserveAttachmentCount; + const uint32_t * pPreserveAttachments; +} VkSubpassDescription2; + +typedef struct VkSubpassDependency2 { + VkStructureType sType; + const void * pNext; + uint32_t srcSubpass; + uint32_t dstSubpass; + VkPipelineStageFlags srcStageMask; + VkPipelineStageFlags dstStageMask; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkDependencyFlags dependencyFlags; + int32_t viewOffset; +} VkSubpassDependency2; + +typedef struct VkRenderPassCreateInfo2 { + VkStructureType sType; + const void * pNext; + VkRenderPassCreateFlags flags; + uint32_t attachmentCount; + const VkAttachmentDescription2 * pAttachments; + uint32_t subpassCount; + const VkSubpassDescription2 * pSubpasses; + uint32_t dependencyCount; + const VkSubpassDependency2 * pDependencies; + uint32_t correlatedViewMaskCount; + const uint32_t * pCorrelatedViewMasks; +} VkRenderPassCreateInfo2; + +typedef struct VkPhysicalDeviceTimelineSemaphoreFeatures { + VkStructureType sType; + void * pNext; + VkBool32 timelineSemaphore; +} VkPhysicalDeviceTimelineSemaphoreFeatures; + +typedef struct VkSemaphoreWaitInfo { + VkStructureType sType; + const void * pNext; + VkSemaphoreWaitFlags flags; + uint32_t semaphoreCount; + const VkSemaphore * pSemaphores; + const uint64_t * pValues; +} VkSemaphoreWaitInfo; + +typedef struct VkPhysicalDevice8BitStorageFeatures { + VkStructureType sType; + void * pNext; + VkBool32 storageBuffer8BitAccess; + VkBool32 uniformAndStorageBuffer8BitAccess; + VkBool32 storagePushConstant8; +} VkPhysicalDevice8BitStorageFeatures; + +typedef struct VkPhysicalDeviceVulkanMemoryModelFeatures { + VkStructureType sType; + void * pNext; + VkBool32 vulkanMemoryModel; + VkBool32 vulkanMemoryModelDeviceScope; + VkBool32 vulkanMemoryModelAvailabilityVisibilityChains; +} VkPhysicalDeviceVulkanMemoryModelFeatures; + +typedef struct VkPhysicalDeviceShaderAtomicInt64Features { + VkStructureType sType; + void * pNext; + VkBool32 shaderBufferInt64Atomics; + VkBool32 shaderSharedInt64Atomics; +} VkPhysicalDeviceShaderAtomicInt64Features; + +typedef struct VkPhysicalDeviceDepthStencilResolveProperties { + VkStructureType sType; + void * pNext; + VkResolveModeFlags supportedDepthResolveModes; + VkResolveModeFlags supportedStencilResolveModes; + VkBool32 independentResolveNone; + VkBool32 independentResolve; +} VkPhysicalDeviceDepthStencilResolveProperties; + +typedef struct VkSubpassDescriptionDepthStencilResolve { + VkStructureType sType; + const void * pNext; + VkResolveModeFlagBits depthResolveMode; + VkResolveModeFlagBits stencilResolveMode; + const VkAttachmentReference2 * pDepthStencilResolveAttachment; +} VkSubpassDescriptionDepthStencilResolve; + +typedef struct VkImageStencilUsageCreateInfo { + VkStructureType sType; + const void * pNext; + VkImageUsageFlags stencilUsage; +} VkImageStencilUsageCreateInfo; + +typedef struct VkPhysicalDeviceScalarBlockLayoutFeatures { + VkStructureType sType; + void * pNext; + VkBool32 scalarBlockLayout; +} VkPhysicalDeviceScalarBlockLayoutFeatures; + +typedef struct VkPhysicalDeviceUniformBufferStandardLayoutFeatures { + VkStructureType sType; + void * pNext; + VkBool32 uniformBufferStandardLayout; +} VkPhysicalDeviceUniformBufferStandardLayoutFeatures; + +typedef struct VkPhysicalDeviceBufferDeviceAddressFeatures { + VkStructureType sType; + void * pNext; + VkBool32 bufferDeviceAddress; + VkBool32 bufferDeviceAddressCaptureReplay; + VkBool32 bufferDeviceAddressMultiDevice; +} VkPhysicalDeviceBufferDeviceAddressFeatures; + +typedef struct VkPhysicalDeviceImagelessFramebufferFeatures { + VkStructureType sType; + void * pNext; + VkBool32 imagelessFramebuffer; +} VkPhysicalDeviceImagelessFramebufferFeatures; + +typedef struct VkFramebufferAttachmentImageInfo { + VkStructureType sType; + const void * pNext; + VkImageCreateFlags flags; + VkImageUsageFlags usage; + uint32_t width; + uint32_t height; + uint32_t layerCount; + uint32_t viewFormatCount; + const VkFormat * pViewFormats; +} VkFramebufferAttachmentImageInfo; + +typedef struct VkPhysicalDeviceTextureCompressionASTCHDRFeatures { + VkStructureType sType; + void * pNext; + VkBool32 textureCompressionASTC_HDR; +} VkPhysicalDeviceTextureCompressionASTCHDRFeatures; + +typedef struct VkPipelineCreationFeedback { + VkPipelineCreationFeedbackFlags flags; + uint64_t duration; +} VkPipelineCreationFeedback; + +typedef struct VkPipelineCreationFeedbackCreateInfo { + VkStructureType sType; + const void * pNext; + VkPipelineCreationFeedback * pPipelineCreationFeedback; + uint32_t pipelineStageCreationFeedbackCount; + VkPipelineCreationFeedback * pPipelineStageCreationFeedbacks; +} VkPipelineCreationFeedbackCreateInfo; + +typedef struct VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures { + VkStructureType sType; + void * pNext; + VkBool32 separateDepthStencilLayouts; +} VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures; + +typedef struct VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures { + VkStructureType sType; + void * pNext; + VkBool32 shaderDemoteToHelperInvocation; +} VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures; + +typedef struct VkPhysicalDeviceTexelBufferAlignmentProperties { + VkStructureType sType; + void * pNext; + VkDeviceSize storageTexelBufferOffsetAlignmentBytes; + VkBool32 storageTexelBufferOffsetSingleTexelAlignment; + VkDeviceSize uniformTexelBufferOffsetAlignmentBytes; + VkBool32 uniformTexelBufferOffsetSingleTexelAlignment; +} VkPhysicalDeviceTexelBufferAlignmentProperties; + +typedef struct VkPhysicalDeviceSubgroupSizeControlFeatures { + VkStructureType sType; + void * pNext; + VkBool32 subgroupSizeControl; + VkBool32 computeFullSubgroups; +} VkPhysicalDeviceSubgroupSizeControlFeatures; + +typedef struct VkPhysicalDeviceSubgroupSizeControlProperties { + VkStructureType sType; + void * pNext; + uint32_t minSubgroupSize; + uint32_t maxSubgroupSize; + uint32_t maxComputeWorkgroupSubgroups; + VkShaderStageFlags requiredSubgroupSizeStages; +} VkPhysicalDeviceSubgroupSizeControlProperties; + +typedef struct VkPhysicalDevicePipelineCreationCacheControlFeatures { + VkStructureType sType; + void * pNext; + VkBool32 pipelineCreationCacheControl; +} VkPhysicalDevicePipelineCreationCacheControlFeatures; + +typedef struct VkPhysicalDeviceVulkan11Features { + VkStructureType sType; + void * pNext; + VkBool32 storageBuffer16BitAccess; + VkBool32 uniformAndStorageBuffer16BitAccess; + VkBool32 storagePushConstant16; + VkBool32 storageInputOutput16; + VkBool32 multiview; + VkBool32 multiviewGeometryShader; + VkBool32 multiviewTessellationShader; + VkBool32 variablePointersStorageBuffer; + VkBool32 variablePointers; + VkBool32 protectedMemory; + VkBool32 samplerYcbcrConversion; + VkBool32 shaderDrawParameters; +} VkPhysicalDeviceVulkan11Features; + +typedef struct VkPhysicalDeviceVulkan11Properties { + VkStructureType sType; + void * pNext; + uint8_t deviceUUID [ VK_UUID_SIZE ]; + uint8_t driverUUID [ VK_UUID_SIZE ]; + uint8_t deviceLUID [ VK_LUID_SIZE ]; + uint32_t deviceNodeMask; + VkBool32 deviceLUIDValid; + uint32_t subgroupSize; + VkShaderStageFlags subgroupSupportedStages; + VkSubgroupFeatureFlags subgroupSupportedOperations; + VkBool32 subgroupQuadOperationsInAllStages; + VkPointClippingBehavior pointClippingBehavior; + uint32_t maxMultiviewViewCount; + uint32_t maxMultiviewInstanceIndex; + VkBool32 protectedNoFault; + uint32_t maxPerSetDescriptors; + VkDeviceSize maxMemoryAllocationSize; +} VkPhysicalDeviceVulkan11Properties; + +typedef struct VkPhysicalDeviceVulkan12Features { + VkStructureType sType; + void * pNext; + VkBool32 samplerMirrorClampToEdge; + VkBool32 drawIndirectCount; + VkBool32 storageBuffer8BitAccess; + VkBool32 uniformAndStorageBuffer8BitAccess; + VkBool32 storagePushConstant8; + VkBool32 shaderBufferInt64Atomics; + VkBool32 shaderSharedInt64Atomics; + VkBool32 shaderFloat16; + VkBool32 shaderInt8; + VkBool32 descriptorIndexing; + VkBool32 shaderInputAttachmentArrayDynamicIndexing; + VkBool32 shaderUniformTexelBufferArrayDynamicIndexing; + VkBool32 shaderStorageTexelBufferArrayDynamicIndexing; + VkBool32 shaderUniformBufferArrayNonUniformIndexing; + VkBool32 shaderSampledImageArrayNonUniformIndexing; + VkBool32 shaderStorageBufferArrayNonUniformIndexing; + VkBool32 shaderStorageImageArrayNonUniformIndexing; + VkBool32 shaderInputAttachmentArrayNonUniformIndexing; + VkBool32 shaderUniformTexelBufferArrayNonUniformIndexing; + VkBool32 shaderStorageTexelBufferArrayNonUniformIndexing; + VkBool32 descriptorBindingUniformBufferUpdateAfterBind; + VkBool32 descriptorBindingSampledImageUpdateAfterBind; + VkBool32 descriptorBindingStorageImageUpdateAfterBind; + VkBool32 descriptorBindingStorageBufferUpdateAfterBind; + VkBool32 descriptorBindingUniformTexelBufferUpdateAfterBind; + VkBool32 descriptorBindingStorageTexelBufferUpdateAfterBind; + VkBool32 descriptorBindingUpdateUnusedWhilePending; + VkBool32 descriptorBindingPartiallyBound; + VkBool32 descriptorBindingVariableDescriptorCount; + VkBool32 runtimeDescriptorArray; + VkBool32 samplerFilterMinmax; + VkBool32 scalarBlockLayout; + VkBool32 imagelessFramebuffer; + VkBool32 uniformBufferStandardLayout; + VkBool32 shaderSubgroupExtendedTypes; + VkBool32 separateDepthStencilLayouts; + VkBool32 hostQueryReset; + VkBool32 timelineSemaphore; + VkBool32 bufferDeviceAddress; + VkBool32 bufferDeviceAddressCaptureReplay; + VkBool32 bufferDeviceAddressMultiDevice; + VkBool32 vulkanMemoryModel; + VkBool32 vulkanMemoryModelDeviceScope; + VkBool32 vulkanMemoryModelAvailabilityVisibilityChains; + VkBool32 shaderOutputViewportIndex; + VkBool32 shaderOutputLayer; + VkBool32 subgroupBroadcastDynamicId; +} VkPhysicalDeviceVulkan12Features; + +typedef struct VkPhysicalDeviceVulkan12Properties { + VkStructureType sType; + void * pNext; + VkDriverId driverID; + char driverName [ VK_MAX_DRIVER_NAME_SIZE ]; + char driverInfo [ VK_MAX_DRIVER_INFO_SIZE ]; + VkConformanceVersion conformanceVersion; + VkShaderFloatControlsIndependence denormBehaviorIndependence; + VkShaderFloatControlsIndependence roundingModeIndependence; + VkBool32 shaderSignedZeroInfNanPreserveFloat16; + VkBool32 shaderSignedZeroInfNanPreserveFloat32; + VkBool32 shaderSignedZeroInfNanPreserveFloat64; + VkBool32 shaderDenormPreserveFloat16; + VkBool32 shaderDenormPreserveFloat32; + VkBool32 shaderDenormPreserveFloat64; + VkBool32 shaderDenormFlushToZeroFloat16; + VkBool32 shaderDenormFlushToZeroFloat32; + VkBool32 shaderDenormFlushToZeroFloat64; + VkBool32 shaderRoundingModeRTEFloat16; + VkBool32 shaderRoundingModeRTEFloat32; + VkBool32 shaderRoundingModeRTEFloat64; + VkBool32 shaderRoundingModeRTZFloat16; + VkBool32 shaderRoundingModeRTZFloat32; + VkBool32 shaderRoundingModeRTZFloat64; + uint32_t maxUpdateAfterBindDescriptorsInAllPools; + VkBool32 shaderUniformBufferArrayNonUniformIndexingNative; + VkBool32 shaderSampledImageArrayNonUniformIndexingNative; + VkBool32 shaderStorageBufferArrayNonUniformIndexingNative; + VkBool32 shaderStorageImageArrayNonUniformIndexingNative; + VkBool32 shaderInputAttachmentArrayNonUniformIndexingNative; + VkBool32 robustBufferAccessUpdateAfterBind; + VkBool32 quadDivergentImplicitLod; + uint32_t maxPerStageDescriptorUpdateAfterBindSamplers; + uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers; + uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages; + uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages; + uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments; + uint32_t maxPerStageUpdateAfterBindResources; + uint32_t maxDescriptorSetUpdateAfterBindSamplers; + uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers; + uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers; + uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic; + uint32_t maxDescriptorSetUpdateAfterBindSampledImages; + uint32_t maxDescriptorSetUpdateAfterBindStorageImages; + uint32_t maxDescriptorSetUpdateAfterBindInputAttachments; + VkResolveModeFlags supportedDepthResolveModes; + VkResolveModeFlags supportedStencilResolveModes; + VkBool32 independentResolveNone; + VkBool32 independentResolve; + VkBool32 filterMinmaxSingleComponentFormats; + VkBool32 filterMinmaxImageComponentMapping; + uint64_t maxTimelineSemaphoreValueDifference; + VkSampleCountFlags framebufferIntegerColorSampleCounts; +} VkPhysicalDeviceVulkan12Properties; + +typedef struct VkPhysicalDeviceVulkan13Features { + VkStructureType sType; + void * pNext; + VkBool32 robustImageAccess; + VkBool32 inlineUniformBlock; + VkBool32 descriptorBindingInlineUniformBlockUpdateAfterBind; + VkBool32 pipelineCreationCacheControl; + VkBool32 privateData; + VkBool32 shaderDemoteToHelperInvocation; + VkBool32 shaderTerminateInvocation; + VkBool32 subgroupSizeControl; + VkBool32 computeFullSubgroups; + VkBool32 synchronization2; + VkBool32 textureCompressionASTC_HDR; + VkBool32 shaderZeroInitializeWorkgroupMemory; + VkBool32 dynamicRendering; + VkBool32 shaderIntegerDotProduct; + VkBool32 maintenance4; +} VkPhysicalDeviceVulkan13Features; + +typedef struct VkPhysicalDeviceVulkan13Properties { + VkStructureType sType; + void * pNext; + uint32_t minSubgroupSize; + uint32_t maxSubgroupSize; + uint32_t maxComputeWorkgroupSubgroups; + VkShaderStageFlags requiredSubgroupSizeStages; + uint32_t maxInlineUniformBlockSize; + uint32_t maxPerStageDescriptorInlineUniformBlocks; + uint32_t maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks; + uint32_t maxDescriptorSetInlineUniformBlocks; + uint32_t maxDescriptorSetUpdateAfterBindInlineUniformBlocks; + uint32_t maxInlineUniformTotalSize; + VkBool32 integerDotProduct8BitUnsignedAccelerated; + VkBool32 integerDotProduct8BitSignedAccelerated; + VkBool32 integerDotProduct8BitMixedSignednessAccelerated; + VkBool32 integerDotProduct4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedSignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProduct16BitUnsignedAccelerated; + VkBool32 integerDotProduct16BitSignedAccelerated; + VkBool32 integerDotProduct16BitMixedSignednessAccelerated; + VkBool32 integerDotProduct32BitUnsignedAccelerated; + VkBool32 integerDotProduct32BitSignedAccelerated; + VkBool32 integerDotProduct32BitMixedSignednessAccelerated; + VkBool32 integerDotProduct64BitUnsignedAccelerated; + VkBool32 integerDotProduct64BitSignedAccelerated; + VkBool32 integerDotProduct64BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated; + VkDeviceSize storageTexelBufferOffsetAlignmentBytes; + VkBool32 storageTexelBufferOffsetSingleTexelAlignment; + VkDeviceSize uniformTexelBufferOffsetAlignmentBytes; + VkBool32 uniformTexelBufferOffsetSingleTexelAlignment; + VkDeviceSize maxBufferSize; +} VkPhysicalDeviceVulkan13Properties; + +typedef struct VkPhysicalDeviceToolProperties { + VkStructureType sType; + void * pNext; + char name [ VK_MAX_EXTENSION_NAME_SIZE ]; + char version [ VK_MAX_EXTENSION_NAME_SIZE ]; + VkToolPurposeFlags purposes; + char description [ VK_MAX_DESCRIPTION_SIZE ]; + char layer [ VK_MAX_EXTENSION_NAME_SIZE ]; +} VkPhysicalDeviceToolProperties; + +typedef struct VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures { + VkStructureType sType; + void * pNext; + VkBool32 shaderZeroInitializeWorkgroupMemory; +} VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures; + +typedef struct VkPhysicalDeviceImageRobustnessFeatures { + VkStructureType sType; + void * pNext; + VkBool32 robustImageAccess; +} VkPhysicalDeviceImageRobustnessFeatures; + +typedef struct VkBufferCopy2 { + VkStructureType sType; + const void * pNext; + VkDeviceSize srcOffset; + VkDeviceSize dstOffset; + VkDeviceSize size; +} VkBufferCopy2; + +typedef struct VkImageCopy2 { + VkStructureType sType; + const void * pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageCopy2; + +typedef struct VkImageBlit2 { + VkStructureType sType; + const void * pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffsets [2]; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffsets [2]; +} VkImageBlit2; + +typedef struct VkBufferImageCopy2 { + VkStructureType sType; + const void * pNext; + VkDeviceSize bufferOffset; + uint32_t bufferRowLength; + uint32_t bufferImageHeight; + VkImageSubresourceLayers imageSubresource; + VkOffset3D imageOffset; + VkExtent3D imageExtent; +} VkBufferImageCopy2; + +typedef struct VkImageResolve2 { + VkStructureType sType; + const void * pNext; + VkImageSubresourceLayers srcSubresource; + VkOffset3D srcOffset; + VkImageSubresourceLayers dstSubresource; + VkOffset3D dstOffset; + VkExtent3D extent; +} VkImageResolve2; + +typedef struct VkCopyBufferInfo2 { + VkStructureType sType; + const void * pNext; + VkBuffer srcBuffer; + VkBuffer dstBuffer; + uint32_t regionCount; + const VkBufferCopy2 * pRegions; +} VkCopyBufferInfo2; + +typedef struct VkCopyImageInfo2 { + VkStructureType sType; + const void * pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageCopy2 * pRegions; +} VkCopyImageInfo2; + +typedef struct VkBlitImageInfo2 { + VkStructureType sType; + const void * pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageBlit2 * pRegions; + VkFilter filter; +} VkBlitImageInfo2; + +typedef struct VkCopyBufferToImageInfo2 { + VkStructureType sType; + const void * pNext; + VkBuffer srcBuffer; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkBufferImageCopy2 * pRegions; +} VkCopyBufferToImageInfo2; + +typedef struct VkCopyImageToBufferInfo2 { + VkStructureType sType; + const void * pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkBuffer dstBuffer; + uint32_t regionCount; + const VkBufferImageCopy2 * pRegions; +} VkCopyImageToBufferInfo2; + +typedef struct VkResolveImageInfo2 { + VkStructureType sType; + const void * pNext; + VkImage srcImage; + VkImageLayout srcImageLayout; + VkImage dstImage; + VkImageLayout dstImageLayout; + uint32_t regionCount; + const VkImageResolve2 * pRegions; +} VkResolveImageInfo2; + +typedef struct VkPhysicalDeviceShaderTerminateInvocationFeatures { + VkStructureType sType; + void * pNext; + VkBool32 shaderTerminateInvocation; +} VkPhysicalDeviceShaderTerminateInvocationFeatures; + +typedef struct VkMemoryBarrier2 { + VkStructureType sType; + const void * pNext; + VkPipelineStageFlags2 srcStageMask; + VkAccessFlags2 srcAccessMask; + VkPipelineStageFlags2 dstStageMask; + VkAccessFlags2 dstAccessMask; +} VkMemoryBarrier2; + +typedef struct VkImageMemoryBarrier2 { + VkStructureType sType; + const void * pNext; + VkPipelineStageFlags2 srcStageMask; + VkAccessFlags2 srcAccessMask; + VkPipelineStageFlags2 dstStageMask; + VkAccessFlags2 dstAccessMask; + VkImageLayout oldLayout; + VkImageLayout newLayout; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkImage image; + VkImageSubresourceRange subresourceRange; +} VkImageMemoryBarrier2; + +typedef struct VkBufferMemoryBarrier2 { + VkStructureType sType; + const void * pNext; + VkPipelineStageFlags2 srcStageMask; + VkAccessFlags2 srcAccessMask; + VkPipelineStageFlags2 dstStageMask; + VkAccessFlags2 dstAccessMask; + uint32_t srcQueueFamilyIndex; + uint32_t dstQueueFamilyIndex; + VkBuffer buffer; + VkDeviceSize offset; + VkDeviceSize size; +} VkBufferMemoryBarrier2; + +typedef struct VkDependencyInfo { + VkStructureType sType; + const void * pNext; + VkDependencyFlags dependencyFlags; + uint32_t memoryBarrierCount; + const VkMemoryBarrier2 * pMemoryBarriers; + uint32_t bufferMemoryBarrierCount; + const VkBufferMemoryBarrier2 * pBufferMemoryBarriers; + uint32_t imageMemoryBarrierCount; + const VkImageMemoryBarrier2 * pImageMemoryBarriers; +} VkDependencyInfo; + +typedef struct VkSemaphoreSubmitInfo { + VkStructureType sType; + const void * pNext; + VkSemaphore semaphore; + uint64_t value; + VkPipelineStageFlags2 stageMask; + uint32_t deviceIndex; +} VkSemaphoreSubmitInfo; + +typedef struct VkSubmitInfo2 { + VkStructureType sType; + const void * pNext; + VkSubmitFlags flags; + uint32_t waitSemaphoreInfoCount; + const VkSemaphoreSubmitInfo * pWaitSemaphoreInfos; + uint32_t commandBufferInfoCount; + const VkCommandBufferSubmitInfo * pCommandBufferInfos; + uint32_t signalSemaphoreInfoCount; + const VkSemaphoreSubmitInfo * pSignalSemaphoreInfos; +} VkSubmitInfo2; + +typedef struct VkPhysicalDeviceSynchronization2Features { + VkStructureType sType; + void * pNext; + VkBool32 synchronization2; +} VkPhysicalDeviceSynchronization2Features; + +typedef struct VkPhysicalDeviceShaderIntegerDotProductFeatures { + VkStructureType sType; + void * pNext; + VkBool32 shaderIntegerDotProduct; +} VkPhysicalDeviceShaderIntegerDotProductFeatures; + +typedef struct VkPhysicalDeviceShaderIntegerDotProductProperties { + VkStructureType sType; + void * pNext; + VkBool32 integerDotProduct8BitUnsignedAccelerated; + VkBool32 integerDotProduct8BitSignedAccelerated; + VkBool32 integerDotProduct8BitMixedSignednessAccelerated; + VkBool32 integerDotProduct4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedSignedAccelerated; + VkBool32 integerDotProduct4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProduct16BitUnsignedAccelerated; + VkBool32 integerDotProduct16BitSignedAccelerated; + VkBool32 integerDotProduct16BitMixedSignednessAccelerated; + VkBool32 integerDotProduct32BitUnsignedAccelerated; + VkBool32 integerDotProduct32BitSignedAccelerated; + VkBool32 integerDotProduct32BitMixedSignednessAccelerated; + VkBool32 integerDotProduct64BitUnsignedAccelerated; + VkBool32 integerDotProduct64BitSignedAccelerated; + VkBool32 integerDotProduct64BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitUnsignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitSignedAccelerated; + VkBool32 integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated; +} VkPhysicalDeviceShaderIntegerDotProductProperties; + +typedef struct VkFormatProperties3 { + VkStructureType sType; + void * pNext; + VkFormatFeatureFlags2 linearTilingFeatures; + VkFormatFeatureFlags2 optimalTilingFeatures; + VkFormatFeatureFlags2 bufferFeatures; +} VkFormatProperties3; + +typedef struct VkRenderingInfo { + VkStructureType sType; + const void * pNext; + VkRenderingFlags flags; + VkRect2D renderArea; + uint32_t layerCount; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkRenderingAttachmentInfo * pColorAttachments; + const VkRenderingAttachmentInfo * pDepthAttachment; + const VkRenderingAttachmentInfo * pStencilAttachment; +} VkRenderingInfo; + +typedef struct VkPhysicalDeviceDynamicRenderingFeatures { + VkStructureType sType; + void * pNext; + VkBool32 dynamicRendering; +} VkPhysicalDeviceDynamicRenderingFeatures; + +typedef struct VkCommandBufferInheritanceRenderingInfo { + VkStructureType sType; + const void * pNext; + VkRenderingFlags flags; + uint32_t viewMask; + uint32_t colorAttachmentCount; + const VkFormat * pColorAttachmentFormats; + VkFormat depthAttachmentFormat; + VkFormat stencilAttachmentFormat; + VkSampleCountFlagBits rasterizationSamples; +} VkCommandBufferInheritanceRenderingInfo; + typedef struct VkPhysicalDeviceProperties { uint32_t apiVersion; uint32_t driverVersion; @@ -3411,14 +4852,27 @@ typedef struct VkPhysicalDeviceMemoryProperties2 { VkPhysicalDeviceMemoryProperties memoryProperties; } VkPhysicalDeviceMemoryProperties2; +typedef struct VkFramebufferAttachmentsCreateInfo { + VkStructureType sType; + const void * pNext; + uint32_t attachmentImageInfoCount; + const VkFramebufferAttachmentImageInfo * pAttachmentImageInfos; +} VkFramebufferAttachmentsCreateInfo; + #define VK_VERSION_1_0 1 GLAD_API_CALL int GLAD_VK_VERSION_1_0; #define VK_VERSION_1_1 1 GLAD_API_CALL int GLAD_VK_VERSION_1_1; +#define VK_VERSION_1_2 1 +GLAD_API_CALL int GLAD_VK_VERSION_1_2; +#define VK_VERSION_1_3 1 +GLAD_API_CALL int GLAD_VK_VERSION_1_3; #define VK_EXT_debug_report 1 GLAD_API_CALL int GLAD_VK_EXT_debug_report; +#define VK_KHR_portability_enumeration 1 +GLAD_API_CALL int GLAD_VK_KHR_portability_enumeration; #define VK_KHR_surface 1 GLAD_API_CALL int GLAD_VK_KHR_surface; #define VK_KHR_swapchain 1 @@ -3437,18 +4891,26 @@ typedef VkResult (GLAD_API_PTR *PFN_vkBindImageMemory)(VkDevice device, VkImage typedef VkResult (GLAD_API_PTR *PFN_vkBindImageMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo * pBindInfos); typedef void (GLAD_API_PTR *PFN_vkCmdBeginQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags); typedef void (GLAD_API_PTR *PFN_vkCmdBeginRenderPass)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo * pRenderPassBegin, VkSubpassContents contents); +typedef void (GLAD_API_PTR *PFN_vkCmdBeginRenderPass2)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo * pRenderPassBegin, const VkSubpassBeginInfo * pSubpassBeginInfo); +typedef void (GLAD_API_PTR *PFN_vkCmdBeginRendering)(VkCommandBuffer commandBuffer, const VkRenderingInfo * pRenderingInfo); typedef void (GLAD_API_PTR *PFN_vkCmdBindDescriptorSets)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet * pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t * pDynamicOffsets); typedef void (GLAD_API_PTR *PFN_vkCmdBindIndexBuffer)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType); typedef void (GLAD_API_PTR *PFN_vkCmdBindPipeline)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline); typedef void (GLAD_API_PTR *PFN_vkCmdBindVertexBuffers)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer * pBuffers, const VkDeviceSize * pOffsets); +typedef void (GLAD_API_PTR *PFN_vkCmdBindVertexBuffers2)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer * pBuffers, const VkDeviceSize * pOffsets, const VkDeviceSize * pSizes, const VkDeviceSize * pStrides); typedef void (GLAD_API_PTR *PFN_vkCmdBlitImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit * pRegions, VkFilter filter); +typedef void (GLAD_API_PTR *PFN_vkCmdBlitImage2)(VkCommandBuffer commandBuffer, const VkBlitImageInfo2 * pBlitImageInfo); typedef void (GLAD_API_PTR *PFN_vkCmdClearAttachments)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkClearAttachment * pAttachments, uint32_t rectCount, const VkClearRect * pRects); typedef void (GLAD_API_PTR *PFN_vkCmdClearColorImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue * pColor, uint32_t rangeCount, const VkImageSubresourceRange * pRanges); typedef void (GLAD_API_PTR *PFN_vkCmdClearDepthStencilImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue * pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange * pRanges); typedef void (GLAD_API_PTR *PFN_vkCmdCopyBuffer)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy * pRegions); +typedef void (GLAD_API_PTR *PFN_vkCmdCopyBuffer2)(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2 * pCopyBufferInfo); typedef void (GLAD_API_PTR *PFN_vkCmdCopyBufferToImage)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy * pRegions); +typedef void (GLAD_API_PTR *PFN_vkCmdCopyBufferToImage2)(VkCommandBuffer commandBuffer, const VkCopyBufferToImageInfo2 * pCopyBufferToImageInfo); typedef void (GLAD_API_PTR *PFN_vkCmdCopyImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy * pRegions); +typedef void (GLAD_API_PTR *PFN_vkCmdCopyImage2)(VkCommandBuffer commandBuffer, const VkCopyImageInfo2 * pCopyImageInfo); typedef void (GLAD_API_PTR *PFN_vkCmdCopyImageToBuffer)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy * pRegions); +typedef void (GLAD_API_PTR *PFN_vkCmdCopyImageToBuffer2)(VkCommandBuffer commandBuffer, const VkCopyImageToBufferInfo2 * pCopyImageToBufferInfo); typedef void (GLAD_API_PTR *PFN_vkCmdCopyQueryPoolResults)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags); typedef void (GLAD_API_PTR *PFN_vkCmdDispatch)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); typedef void (GLAD_API_PTR *PFN_vkCmdDispatchBase)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); @@ -3456,31 +4918,56 @@ typedef void (GLAD_API_PTR *PFN_vkCmdDispatchIndirect)(VkCommandBuffer commandBu typedef void (GLAD_API_PTR *PFN_vkCmdDraw)(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance); typedef void (GLAD_API_PTR *PFN_vkCmdDrawIndexed)(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance); typedef void (GLAD_API_PTR *PFN_vkCmdDrawIndexedIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +typedef void (GLAD_API_PTR *PFN_vkCmdDrawIndexedIndirectCount)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); typedef void (GLAD_API_PTR *PFN_vkCmdDrawIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride); +typedef void (GLAD_API_PTR *PFN_vkCmdDrawIndirectCount)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride); typedef void (GLAD_API_PTR *PFN_vkCmdEndQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query); typedef void (GLAD_API_PTR *PFN_vkCmdEndRenderPass)(VkCommandBuffer commandBuffer); +typedef void (GLAD_API_PTR *PFN_vkCmdEndRenderPass2)(VkCommandBuffer commandBuffer, const VkSubpassEndInfo * pSubpassEndInfo); +typedef void (GLAD_API_PTR *PFN_vkCmdEndRendering)(VkCommandBuffer commandBuffer); typedef void (GLAD_API_PTR *PFN_vkCmdExecuteCommands)(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer * pCommandBuffers); typedef void (GLAD_API_PTR *PFN_vkCmdFillBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data); typedef void (GLAD_API_PTR *PFN_vkCmdNextSubpass)(VkCommandBuffer commandBuffer, VkSubpassContents contents); +typedef void (GLAD_API_PTR *PFN_vkCmdNextSubpass2)(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo * pSubpassBeginInfo, const VkSubpassEndInfo * pSubpassEndInfo); typedef void (GLAD_API_PTR *PFN_vkCmdPipelineBarrier)(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier * pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier * pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier * pImageMemoryBarriers); +typedef void (GLAD_API_PTR *PFN_vkCmdPipelineBarrier2)(VkCommandBuffer commandBuffer, const VkDependencyInfo * pDependencyInfo); typedef void (GLAD_API_PTR *PFN_vkCmdPushConstants)(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void * pValues); typedef void (GLAD_API_PTR *PFN_vkCmdResetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask); +typedef void (GLAD_API_PTR *PFN_vkCmdResetEvent2)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2 stageMask); typedef void (GLAD_API_PTR *PFN_vkCmdResetQueryPool)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); typedef void (GLAD_API_PTR *PFN_vkCmdResolveImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve * pRegions); +typedef void (GLAD_API_PTR *PFN_vkCmdResolveImage2)(VkCommandBuffer commandBuffer, const VkResolveImageInfo2 * pResolveImageInfo); typedef void (GLAD_API_PTR *PFN_vkCmdSetBlendConstants)(VkCommandBuffer commandBuffer, const float blendConstants [4]); +typedef void (GLAD_API_PTR *PFN_vkCmdSetCullMode)(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode); typedef void (GLAD_API_PTR *PFN_vkCmdSetDepthBias)(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor); +typedef void (GLAD_API_PTR *PFN_vkCmdSetDepthBiasEnable)(VkCommandBuffer commandBuffer, VkBool32 depthBiasEnable); typedef void (GLAD_API_PTR *PFN_vkCmdSetDepthBounds)(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds); +typedef void (GLAD_API_PTR *PFN_vkCmdSetDepthBoundsTestEnable)(VkCommandBuffer commandBuffer, VkBool32 depthBoundsTestEnable); +typedef void (GLAD_API_PTR *PFN_vkCmdSetDepthCompareOp)(VkCommandBuffer commandBuffer, VkCompareOp depthCompareOp); +typedef void (GLAD_API_PTR *PFN_vkCmdSetDepthTestEnable)(VkCommandBuffer commandBuffer, VkBool32 depthTestEnable); +typedef void (GLAD_API_PTR *PFN_vkCmdSetDepthWriteEnable)(VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable); typedef void (GLAD_API_PTR *PFN_vkCmdSetDeviceMask)(VkCommandBuffer commandBuffer, uint32_t deviceMask); typedef void (GLAD_API_PTR *PFN_vkCmdSetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask); +typedef void (GLAD_API_PTR *PFN_vkCmdSetEvent2)(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfo * pDependencyInfo); +typedef void (GLAD_API_PTR *PFN_vkCmdSetFrontFace)(VkCommandBuffer commandBuffer, VkFrontFace frontFace); typedef void (GLAD_API_PTR *PFN_vkCmdSetLineWidth)(VkCommandBuffer commandBuffer, float lineWidth); +typedef void (GLAD_API_PTR *PFN_vkCmdSetPrimitiveRestartEnable)(VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable); +typedef void (GLAD_API_PTR *PFN_vkCmdSetPrimitiveTopology)(VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology); +typedef void (GLAD_API_PTR *PFN_vkCmdSetRasterizerDiscardEnable)(VkCommandBuffer commandBuffer, VkBool32 rasterizerDiscardEnable); typedef void (GLAD_API_PTR *PFN_vkCmdSetScissor)(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D * pScissors); +typedef void (GLAD_API_PTR *PFN_vkCmdSetScissorWithCount)(VkCommandBuffer commandBuffer, uint32_t scissorCount, const VkRect2D * pScissors); typedef void (GLAD_API_PTR *PFN_vkCmdSetStencilCompareMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask); +typedef void (GLAD_API_PTR *PFN_vkCmdSetStencilOp)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp); typedef void (GLAD_API_PTR *PFN_vkCmdSetStencilReference)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference); +typedef void (GLAD_API_PTR *PFN_vkCmdSetStencilTestEnable)(VkCommandBuffer commandBuffer, VkBool32 stencilTestEnable); typedef void (GLAD_API_PTR *PFN_vkCmdSetStencilWriteMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask); typedef void (GLAD_API_PTR *PFN_vkCmdSetViewport)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport * pViewports); +typedef void (GLAD_API_PTR *PFN_vkCmdSetViewportWithCount)(VkCommandBuffer commandBuffer, uint32_t viewportCount, const VkViewport * pViewports); typedef void (GLAD_API_PTR *PFN_vkCmdUpdateBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void * pData); typedef void (GLAD_API_PTR *PFN_vkCmdWaitEvents)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent * pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier * pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier * pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier * pImageMemoryBarriers); +typedef void (GLAD_API_PTR *PFN_vkCmdWaitEvents2)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent * pEvents, const VkDependencyInfo * pDependencyInfos); typedef void (GLAD_API_PTR *PFN_vkCmdWriteTimestamp)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query); +typedef void (GLAD_API_PTR *PFN_vkCmdWriteTimestamp2)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkQueryPool queryPool, uint32_t query); typedef VkResult (GLAD_API_PTR *PFN_vkCreateBuffer)(VkDevice device, const VkBufferCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkBuffer * pBuffer); typedef VkResult (GLAD_API_PTR *PFN_vkCreateBufferView)(VkDevice device, const VkBufferViewCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkBufferView * pView); typedef VkResult (GLAD_API_PTR *PFN_vkCreateCommandPool)(VkDevice device, const VkCommandPoolCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkCommandPool * pCommandPool); @@ -3499,8 +4986,10 @@ typedef VkResult (GLAD_API_PTR *PFN_vkCreateImageView)(VkDevice device, const Vk typedef VkResult (GLAD_API_PTR *PFN_vkCreateInstance)(const VkInstanceCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkInstance * pInstance); typedef VkResult (GLAD_API_PTR *PFN_vkCreatePipelineCache)(VkDevice device, const VkPipelineCacheCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkPipelineCache * pPipelineCache); typedef VkResult (GLAD_API_PTR *PFN_vkCreatePipelineLayout)(VkDevice device, const VkPipelineLayoutCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkPipelineLayout * pPipelineLayout); +typedef VkResult (GLAD_API_PTR *PFN_vkCreatePrivateDataSlot)(VkDevice device, const VkPrivateDataSlotCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkPrivateDataSlot * pPrivateDataSlot); typedef VkResult (GLAD_API_PTR *PFN_vkCreateQueryPool)(VkDevice device, const VkQueryPoolCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkQueryPool * pQueryPool); typedef VkResult (GLAD_API_PTR *PFN_vkCreateRenderPass)(VkDevice device, const VkRenderPassCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkRenderPass * pRenderPass); +typedef VkResult (GLAD_API_PTR *PFN_vkCreateRenderPass2)(VkDevice device, const VkRenderPassCreateInfo2 * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkRenderPass * pRenderPass); typedef VkResult (GLAD_API_PTR *PFN_vkCreateSampler)(VkDevice device, const VkSamplerCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkSampler * pSampler); typedef VkResult (GLAD_API_PTR *PFN_vkCreateSamplerYcbcrConversion)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkSamplerYcbcrConversion * pYcbcrConversion); typedef VkResult (GLAD_API_PTR *PFN_vkCreateSemaphore)(VkDevice device, const VkSemaphoreCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkSemaphore * pSemaphore); @@ -3524,6 +5013,7 @@ typedef void (GLAD_API_PTR *PFN_vkDestroyInstance)(VkInstance instance, const Vk typedef void (GLAD_API_PTR *PFN_vkDestroyPipeline)(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks * pAllocator); typedef void (GLAD_API_PTR *PFN_vkDestroyPipelineCache)(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks * pAllocator); typedef void (GLAD_API_PTR *PFN_vkDestroyPipelineLayout)(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks * pAllocator); +typedef void (GLAD_API_PTR *PFN_vkDestroyPrivateDataSlot)(VkDevice device, VkPrivateDataSlot privateDataSlot, const VkAllocationCallbacks * pAllocator); typedef void (GLAD_API_PTR *PFN_vkDestroyQueryPool)(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks * pAllocator); typedef void (GLAD_API_PTR *PFN_vkDestroyRenderPass)(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks * pAllocator); typedef void (GLAD_API_PTR *PFN_vkDestroySampler)(VkDevice device, VkSampler sampler, const VkAllocationCallbacks * pAllocator); @@ -3545,13 +5035,19 @@ typedef VkResult (GLAD_API_PTR *PFN_vkFlushMappedMemoryRanges)(VkDevice device, typedef void (GLAD_API_PTR *PFN_vkFreeCommandBuffers)(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer * pCommandBuffers); typedef VkResult (GLAD_API_PTR *PFN_vkFreeDescriptorSets)(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet * pDescriptorSets); typedef void (GLAD_API_PTR *PFN_vkFreeMemory)(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks * pAllocator); +typedef VkDeviceAddress (GLAD_API_PTR *PFN_vkGetBufferDeviceAddress)(VkDevice device, const VkBufferDeviceAddressInfo * pInfo); typedef void (GLAD_API_PTR *PFN_vkGetBufferMemoryRequirements)(VkDevice device, VkBuffer buffer, VkMemoryRequirements * pMemoryRequirements); typedef void (GLAD_API_PTR *PFN_vkGetBufferMemoryRequirements2)(VkDevice device, const VkBufferMemoryRequirementsInfo2 * pInfo, VkMemoryRequirements2 * pMemoryRequirements); +typedef uint64_t (GLAD_API_PTR *PFN_vkGetBufferOpaqueCaptureAddress)(VkDevice device, const VkBufferDeviceAddressInfo * pInfo); typedef void (GLAD_API_PTR *PFN_vkGetDescriptorSetLayoutSupport)(VkDevice device, const VkDescriptorSetLayoutCreateInfo * pCreateInfo, VkDescriptorSetLayoutSupport * pSupport); +typedef void (GLAD_API_PTR *PFN_vkGetDeviceBufferMemoryRequirements)(VkDevice device, const VkDeviceBufferMemoryRequirements * pInfo, VkMemoryRequirements2 * pMemoryRequirements); typedef void (GLAD_API_PTR *PFN_vkGetDeviceGroupPeerMemoryFeatures)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags * pPeerMemoryFeatures); typedef VkResult (GLAD_API_PTR *PFN_vkGetDeviceGroupPresentCapabilitiesKHR)(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR * pDeviceGroupPresentCapabilities); typedef VkResult (GLAD_API_PTR *PFN_vkGetDeviceGroupSurfacePresentModesKHR)(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR * pModes); +typedef void (GLAD_API_PTR *PFN_vkGetDeviceImageMemoryRequirements)(VkDevice device, const VkDeviceImageMemoryRequirements * pInfo, VkMemoryRequirements2 * pMemoryRequirements); +typedef void (GLAD_API_PTR *PFN_vkGetDeviceImageSparseMemoryRequirements)(VkDevice device, const VkDeviceImageMemoryRequirements * pInfo, uint32_t * pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements); typedef void (GLAD_API_PTR *PFN_vkGetDeviceMemoryCommitment)(VkDevice device, VkDeviceMemory memory, VkDeviceSize * pCommittedMemoryInBytes); +typedef uint64_t (GLAD_API_PTR *PFN_vkGetDeviceMemoryOpaqueCaptureAddress)(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo * pInfo); typedef PFN_vkVoidFunction (GLAD_API_PTR *PFN_vkGetDeviceProcAddr)(VkDevice device, const char * pName); typedef void (GLAD_API_PTR *PFN_vkGetDeviceQueue)(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue * pQueue); typedef void (GLAD_API_PTR *PFN_vkGetDeviceQueue2)(VkDevice device, const VkDeviceQueueInfo2 * pQueueInfo, VkQueue * pQueue); @@ -3585,9 +5081,12 @@ typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(V typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t * pSurfaceFormatCount, VkSurfaceFormatKHR * pSurfaceFormats); typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t * pPresentModeCount, VkPresentModeKHR * pPresentModes); typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32 * pSupported); +typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceToolProperties)(VkPhysicalDevice physicalDevice, uint32_t * pToolCount, VkPhysicalDeviceToolProperties * pToolProperties); typedef VkResult (GLAD_API_PTR *PFN_vkGetPipelineCacheData)(VkDevice device, VkPipelineCache pipelineCache, size_t * pDataSize, void * pData); +typedef void (GLAD_API_PTR *PFN_vkGetPrivateData)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t * pData); typedef VkResult (GLAD_API_PTR *PFN_vkGetQueryPoolResults)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void * pData, VkDeviceSize stride, VkQueryResultFlags flags); typedef void (GLAD_API_PTR *PFN_vkGetRenderAreaGranularity)(VkDevice device, VkRenderPass renderPass, VkExtent2D * pGranularity); +typedef VkResult (GLAD_API_PTR *PFN_vkGetSemaphoreCounterValue)(VkDevice device, VkSemaphore semaphore, uint64_t * pValue); typedef VkResult (GLAD_API_PTR *PFN_vkGetSwapchainImagesKHR)(VkDevice device, VkSwapchainKHR swapchain, uint32_t * pSwapchainImageCount, VkImage * pSwapchainImages); typedef VkResult (GLAD_API_PTR *PFN_vkInvalidateMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange * pMemoryRanges); typedef VkResult (GLAD_API_PTR *PFN_vkMapMemory)(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void ** ppData); @@ -3595,18 +5094,23 @@ typedef VkResult (GLAD_API_PTR *PFN_vkMergePipelineCaches)(VkDevice device, VkPi typedef VkResult (GLAD_API_PTR *PFN_vkQueueBindSparse)(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo * pBindInfo, VkFence fence); typedef VkResult (GLAD_API_PTR *PFN_vkQueuePresentKHR)(VkQueue queue, const VkPresentInfoKHR * pPresentInfo); typedef VkResult (GLAD_API_PTR *PFN_vkQueueSubmit)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo * pSubmits, VkFence fence); +typedef VkResult (GLAD_API_PTR *PFN_vkQueueSubmit2)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2 * pSubmits, VkFence fence); typedef VkResult (GLAD_API_PTR *PFN_vkQueueWaitIdle)(VkQueue queue); typedef VkResult (GLAD_API_PTR *PFN_vkResetCommandBuffer)(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags); typedef VkResult (GLAD_API_PTR *PFN_vkResetCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags); typedef VkResult (GLAD_API_PTR *PFN_vkResetDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags); typedef VkResult (GLAD_API_PTR *PFN_vkResetEvent)(VkDevice device, VkEvent event); typedef VkResult (GLAD_API_PTR *PFN_vkResetFences)(VkDevice device, uint32_t fenceCount, const VkFence * pFences); +typedef void (GLAD_API_PTR *PFN_vkResetQueryPool)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); typedef VkResult (GLAD_API_PTR *PFN_vkSetEvent)(VkDevice device, VkEvent event); +typedef VkResult (GLAD_API_PTR *PFN_vkSetPrivateData)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t data); +typedef VkResult (GLAD_API_PTR *PFN_vkSignalSemaphore)(VkDevice device, const VkSemaphoreSignalInfo * pSignalInfo); typedef void (GLAD_API_PTR *PFN_vkTrimCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags); typedef void (GLAD_API_PTR *PFN_vkUnmapMemory)(VkDevice device, VkDeviceMemory memory); typedef void (GLAD_API_PTR *PFN_vkUpdateDescriptorSetWithTemplate)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void * pData); typedef void (GLAD_API_PTR *PFN_vkUpdateDescriptorSets)(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet * pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet * pDescriptorCopies); typedef VkResult (GLAD_API_PTR *PFN_vkWaitForFences)(VkDevice device, uint32_t fenceCount, const VkFence * pFences, VkBool32 waitAll, uint64_t timeout); +typedef VkResult (GLAD_API_PTR *PFN_vkWaitSemaphores)(VkDevice device, const VkSemaphoreWaitInfo * pWaitInfo, uint64_t timeout); GLAD_API_CALL PFN_vkAcquireNextImage2KHR glad_vkAcquireNextImage2KHR; #define vkAcquireNextImage2KHR glad_vkAcquireNextImage2KHR @@ -3632,6 +5136,10 @@ GLAD_API_CALL PFN_vkCmdBeginQuery glad_vkCmdBeginQuery; #define vkCmdBeginQuery glad_vkCmdBeginQuery GLAD_API_CALL PFN_vkCmdBeginRenderPass glad_vkCmdBeginRenderPass; #define vkCmdBeginRenderPass glad_vkCmdBeginRenderPass +GLAD_API_CALL PFN_vkCmdBeginRenderPass2 glad_vkCmdBeginRenderPass2; +#define vkCmdBeginRenderPass2 glad_vkCmdBeginRenderPass2 +GLAD_API_CALL PFN_vkCmdBeginRendering glad_vkCmdBeginRendering; +#define vkCmdBeginRendering glad_vkCmdBeginRendering GLAD_API_CALL PFN_vkCmdBindDescriptorSets glad_vkCmdBindDescriptorSets; #define vkCmdBindDescriptorSets glad_vkCmdBindDescriptorSets GLAD_API_CALL PFN_vkCmdBindIndexBuffer glad_vkCmdBindIndexBuffer; @@ -3640,8 +5148,12 @@ GLAD_API_CALL PFN_vkCmdBindPipeline glad_vkCmdBindPipeline; #define vkCmdBindPipeline glad_vkCmdBindPipeline GLAD_API_CALL PFN_vkCmdBindVertexBuffers glad_vkCmdBindVertexBuffers; #define vkCmdBindVertexBuffers glad_vkCmdBindVertexBuffers +GLAD_API_CALL PFN_vkCmdBindVertexBuffers2 glad_vkCmdBindVertexBuffers2; +#define vkCmdBindVertexBuffers2 glad_vkCmdBindVertexBuffers2 GLAD_API_CALL PFN_vkCmdBlitImage glad_vkCmdBlitImage; #define vkCmdBlitImage glad_vkCmdBlitImage +GLAD_API_CALL PFN_vkCmdBlitImage2 glad_vkCmdBlitImage2; +#define vkCmdBlitImage2 glad_vkCmdBlitImage2 GLAD_API_CALL PFN_vkCmdClearAttachments glad_vkCmdClearAttachments; #define vkCmdClearAttachments glad_vkCmdClearAttachments GLAD_API_CALL PFN_vkCmdClearColorImage glad_vkCmdClearColorImage; @@ -3650,12 +5162,20 @@ GLAD_API_CALL PFN_vkCmdClearDepthStencilImage glad_vkCmdClearDepthStencilImage; #define vkCmdClearDepthStencilImage glad_vkCmdClearDepthStencilImage GLAD_API_CALL PFN_vkCmdCopyBuffer glad_vkCmdCopyBuffer; #define vkCmdCopyBuffer glad_vkCmdCopyBuffer +GLAD_API_CALL PFN_vkCmdCopyBuffer2 glad_vkCmdCopyBuffer2; +#define vkCmdCopyBuffer2 glad_vkCmdCopyBuffer2 GLAD_API_CALL PFN_vkCmdCopyBufferToImage glad_vkCmdCopyBufferToImage; #define vkCmdCopyBufferToImage glad_vkCmdCopyBufferToImage +GLAD_API_CALL PFN_vkCmdCopyBufferToImage2 glad_vkCmdCopyBufferToImage2; +#define vkCmdCopyBufferToImage2 glad_vkCmdCopyBufferToImage2 GLAD_API_CALL PFN_vkCmdCopyImage glad_vkCmdCopyImage; #define vkCmdCopyImage glad_vkCmdCopyImage +GLAD_API_CALL PFN_vkCmdCopyImage2 glad_vkCmdCopyImage2; +#define vkCmdCopyImage2 glad_vkCmdCopyImage2 GLAD_API_CALL PFN_vkCmdCopyImageToBuffer glad_vkCmdCopyImageToBuffer; #define vkCmdCopyImageToBuffer glad_vkCmdCopyImageToBuffer +GLAD_API_CALL PFN_vkCmdCopyImageToBuffer2 glad_vkCmdCopyImageToBuffer2; +#define vkCmdCopyImageToBuffer2 glad_vkCmdCopyImageToBuffer2 GLAD_API_CALL PFN_vkCmdCopyQueryPoolResults glad_vkCmdCopyQueryPoolResults; #define vkCmdCopyQueryPoolResults glad_vkCmdCopyQueryPoolResults GLAD_API_CALL PFN_vkCmdDispatch glad_vkCmdDispatch; @@ -3670,56 +5190,106 @@ GLAD_API_CALL PFN_vkCmdDrawIndexed glad_vkCmdDrawIndexed; #define vkCmdDrawIndexed glad_vkCmdDrawIndexed GLAD_API_CALL PFN_vkCmdDrawIndexedIndirect glad_vkCmdDrawIndexedIndirect; #define vkCmdDrawIndexedIndirect glad_vkCmdDrawIndexedIndirect +GLAD_API_CALL PFN_vkCmdDrawIndexedIndirectCount glad_vkCmdDrawIndexedIndirectCount; +#define vkCmdDrawIndexedIndirectCount glad_vkCmdDrawIndexedIndirectCount GLAD_API_CALL PFN_vkCmdDrawIndirect glad_vkCmdDrawIndirect; #define vkCmdDrawIndirect glad_vkCmdDrawIndirect +GLAD_API_CALL PFN_vkCmdDrawIndirectCount glad_vkCmdDrawIndirectCount; +#define vkCmdDrawIndirectCount glad_vkCmdDrawIndirectCount GLAD_API_CALL PFN_vkCmdEndQuery glad_vkCmdEndQuery; #define vkCmdEndQuery glad_vkCmdEndQuery GLAD_API_CALL PFN_vkCmdEndRenderPass glad_vkCmdEndRenderPass; #define vkCmdEndRenderPass glad_vkCmdEndRenderPass +GLAD_API_CALL PFN_vkCmdEndRenderPass2 glad_vkCmdEndRenderPass2; +#define vkCmdEndRenderPass2 glad_vkCmdEndRenderPass2 +GLAD_API_CALL PFN_vkCmdEndRendering glad_vkCmdEndRendering; +#define vkCmdEndRendering glad_vkCmdEndRendering GLAD_API_CALL PFN_vkCmdExecuteCommands glad_vkCmdExecuteCommands; #define vkCmdExecuteCommands glad_vkCmdExecuteCommands GLAD_API_CALL PFN_vkCmdFillBuffer glad_vkCmdFillBuffer; #define vkCmdFillBuffer glad_vkCmdFillBuffer GLAD_API_CALL PFN_vkCmdNextSubpass glad_vkCmdNextSubpass; #define vkCmdNextSubpass glad_vkCmdNextSubpass +GLAD_API_CALL PFN_vkCmdNextSubpass2 glad_vkCmdNextSubpass2; +#define vkCmdNextSubpass2 glad_vkCmdNextSubpass2 GLAD_API_CALL PFN_vkCmdPipelineBarrier glad_vkCmdPipelineBarrier; #define vkCmdPipelineBarrier glad_vkCmdPipelineBarrier +GLAD_API_CALL PFN_vkCmdPipelineBarrier2 glad_vkCmdPipelineBarrier2; +#define vkCmdPipelineBarrier2 glad_vkCmdPipelineBarrier2 GLAD_API_CALL PFN_vkCmdPushConstants glad_vkCmdPushConstants; #define vkCmdPushConstants glad_vkCmdPushConstants GLAD_API_CALL PFN_vkCmdResetEvent glad_vkCmdResetEvent; #define vkCmdResetEvent glad_vkCmdResetEvent +GLAD_API_CALL PFN_vkCmdResetEvent2 glad_vkCmdResetEvent2; +#define vkCmdResetEvent2 glad_vkCmdResetEvent2 GLAD_API_CALL PFN_vkCmdResetQueryPool glad_vkCmdResetQueryPool; #define vkCmdResetQueryPool glad_vkCmdResetQueryPool GLAD_API_CALL PFN_vkCmdResolveImage glad_vkCmdResolveImage; #define vkCmdResolveImage glad_vkCmdResolveImage +GLAD_API_CALL PFN_vkCmdResolveImage2 glad_vkCmdResolveImage2; +#define vkCmdResolveImage2 glad_vkCmdResolveImage2 GLAD_API_CALL PFN_vkCmdSetBlendConstants glad_vkCmdSetBlendConstants; #define vkCmdSetBlendConstants glad_vkCmdSetBlendConstants +GLAD_API_CALL PFN_vkCmdSetCullMode glad_vkCmdSetCullMode; +#define vkCmdSetCullMode glad_vkCmdSetCullMode GLAD_API_CALL PFN_vkCmdSetDepthBias glad_vkCmdSetDepthBias; #define vkCmdSetDepthBias glad_vkCmdSetDepthBias +GLAD_API_CALL PFN_vkCmdSetDepthBiasEnable glad_vkCmdSetDepthBiasEnable; +#define vkCmdSetDepthBiasEnable glad_vkCmdSetDepthBiasEnable GLAD_API_CALL PFN_vkCmdSetDepthBounds glad_vkCmdSetDepthBounds; #define vkCmdSetDepthBounds glad_vkCmdSetDepthBounds +GLAD_API_CALL PFN_vkCmdSetDepthBoundsTestEnable glad_vkCmdSetDepthBoundsTestEnable; +#define vkCmdSetDepthBoundsTestEnable glad_vkCmdSetDepthBoundsTestEnable +GLAD_API_CALL PFN_vkCmdSetDepthCompareOp glad_vkCmdSetDepthCompareOp; +#define vkCmdSetDepthCompareOp glad_vkCmdSetDepthCompareOp +GLAD_API_CALL PFN_vkCmdSetDepthTestEnable glad_vkCmdSetDepthTestEnable; +#define vkCmdSetDepthTestEnable glad_vkCmdSetDepthTestEnable +GLAD_API_CALL PFN_vkCmdSetDepthWriteEnable glad_vkCmdSetDepthWriteEnable; +#define vkCmdSetDepthWriteEnable glad_vkCmdSetDepthWriteEnable GLAD_API_CALL PFN_vkCmdSetDeviceMask glad_vkCmdSetDeviceMask; #define vkCmdSetDeviceMask glad_vkCmdSetDeviceMask GLAD_API_CALL PFN_vkCmdSetEvent glad_vkCmdSetEvent; #define vkCmdSetEvent glad_vkCmdSetEvent +GLAD_API_CALL PFN_vkCmdSetEvent2 glad_vkCmdSetEvent2; +#define vkCmdSetEvent2 glad_vkCmdSetEvent2 +GLAD_API_CALL PFN_vkCmdSetFrontFace glad_vkCmdSetFrontFace; +#define vkCmdSetFrontFace glad_vkCmdSetFrontFace GLAD_API_CALL PFN_vkCmdSetLineWidth glad_vkCmdSetLineWidth; #define vkCmdSetLineWidth glad_vkCmdSetLineWidth +GLAD_API_CALL PFN_vkCmdSetPrimitiveRestartEnable glad_vkCmdSetPrimitiveRestartEnable; +#define vkCmdSetPrimitiveRestartEnable glad_vkCmdSetPrimitiveRestartEnable +GLAD_API_CALL PFN_vkCmdSetPrimitiveTopology glad_vkCmdSetPrimitiveTopology; +#define vkCmdSetPrimitiveTopology glad_vkCmdSetPrimitiveTopology +GLAD_API_CALL PFN_vkCmdSetRasterizerDiscardEnable glad_vkCmdSetRasterizerDiscardEnable; +#define vkCmdSetRasterizerDiscardEnable glad_vkCmdSetRasterizerDiscardEnable GLAD_API_CALL PFN_vkCmdSetScissor glad_vkCmdSetScissor; #define vkCmdSetScissor glad_vkCmdSetScissor +GLAD_API_CALL PFN_vkCmdSetScissorWithCount glad_vkCmdSetScissorWithCount; +#define vkCmdSetScissorWithCount glad_vkCmdSetScissorWithCount GLAD_API_CALL PFN_vkCmdSetStencilCompareMask glad_vkCmdSetStencilCompareMask; #define vkCmdSetStencilCompareMask glad_vkCmdSetStencilCompareMask +GLAD_API_CALL PFN_vkCmdSetStencilOp glad_vkCmdSetStencilOp; +#define vkCmdSetStencilOp glad_vkCmdSetStencilOp GLAD_API_CALL PFN_vkCmdSetStencilReference glad_vkCmdSetStencilReference; #define vkCmdSetStencilReference glad_vkCmdSetStencilReference +GLAD_API_CALL PFN_vkCmdSetStencilTestEnable glad_vkCmdSetStencilTestEnable; +#define vkCmdSetStencilTestEnable glad_vkCmdSetStencilTestEnable GLAD_API_CALL PFN_vkCmdSetStencilWriteMask glad_vkCmdSetStencilWriteMask; #define vkCmdSetStencilWriteMask glad_vkCmdSetStencilWriteMask GLAD_API_CALL PFN_vkCmdSetViewport glad_vkCmdSetViewport; #define vkCmdSetViewport glad_vkCmdSetViewport +GLAD_API_CALL PFN_vkCmdSetViewportWithCount glad_vkCmdSetViewportWithCount; +#define vkCmdSetViewportWithCount glad_vkCmdSetViewportWithCount GLAD_API_CALL PFN_vkCmdUpdateBuffer glad_vkCmdUpdateBuffer; #define vkCmdUpdateBuffer glad_vkCmdUpdateBuffer GLAD_API_CALL PFN_vkCmdWaitEvents glad_vkCmdWaitEvents; #define vkCmdWaitEvents glad_vkCmdWaitEvents +GLAD_API_CALL PFN_vkCmdWaitEvents2 glad_vkCmdWaitEvents2; +#define vkCmdWaitEvents2 glad_vkCmdWaitEvents2 GLAD_API_CALL PFN_vkCmdWriteTimestamp glad_vkCmdWriteTimestamp; #define vkCmdWriteTimestamp glad_vkCmdWriteTimestamp +GLAD_API_CALL PFN_vkCmdWriteTimestamp2 glad_vkCmdWriteTimestamp2; +#define vkCmdWriteTimestamp2 glad_vkCmdWriteTimestamp2 GLAD_API_CALL PFN_vkCreateBuffer glad_vkCreateBuffer; #define vkCreateBuffer glad_vkCreateBuffer GLAD_API_CALL PFN_vkCreateBufferView glad_vkCreateBufferView; @@ -3756,10 +5326,14 @@ GLAD_API_CALL PFN_vkCreatePipelineCache glad_vkCreatePipelineCache; #define vkCreatePipelineCache glad_vkCreatePipelineCache GLAD_API_CALL PFN_vkCreatePipelineLayout glad_vkCreatePipelineLayout; #define vkCreatePipelineLayout glad_vkCreatePipelineLayout +GLAD_API_CALL PFN_vkCreatePrivateDataSlot glad_vkCreatePrivateDataSlot; +#define vkCreatePrivateDataSlot glad_vkCreatePrivateDataSlot GLAD_API_CALL PFN_vkCreateQueryPool glad_vkCreateQueryPool; #define vkCreateQueryPool glad_vkCreateQueryPool GLAD_API_CALL PFN_vkCreateRenderPass glad_vkCreateRenderPass; #define vkCreateRenderPass glad_vkCreateRenderPass +GLAD_API_CALL PFN_vkCreateRenderPass2 glad_vkCreateRenderPass2; +#define vkCreateRenderPass2 glad_vkCreateRenderPass2 GLAD_API_CALL PFN_vkCreateSampler glad_vkCreateSampler; #define vkCreateSampler glad_vkCreateSampler GLAD_API_CALL PFN_vkCreateSamplerYcbcrConversion glad_vkCreateSamplerYcbcrConversion; @@ -3806,6 +5380,8 @@ GLAD_API_CALL PFN_vkDestroyPipelineCache glad_vkDestroyPipelineCache; #define vkDestroyPipelineCache glad_vkDestroyPipelineCache GLAD_API_CALL PFN_vkDestroyPipelineLayout glad_vkDestroyPipelineLayout; #define vkDestroyPipelineLayout glad_vkDestroyPipelineLayout +GLAD_API_CALL PFN_vkDestroyPrivateDataSlot glad_vkDestroyPrivateDataSlot; +#define vkDestroyPrivateDataSlot glad_vkDestroyPrivateDataSlot GLAD_API_CALL PFN_vkDestroyQueryPool glad_vkDestroyQueryPool; #define vkDestroyQueryPool glad_vkDestroyQueryPool GLAD_API_CALL PFN_vkDestroyRenderPass glad_vkDestroyRenderPass; @@ -3848,20 +5424,32 @@ GLAD_API_CALL PFN_vkFreeDescriptorSets glad_vkFreeDescriptorSets; #define vkFreeDescriptorSets glad_vkFreeDescriptorSets GLAD_API_CALL PFN_vkFreeMemory glad_vkFreeMemory; #define vkFreeMemory glad_vkFreeMemory +GLAD_API_CALL PFN_vkGetBufferDeviceAddress glad_vkGetBufferDeviceAddress; +#define vkGetBufferDeviceAddress glad_vkGetBufferDeviceAddress GLAD_API_CALL PFN_vkGetBufferMemoryRequirements glad_vkGetBufferMemoryRequirements; #define vkGetBufferMemoryRequirements glad_vkGetBufferMemoryRequirements GLAD_API_CALL PFN_vkGetBufferMemoryRequirements2 glad_vkGetBufferMemoryRequirements2; #define vkGetBufferMemoryRequirements2 glad_vkGetBufferMemoryRequirements2 +GLAD_API_CALL PFN_vkGetBufferOpaqueCaptureAddress glad_vkGetBufferOpaqueCaptureAddress; +#define vkGetBufferOpaqueCaptureAddress glad_vkGetBufferOpaqueCaptureAddress GLAD_API_CALL PFN_vkGetDescriptorSetLayoutSupport glad_vkGetDescriptorSetLayoutSupport; #define vkGetDescriptorSetLayoutSupport glad_vkGetDescriptorSetLayoutSupport +GLAD_API_CALL PFN_vkGetDeviceBufferMemoryRequirements glad_vkGetDeviceBufferMemoryRequirements; +#define vkGetDeviceBufferMemoryRequirements glad_vkGetDeviceBufferMemoryRequirements GLAD_API_CALL PFN_vkGetDeviceGroupPeerMemoryFeatures glad_vkGetDeviceGroupPeerMemoryFeatures; #define vkGetDeviceGroupPeerMemoryFeatures glad_vkGetDeviceGroupPeerMemoryFeatures GLAD_API_CALL PFN_vkGetDeviceGroupPresentCapabilitiesKHR glad_vkGetDeviceGroupPresentCapabilitiesKHR; #define vkGetDeviceGroupPresentCapabilitiesKHR glad_vkGetDeviceGroupPresentCapabilitiesKHR GLAD_API_CALL PFN_vkGetDeviceGroupSurfacePresentModesKHR glad_vkGetDeviceGroupSurfacePresentModesKHR; #define vkGetDeviceGroupSurfacePresentModesKHR glad_vkGetDeviceGroupSurfacePresentModesKHR +GLAD_API_CALL PFN_vkGetDeviceImageMemoryRequirements glad_vkGetDeviceImageMemoryRequirements; +#define vkGetDeviceImageMemoryRequirements glad_vkGetDeviceImageMemoryRequirements +GLAD_API_CALL PFN_vkGetDeviceImageSparseMemoryRequirements glad_vkGetDeviceImageSparseMemoryRequirements; +#define vkGetDeviceImageSparseMemoryRequirements glad_vkGetDeviceImageSparseMemoryRequirements GLAD_API_CALL PFN_vkGetDeviceMemoryCommitment glad_vkGetDeviceMemoryCommitment; #define vkGetDeviceMemoryCommitment glad_vkGetDeviceMemoryCommitment +GLAD_API_CALL PFN_vkGetDeviceMemoryOpaqueCaptureAddress glad_vkGetDeviceMemoryOpaqueCaptureAddress; +#define vkGetDeviceMemoryOpaqueCaptureAddress glad_vkGetDeviceMemoryOpaqueCaptureAddress GLAD_API_CALL PFN_vkGetDeviceProcAddr glad_vkGetDeviceProcAddr; #define vkGetDeviceProcAddr glad_vkGetDeviceProcAddr GLAD_API_CALL PFN_vkGetDeviceQueue glad_vkGetDeviceQueue; @@ -3928,12 +5516,18 @@ GLAD_API_CALL PFN_vkGetPhysicalDeviceSurfacePresentModesKHR glad_vkGetPhysicalDe #define vkGetPhysicalDeviceSurfacePresentModesKHR glad_vkGetPhysicalDeviceSurfacePresentModesKHR GLAD_API_CALL PFN_vkGetPhysicalDeviceSurfaceSupportKHR glad_vkGetPhysicalDeviceSurfaceSupportKHR; #define vkGetPhysicalDeviceSurfaceSupportKHR glad_vkGetPhysicalDeviceSurfaceSupportKHR +GLAD_API_CALL PFN_vkGetPhysicalDeviceToolProperties glad_vkGetPhysicalDeviceToolProperties; +#define vkGetPhysicalDeviceToolProperties glad_vkGetPhysicalDeviceToolProperties GLAD_API_CALL PFN_vkGetPipelineCacheData glad_vkGetPipelineCacheData; #define vkGetPipelineCacheData glad_vkGetPipelineCacheData +GLAD_API_CALL PFN_vkGetPrivateData glad_vkGetPrivateData; +#define vkGetPrivateData glad_vkGetPrivateData GLAD_API_CALL PFN_vkGetQueryPoolResults glad_vkGetQueryPoolResults; #define vkGetQueryPoolResults glad_vkGetQueryPoolResults GLAD_API_CALL PFN_vkGetRenderAreaGranularity glad_vkGetRenderAreaGranularity; #define vkGetRenderAreaGranularity glad_vkGetRenderAreaGranularity +GLAD_API_CALL PFN_vkGetSemaphoreCounterValue glad_vkGetSemaphoreCounterValue; +#define vkGetSemaphoreCounterValue glad_vkGetSemaphoreCounterValue GLAD_API_CALL PFN_vkGetSwapchainImagesKHR glad_vkGetSwapchainImagesKHR; #define vkGetSwapchainImagesKHR glad_vkGetSwapchainImagesKHR GLAD_API_CALL PFN_vkInvalidateMappedMemoryRanges glad_vkInvalidateMappedMemoryRanges; @@ -3948,6 +5542,8 @@ GLAD_API_CALL PFN_vkQueuePresentKHR glad_vkQueuePresentKHR; #define vkQueuePresentKHR glad_vkQueuePresentKHR GLAD_API_CALL PFN_vkQueueSubmit glad_vkQueueSubmit; #define vkQueueSubmit glad_vkQueueSubmit +GLAD_API_CALL PFN_vkQueueSubmit2 glad_vkQueueSubmit2; +#define vkQueueSubmit2 glad_vkQueueSubmit2 GLAD_API_CALL PFN_vkQueueWaitIdle glad_vkQueueWaitIdle; #define vkQueueWaitIdle glad_vkQueueWaitIdle GLAD_API_CALL PFN_vkResetCommandBuffer glad_vkResetCommandBuffer; @@ -3960,8 +5556,14 @@ GLAD_API_CALL PFN_vkResetEvent glad_vkResetEvent; #define vkResetEvent glad_vkResetEvent GLAD_API_CALL PFN_vkResetFences glad_vkResetFences; #define vkResetFences glad_vkResetFences +GLAD_API_CALL PFN_vkResetQueryPool glad_vkResetQueryPool; +#define vkResetQueryPool glad_vkResetQueryPool GLAD_API_CALL PFN_vkSetEvent glad_vkSetEvent; #define vkSetEvent glad_vkSetEvent +GLAD_API_CALL PFN_vkSetPrivateData glad_vkSetPrivateData; +#define vkSetPrivateData glad_vkSetPrivateData +GLAD_API_CALL PFN_vkSignalSemaphore glad_vkSignalSemaphore; +#define vkSignalSemaphore glad_vkSignalSemaphore GLAD_API_CALL PFN_vkTrimCommandPool glad_vkTrimCommandPool; #define vkTrimCommandPool glad_vkTrimCommandPool GLAD_API_CALL PFN_vkUnmapMemory glad_vkUnmapMemory; @@ -3972,6 +5574,8 @@ GLAD_API_CALL PFN_vkUpdateDescriptorSets glad_vkUpdateDescriptorSets; #define vkUpdateDescriptorSets glad_vkUpdateDescriptorSets GLAD_API_CALL PFN_vkWaitForFences glad_vkWaitForFences; #define vkWaitForFences glad_vkWaitForFences +GLAD_API_CALL PFN_vkWaitSemaphores glad_vkWaitSemaphores; +#define vkWaitSemaphores glad_vkWaitSemaphores @@ -4012,7 +5616,10 @@ extern "C" { int GLAD_VK_VERSION_1_0 = 0; int GLAD_VK_VERSION_1_1 = 0; +int GLAD_VK_VERSION_1_2 = 0; +int GLAD_VK_VERSION_1_3 = 0; int GLAD_VK_EXT_debug_report = 0; +int GLAD_VK_KHR_portability_enumeration = 0; int GLAD_VK_KHR_surface = 0; int GLAD_VK_KHR_swapchain = 0; @@ -4030,18 +5637,26 @@ PFN_vkBindImageMemory glad_vkBindImageMemory = NULL; PFN_vkBindImageMemory2 glad_vkBindImageMemory2 = NULL; PFN_vkCmdBeginQuery glad_vkCmdBeginQuery = NULL; PFN_vkCmdBeginRenderPass glad_vkCmdBeginRenderPass = NULL; +PFN_vkCmdBeginRenderPass2 glad_vkCmdBeginRenderPass2 = NULL; +PFN_vkCmdBeginRendering glad_vkCmdBeginRendering = NULL; PFN_vkCmdBindDescriptorSets glad_vkCmdBindDescriptorSets = NULL; PFN_vkCmdBindIndexBuffer glad_vkCmdBindIndexBuffer = NULL; PFN_vkCmdBindPipeline glad_vkCmdBindPipeline = NULL; PFN_vkCmdBindVertexBuffers glad_vkCmdBindVertexBuffers = NULL; +PFN_vkCmdBindVertexBuffers2 glad_vkCmdBindVertexBuffers2 = NULL; PFN_vkCmdBlitImage glad_vkCmdBlitImage = NULL; +PFN_vkCmdBlitImage2 glad_vkCmdBlitImage2 = NULL; PFN_vkCmdClearAttachments glad_vkCmdClearAttachments = NULL; PFN_vkCmdClearColorImage glad_vkCmdClearColorImage = NULL; PFN_vkCmdClearDepthStencilImage glad_vkCmdClearDepthStencilImage = NULL; PFN_vkCmdCopyBuffer glad_vkCmdCopyBuffer = NULL; +PFN_vkCmdCopyBuffer2 glad_vkCmdCopyBuffer2 = NULL; PFN_vkCmdCopyBufferToImage glad_vkCmdCopyBufferToImage = NULL; +PFN_vkCmdCopyBufferToImage2 glad_vkCmdCopyBufferToImage2 = NULL; PFN_vkCmdCopyImage glad_vkCmdCopyImage = NULL; +PFN_vkCmdCopyImage2 glad_vkCmdCopyImage2 = NULL; PFN_vkCmdCopyImageToBuffer glad_vkCmdCopyImageToBuffer = NULL; +PFN_vkCmdCopyImageToBuffer2 glad_vkCmdCopyImageToBuffer2 = NULL; PFN_vkCmdCopyQueryPoolResults glad_vkCmdCopyQueryPoolResults = NULL; PFN_vkCmdDispatch glad_vkCmdDispatch = NULL; PFN_vkCmdDispatchBase glad_vkCmdDispatchBase = NULL; @@ -4049,31 +5664,56 @@ PFN_vkCmdDispatchIndirect glad_vkCmdDispatchIndirect = NULL; PFN_vkCmdDraw glad_vkCmdDraw = NULL; PFN_vkCmdDrawIndexed glad_vkCmdDrawIndexed = NULL; PFN_vkCmdDrawIndexedIndirect glad_vkCmdDrawIndexedIndirect = NULL; +PFN_vkCmdDrawIndexedIndirectCount glad_vkCmdDrawIndexedIndirectCount = NULL; PFN_vkCmdDrawIndirect glad_vkCmdDrawIndirect = NULL; +PFN_vkCmdDrawIndirectCount glad_vkCmdDrawIndirectCount = NULL; PFN_vkCmdEndQuery glad_vkCmdEndQuery = NULL; PFN_vkCmdEndRenderPass glad_vkCmdEndRenderPass = NULL; +PFN_vkCmdEndRenderPass2 glad_vkCmdEndRenderPass2 = NULL; +PFN_vkCmdEndRendering glad_vkCmdEndRendering = NULL; PFN_vkCmdExecuteCommands glad_vkCmdExecuteCommands = NULL; PFN_vkCmdFillBuffer glad_vkCmdFillBuffer = NULL; PFN_vkCmdNextSubpass glad_vkCmdNextSubpass = NULL; +PFN_vkCmdNextSubpass2 glad_vkCmdNextSubpass2 = NULL; PFN_vkCmdPipelineBarrier glad_vkCmdPipelineBarrier = NULL; +PFN_vkCmdPipelineBarrier2 glad_vkCmdPipelineBarrier2 = NULL; PFN_vkCmdPushConstants glad_vkCmdPushConstants = NULL; PFN_vkCmdResetEvent glad_vkCmdResetEvent = NULL; +PFN_vkCmdResetEvent2 glad_vkCmdResetEvent2 = NULL; PFN_vkCmdResetQueryPool glad_vkCmdResetQueryPool = NULL; PFN_vkCmdResolveImage glad_vkCmdResolveImage = NULL; +PFN_vkCmdResolveImage2 glad_vkCmdResolveImage2 = NULL; PFN_vkCmdSetBlendConstants glad_vkCmdSetBlendConstants = NULL; +PFN_vkCmdSetCullMode glad_vkCmdSetCullMode = NULL; PFN_vkCmdSetDepthBias glad_vkCmdSetDepthBias = NULL; +PFN_vkCmdSetDepthBiasEnable glad_vkCmdSetDepthBiasEnable = NULL; PFN_vkCmdSetDepthBounds glad_vkCmdSetDepthBounds = NULL; +PFN_vkCmdSetDepthBoundsTestEnable glad_vkCmdSetDepthBoundsTestEnable = NULL; +PFN_vkCmdSetDepthCompareOp glad_vkCmdSetDepthCompareOp = NULL; +PFN_vkCmdSetDepthTestEnable glad_vkCmdSetDepthTestEnable = NULL; +PFN_vkCmdSetDepthWriteEnable glad_vkCmdSetDepthWriteEnable = NULL; PFN_vkCmdSetDeviceMask glad_vkCmdSetDeviceMask = NULL; PFN_vkCmdSetEvent glad_vkCmdSetEvent = NULL; +PFN_vkCmdSetEvent2 glad_vkCmdSetEvent2 = NULL; +PFN_vkCmdSetFrontFace glad_vkCmdSetFrontFace = NULL; PFN_vkCmdSetLineWidth glad_vkCmdSetLineWidth = NULL; +PFN_vkCmdSetPrimitiveRestartEnable glad_vkCmdSetPrimitiveRestartEnable = NULL; +PFN_vkCmdSetPrimitiveTopology glad_vkCmdSetPrimitiveTopology = NULL; +PFN_vkCmdSetRasterizerDiscardEnable glad_vkCmdSetRasterizerDiscardEnable = NULL; PFN_vkCmdSetScissor glad_vkCmdSetScissor = NULL; +PFN_vkCmdSetScissorWithCount glad_vkCmdSetScissorWithCount = NULL; PFN_vkCmdSetStencilCompareMask glad_vkCmdSetStencilCompareMask = NULL; +PFN_vkCmdSetStencilOp glad_vkCmdSetStencilOp = NULL; PFN_vkCmdSetStencilReference glad_vkCmdSetStencilReference = NULL; +PFN_vkCmdSetStencilTestEnable glad_vkCmdSetStencilTestEnable = NULL; PFN_vkCmdSetStencilWriteMask glad_vkCmdSetStencilWriteMask = NULL; PFN_vkCmdSetViewport glad_vkCmdSetViewport = NULL; +PFN_vkCmdSetViewportWithCount glad_vkCmdSetViewportWithCount = NULL; PFN_vkCmdUpdateBuffer glad_vkCmdUpdateBuffer = NULL; PFN_vkCmdWaitEvents glad_vkCmdWaitEvents = NULL; +PFN_vkCmdWaitEvents2 glad_vkCmdWaitEvents2 = NULL; PFN_vkCmdWriteTimestamp glad_vkCmdWriteTimestamp = NULL; +PFN_vkCmdWriteTimestamp2 glad_vkCmdWriteTimestamp2 = NULL; PFN_vkCreateBuffer glad_vkCreateBuffer = NULL; PFN_vkCreateBufferView glad_vkCreateBufferView = NULL; PFN_vkCreateCommandPool glad_vkCreateCommandPool = NULL; @@ -4092,8 +5732,10 @@ PFN_vkCreateImageView glad_vkCreateImageView = NULL; PFN_vkCreateInstance glad_vkCreateInstance = NULL; PFN_vkCreatePipelineCache glad_vkCreatePipelineCache = NULL; PFN_vkCreatePipelineLayout glad_vkCreatePipelineLayout = NULL; +PFN_vkCreatePrivateDataSlot glad_vkCreatePrivateDataSlot = NULL; PFN_vkCreateQueryPool glad_vkCreateQueryPool = NULL; PFN_vkCreateRenderPass glad_vkCreateRenderPass = NULL; +PFN_vkCreateRenderPass2 glad_vkCreateRenderPass2 = NULL; PFN_vkCreateSampler glad_vkCreateSampler = NULL; PFN_vkCreateSamplerYcbcrConversion glad_vkCreateSamplerYcbcrConversion = NULL; PFN_vkCreateSemaphore glad_vkCreateSemaphore = NULL; @@ -4117,6 +5759,7 @@ PFN_vkDestroyInstance glad_vkDestroyInstance = NULL; PFN_vkDestroyPipeline glad_vkDestroyPipeline = NULL; PFN_vkDestroyPipelineCache glad_vkDestroyPipelineCache = NULL; PFN_vkDestroyPipelineLayout glad_vkDestroyPipelineLayout = NULL; +PFN_vkDestroyPrivateDataSlot glad_vkDestroyPrivateDataSlot = NULL; PFN_vkDestroyQueryPool glad_vkDestroyQueryPool = NULL; PFN_vkDestroyRenderPass glad_vkDestroyRenderPass = NULL; PFN_vkDestroySampler glad_vkDestroySampler = NULL; @@ -4138,13 +5781,19 @@ PFN_vkFlushMappedMemoryRanges glad_vkFlushMappedMemoryRanges = NULL; PFN_vkFreeCommandBuffers glad_vkFreeCommandBuffers = NULL; PFN_vkFreeDescriptorSets glad_vkFreeDescriptorSets = NULL; PFN_vkFreeMemory glad_vkFreeMemory = NULL; +PFN_vkGetBufferDeviceAddress glad_vkGetBufferDeviceAddress = NULL; PFN_vkGetBufferMemoryRequirements glad_vkGetBufferMemoryRequirements = NULL; PFN_vkGetBufferMemoryRequirements2 glad_vkGetBufferMemoryRequirements2 = NULL; +PFN_vkGetBufferOpaqueCaptureAddress glad_vkGetBufferOpaqueCaptureAddress = NULL; PFN_vkGetDescriptorSetLayoutSupport glad_vkGetDescriptorSetLayoutSupport = NULL; +PFN_vkGetDeviceBufferMemoryRequirements glad_vkGetDeviceBufferMemoryRequirements = NULL; PFN_vkGetDeviceGroupPeerMemoryFeatures glad_vkGetDeviceGroupPeerMemoryFeatures = NULL; PFN_vkGetDeviceGroupPresentCapabilitiesKHR glad_vkGetDeviceGroupPresentCapabilitiesKHR = NULL; PFN_vkGetDeviceGroupSurfacePresentModesKHR glad_vkGetDeviceGroupSurfacePresentModesKHR = NULL; +PFN_vkGetDeviceImageMemoryRequirements glad_vkGetDeviceImageMemoryRequirements = NULL; +PFN_vkGetDeviceImageSparseMemoryRequirements glad_vkGetDeviceImageSparseMemoryRequirements = NULL; PFN_vkGetDeviceMemoryCommitment glad_vkGetDeviceMemoryCommitment = NULL; +PFN_vkGetDeviceMemoryOpaqueCaptureAddress glad_vkGetDeviceMemoryOpaqueCaptureAddress = NULL; PFN_vkGetDeviceProcAddr glad_vkGetDeviceProcAddr = NULL; PFN_vkGetDeviceQueue glad_vkGetDeviceQueue = NULL; PFN_vkGetDeviceQueue2 glad_vkGetDeviceQueue2 = NULL; @@ -4178,9 +5827,12 @@ PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR glad_vkGetPhysicalDeviceSurfaceCap PFN_vkGetPhysicalDeviceSurfaceFormatsKHR glad_vkGetPhysicalDeviceSurfaceFormatsKHR = NULL; PFN_vkGetPhysicalDeviceSurfacePresentModesKHR glad_vkGetPhysicalDeviceSurfacePresentModesKHR = NULL; PFN_vkGetPhysicalDeviceSurfaceSupportKHR glad_vkGetPhysicalDeviceSurfaceSupportKHR = NULL; +PFN_vkGetPhysicalDeviceToolProperties glad_vkGetPhysicalDeviceToolProperties = NULL; PFN_vkGetPipelineCacheData glad_vkGetPipelineCacheData = NULL; +PFN_vkGetPrivateData glad_vkGetPrivateData = NULL; PFN_vkGetQueryPoolResults glad_vkGetQueryPoolResults = NULL; PFN_vkGetRenderAreaGranularity glad_vkGetRenderAreaGranularity = NULL; +PFN_vkGetSemaphoreCounterValue glad_vkGetSemaphoreCounterValue = NULL; PFN_vkGetSwapchainImagesKHR glad_vkGetSwapchainImagesKHR = NULL; PFN_vkInvalidateMappedMemoryRanges glad_vkInvalidateMappedMemoryRanges = NULL; PFN_vkMapMemory glad_vkMapMemory = NULL; @@ -4188,18 +5840,23 @@ PFN_vkMergePipelineCaches glad_vkMergePipelineCaches = NULL; PFN_vkQueueBindSparse glad_vkQueueBindSparse = NULL; PFN_vkQueuePresentKHR glad_vkQueuePresentKHR = NULL; PFN_vkQueueSubmit glad_vkQueueSubmit = NULL; +PFN_vkQueueSubmit2 glad_vkQueueSubmit2 = NULL; PFN_vkQueueWaitIdle glad_vkQueueWaitIdle = NULL; PFN_vkResetCommandBuffer glad_vkResetCommandBuffer = NULL; PFN_vkResetCommandPool glad_vkResetCommandPool = NULL; PFN_vkResetDescriptorPool glad_vkResetDescriptorPool = NULL; PFN_vkResetEvent glad_vkResetEvent = NULL; PFN_vkResetFences glad_vkResetFences = NULL; +PFN_vkResetQueryPool glad_vkResetQueryPool = NULL; PFN_vkSetEvent glad_vkSetEvent = NULL; +PFN_vkSetPrivateData glad_vkSetPrivateData = NULL; +PFN_vkSignalSemaphore glad_vkSignalSemaphore = NULL; PFN_vkTrimCommandPool glad_vkTrimCommandPool = NULL; PFN_vkUnmapMemory glad_vkUnmapMemory = NULL; PFN_vkUpdateDescriptorSetWithTemplate glad_vkUpdateDescriptorSetWithTemplate = NULL; PFN_vkUpdateDescriptorSets glad_vkUpdateDescriptorSets = NULL; PFN_vkWaitForFences glad_vkWaitForFences = NULL; +PFN_vkWaitSemaphores glad_vkWaitSemaphores = NULL; static void glad_vk_load_VK_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) { @@ -4373,6 +6030,62 @@ static void glad_vk_load_VK_VERSION_1_1( GLADuserptrloadfunc load, void* userptr glad_vkTrimCommandPool = (PFN_vkTrimCommandPool) load(userptr, "vkTrimCommandPool"); glad_vkUpdateDescriptorSetWithTemplate = (PFN_vkUpdateDescriptorSetWithTemplate) load(userptr, "vkUpdateDescriptorSetWithTemplate"); } +static void glad_vk_load_VK_VERSION_1_2( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_VK_VERSION_1_2) return; + glad_vkCmdBeginRenderPass2 = (PFN_vkCmdBeginRenderPass2) load(userptr, "vkCmdBeginRenderPass2"); + glad_vkCmdDrawIndexedIndirectCount = (PFN_vkCmdDrawIndexedIndirectCount) load(userptr, "vkCmdDrawIndexedIndirectCount"); + glad_vkCmdDrawIndirectCount = (PFN_vkCmdDrawIndirectCount) load(userptr, "vkCmdDrawIndirectCount"); + glad_vkCmdEndRenderPass2 = (PFN_vkCmdEndRenderPass2) load(userptr, "vkCmdEndRenderPass2"); + glad_vkCmdNextSubpass2 = (PFN_vkCmdNextSubpass2) load(userptr, "vkCmdNextSubpass2"); + glad_vkCreateRenderPass2 = (PFN_vkCreateRenderPass2) load(userptr, "vkCreateRenderPass2"); + glad_vkGetBufferDeviceAddress = (PFN_vkGetBufferDeviceAddress) load(userptr, "vkGetBufferDeviceAddress"); + glad_vkGetBufferOpaqueCaptureAddress = (PFN_vkGetBufferOpaqueCaptureAddress) load(userptr, "vkGetBufferOpaqueCaptureAddress"); + glad_vkGetDeviceMemoryOpaqueCaptureAddress = (PFN_vkGetDeviceMemoryOpaqueCaptureAddress) load(userptr, "vkGetDeviceMemoryOpaqueCaptureAddress"); + glad_vkGetSemaphoreCounterValue = (PFN_vkGetSemaphoreCounterValue) load(userptr, "vkGetSemaphoreCounterValue"); + glad_vkResetQueryPool = (PFN_vkResetQueryPool) load(userptr, "vkResetQueryPool"); + glad_vkSignalSemaphore = (PFN_vkSignalSemaphore) load(userptr, "vkSignalSemaphore"); + glad_vkWaitSemaphores = (PFN_vkWaitSemaphores) load(userptr, "vkWaitSemaphores"); +} +static void glad_vk_load_VK_VERSION_1_3( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_VK_VERSION_1_3) return; + glad_vkCmdBeginRendering = (PFN_vkCmdBeginRendering) load(userptr, "vkCmdBeginRendering"); + glad_vkCmdBindVertexBuffers2 = (PFN_vkCmdBindVertexBuffers2) load(userptr, "vkCmdBindVertexBuffers2"); + glad_vkCmdBlitImage2 = (PFN_vkCmdBlitImage2) load(userptr, "vkCmdBlitImage2"); + glad_vkCmdCopyBuffer2 = (PFN_vkCmdCopyBuffer2) load(userptr, "vkCmdCopyBuffer2"); + glad_vkCmdCopyBufferToImage2 = (PFN_vkCmdCopyBufferToImage2) load(userptr, "vkCmdCopyBufferToImage2"); + glad_vkCmdCopyImage2 = (PFN_vkCmdCopyImage2) load(userptr, "vkCmdCopyImage2"); + glad_vkCmdCopyImageToBuffer2 = (PFN_vkCmdCopyImageToBuffer2) load(userptr, "vkCmdCopyImageToBuffer2"); + glad_vkCmdEndRendering = (PFN_vkCmdEndRendering) load(userptr, "vkCmdEndRendering"); + glad_vkCmdPipelineBarrier2 = (PFN_vkCmdPipelineBarrier2) load(userptr, "vkCmdPipelineBarrier2"); + glad_vkCmdResetEvent2 = (PFN_vkCmdResetEvent2) load(userptr, "vkCmdResetEvent2"); + glad_vkCmdResolveImage2 = (PFN_vkCmdResolveImage2) load(userptr, "vkCmdResolveImage2"); + glad_vkCmdSetCullMode = (PFN_vkCmdSetCullMode) load(userptr, "vkCmdSetCullMode"); + glad_vkCmdSetDepthBiasEnable = (PFN_vkCmdSetDepthBiasEnable) load(userptr, "vkCmdSetDepthBiasEnable"); + glad_vkCmdSetDepthBoundsTestEnable = (PFN_vkCmdSetDepthBoundsTestEnable) load(userptr, "vkCmdSetDepthBoundsTestEnable"); + glad_vkCmdSetDepthCompareOp = (PFN_vkCmdSetDepthCompareOp) load(userptr, "vkCmdSetDepthCompareOp"); + glad_vkCmdSetDepthTestEnable = (PFN_vkCmdSetDepthTestEnable) load(userptr, "vkCmdSetDepthTestEnable"); + glad_vkCmdSetDepthWriteEnable = (PFN_vkCmdSetDepthWriteEnable) load(userptr, "vkCmdSetDepthWriteEnable"); + glad_vkCmdSetEvent2 = (PFN_vkCmdSetEvent2) load(userptr, "vkCmdSetEvent2"); + glad_vkCmdSetFrontFace = (PFN_vkCmdSetFrontFace) load(userptr, "vkCmdSetFrontFace"); + glad_vkCmdSetPrimitiveRestartEnable = (PFN_vkCmdSetPrimitiveRestartEnable) load(userptr, "vkCmdSetPrimitiveRestartEnable"); + glad_vkCmdSetPrimitiveTopology = (PFN_vkCmdSetPrimitiveTopology) load(userptr, "vkCmdSetPrimitiveTopology"); + glad_vkCmdSetRasterizerDiscardEnable = (PFN_vkCmdSetRasterizerDiscardEnable) load(userptr, "vkCmdSetRasterizerDiscardEnable"); + glad_vkCmdSetScissorWithCount = (PFN_vkCmdSetScissorWithCount) load(userptr, "vkCmdSetScissorWithCount"); + glad_vkCmdSetStencilOp = (PFN_vkCmdSetStencilOp) load(userptr, "vkCmdSetStencilOp"); + glad_vkCmdSetStencilTestEnable = (PFN_vkCmdSetStencilTestEnable) load(userptr, "vkCmdSetStencilTestEnable"); + glad_vkCmdSetViewportWithCount = (PFN_vkCmdSetViewportWithCount) load(userptr, "vkCmdSetViewportWithCount"); + glad_vkCmdWaitEvents2 = (PFN_vkCmdWaitEvents2) load(userptr, "vkCmdWaitEvents2"); + glad_vkCmdWriteTimestamp2 = (PFN_vkCmdWriteTimestamp2) load(userptr, "vkCmdWriteTimestamp2"); + glad_vkCreatePrivateDataSlot = (PFN_vkCreatePrivateDataSlot) load(userptr, "vkCreatePrivateDataSlot"); + glad_vkDestroyPrivateDataSlot = (PFN_vkDestroyPrivateDataSlot) load(userptr, "vkDestroyPrivateDataSlot"); + glad_vkGetDeviceBufferMemoryRequirements = (PFN_vkGetDeviceBufferMemoryRequirements) load(userptr, "vkGetDeviceBufferMemoryRequirements"); + glad_vkGetDeviceImageMemoryRequirements = (PFN_vkGetDeviceImageMemoryRequirements) load(userptr, "vkGetDeviceImageMemoryRequirements"); + glad_vkGetDeviceImageSparseMemoryRequirements = (PFN_vkGetDeviceImageSparseMemoryRequirements) load(userptr, "vkGetDeviceImageSparseMemoryRequirements"); + glad_vkGetPhysicalDeviceToolProperties = (PFN_vkGetPhysicalDeviceToolProperties) load(userptr, "vkGetPhysicalDeviceToolProperties"); + glad_vkGetPrivateData = (PFN_vkGetPrivateData) load(userptr, "vkGetPrivateData"); + glad_vkQueueSubmit2 = (PFN_vkQueueSubmit2) load(userptr, "vkQueueSubmit2"); + glad_vkSetPrivateData = (PFN_vkSetPrivateData) load(userptr, "vkSetPrivateData"); +} static void glad_vk_load_VK_EXT_debug_report( GLADuserptrloadfunc load, void* userptr) { if(!GLAD_VK_EXT_debug_report) return; glad_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT) load(userptr, "vkCreateDebugReportCallbackEXT"); @@ -4530,6 +6243,7 @@ static int glad_vk_find_extensions_vulkan( VkPhysicalDevice physical_device) { if (!glad_vk_get_extensions(physical_device, &extension_count, &extensions)) return 0; GLAD_VK_EXT_debug_report = glad_vk_has_extension("VK_EXT_debug_report", extension_count, extensions); + GLAD_VK_KHR_portability_enumeration = glad_vk_has_extension("VK_KHR_portability_enumeration", extension_count, extensions); GLAD_VK_KHR_surface = glad_vk_has_extension("VK_KHR_surface", extension_count, extensions); GLAD_VK_KHR_swapchain = glad_vk_has_extension("VK_KHR_swapchain", extension_count, extensions); @@ -4567,6 +6281,8 @@ static int glad_vk_find_core_vulkan( VkPhysicalDevice physical_device) { GLAD_VK_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1; GLAD_VK_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1; + GLAD_VK_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1; + GLAD_VK_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1; return GLAD_MAKE_VERSION(major, minor); } @@ -4584,6 +6300,8 @@ int gladLoadVulkanUserPtr( VkPhysicalDevice physical_device, GLADuserptrloadfunc glad_vk_load_VK_VERSION_1_0(load, userptr); glad_vk_load_VK_VERSION_1_1(load, userptr); + glad_vk_load_VK_VERSION_1_2(load, userptr); + glad_vk_load_VK_VERSION_1_3(load, userptr); if (!glad_vk_find_extensions_vulkan( physical_device)) return 0; glad_vk_load_VK_EXT_debug_report(load, userptr); diff --git a/deps/stb_image_write.h b/deps/stb_image_write.h index 4319c0de..e4b32ed1 100644 --- a/deps/stb_image_write.h +++ b/deps/stb_image_write.h @@ -1,5 +1,5 @@ -/* stb_image_write - v1.02 - public domain - http://nothings.org/stb/stb_image_write.h - writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 +/* stb_image_write - v1.16 - public domain - http://nothings.org/stb + writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 no warranty implied; use at your own risk Before #including, @@ -12,41 +12,64 @@ ABOUT: - This header file is a library for writing images to C stdio. It could be - adapted to write to memory or a general streaming interface; let me know. + This header file is a library for writing images to C stdio or a callback. The PNG output is not optimal; it is 20-50% larger than the file - written by a decent optimizing implementation. This library is designed - for source code compactness and simplicity, not optimal image file size - or run-time performance. + written by a decent optimizing implementation; though providing a custom + zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that. + This library is designed for source code compactness and simplicity, + not optimal image file size or run-time performance. BUILDING: You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace malloc,realloc,free. - You can define STBIW_MEMMOVE() to replace memmove() + You can #define STBIW_MEMMOVE() to replace memmove() + You can #define STBIW_ZLIB_COMPRESS to use a custom zlib-style compress function + for PNG compression (instead of the builtin one), it must have the following signature: + unsigned char * my_compress(unsigned char *data, int data_len, int *out_len, int quality); + The returned data will be freed with STBIW_FREE() (free() by default), + so it must be heap allocated with STBIW_MALLOC() (malloc() by default), + +UNICODE: + + If compiling for Windows and you wish to use Unicode filenames, compile + with + #define STBIW_WINDOWS_UTF8 + and pass utf8-encoded filenames. Call stbiw_convert_wchar_to_utf8 to convert + Windows wchar_t filenames to utf8. USAGE: - There are four functions, one for each image file format: + There are five functions, one for each image file format: int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_jpg(char const *filename, int w, int h, int comp, const void *data, int quality); int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); - There are also four equivalent functions that use an arbitrary write function. You are + void stbi_flip_vertically_on_write(int flag); // flag is non-zero to flip data vertically + + There are also five equivalent functions that use an arbitrary write function. You are expected to open/close your file-equivalent before and after calling these: int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); where the callback is: void stbi_write_func(void *context, void *data, int size); + You can configure it with these global variables: + int stbi_write_tga_with_rle; // defaults to true; set to 0 to disable RLE + int stbi_write_png_compression_level; // defaults to 8; set to higher for more compression + int stbi_write_force_png_filter; // defaults to -1; set to 0..5 to force a filter mode + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these functions, so the library will not use stdio.h at all. However, this will also disable HDR writing, because it requires stdio for formatted output. @@ -73,6 +96,9 @@ USAGE: writer, both because it is in BGR order and because it may have padding at the end of the line.) + PNG allows you to set the deflate compression level by setting the global + variable 'stbi_write_png_compression_level' (it defaults to 8). + HDR expects linear float data. Since the format is always 32-bit rgb(e) data, alpha (if provided) is discarded, and for monochrome data it is replicated across all three channels. @@ -80,20 +106,23 @@ USAGE: TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed data, set the global variable 'stbi_write_tga_with_rle' to 0. + JPEG does ignore alpha channels in input data; quality is between 1 and 100. + Higher quality looks better but results in a bigger image. + JPEG baseline (no JPEG progressive). + CREDITS: - PNG/BMP/TGA - Sean Barrett - HDR - Baldur Karlsson - TGA monochrome: - Jean-Sebastien Guay - misc enhancements: - Tim Kelsey - TGA RLE - Alan Hickman - initial file IO callback implementation - Emmanuel Julien + + Sean Barrett - PNG/BMP/TGA + Baldur Karlsson - HDR + Jean-Sebastien Guay - TGA monochrome + Tim Kelsey - misc enhancements + Alan Hickman - TGA RLE + Emmanuel Julien - initial file IO callback implementation + Jon Olick - original jo_jpeg.cpp code + Daniel Gibson - integrate JPEG, allow external zlib + Aarni Koskela - allow choosing PNG filter + bugfixes: github:Chribba Guillaume Chereau @@ -103,27 +132,44 @@ CREDITS: Jonas Karlsson Filip Wasil Thatcher Ulrich - + github:poppolopoppo + Patrick Boettcher + github:xeekworx + Cap Petschulat + Simon Rodriguez + Ivan Tikhonov + github:ignotion + Adam Schackart + Andrew Kensler + LICENSE -This software is dual-licensed to the public domain and under the following -license: you are granted a perpetual, irrevocable license to copy, modify, -publish, and distribute this file as you see fit. + See end of file for license information. */ #ifndef INCLUDE_STB_IMAGE_WRITE_H #define INCLUDE_STB_IMAGE_WRITE_H +#include + +// if STB_IMAGE_WRITE_STATIC causes problems, try defining STBIWDEF to 'inline' or 'static inline' +#ifndef STBIWDEF +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else #ifdef __cplusplus -extern "C" { +#define STBIWDEF extern "C" +#else +#define STBIWDEF extern +#endif +#endif #endif -#ifdef STB_IMAGE_WRITE_STATIC -#define STBIWDEF static -#else -#define STBIWDEF extern -extern int stbi_write_tga_with_rle; +#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations +STBIWDEF int stbi_write_tga_with_rle; +STBIWDEF int stbi_write_png_compression_level; +STBIWDEF int stbi_write_force_png_filter; #endif #ifndef STBI_WRITE_NO_STDIO @@ -131,6 +177,11 @@ STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality); + +#ifdef STBIW_WINDOWS_UTF8 +STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif #endif typedef void stbi_write_func(void *context, void *data, int size); @@ -139,10 +190,9 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); -#ifdef __cplusplus -} -#endif +STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean); #endif//INCLUDE_STB_IMAGE_WRITE_H @@ -197,10 +247,29 @@ STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi_write_png_compression_level = 8; +static int stbi_write_tga_with_rle = 1; +static int stbi_write_force_png_filter = -1; +#else +int stbi_write_png_compression_level = 8; +int stbi_write_tga_with_rle = 1; +int stbi_write_force_png_filter = -1; +#endif + +static int stbi__flip_vertically_on_write = 0; + +STBIWDEF void stbi_flip_vertically_on_write(int flag) +{ + stbi__flip_vertically_on_write = flag; +} + typedef struct { stbi_write_func *func; void *context; + unsigned char buffer[64]; + int buf_used; } stbi__write_context; // initialize a callback-based context @@ -217,9 +286,52 @@ static void stbi__stdio_write(void *context, void *data, int size) fwrite(data,1,size,(FILE*) context); } +#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8) +#ifdef __cplusplus +#define STBIW_EXTERN extern "C" +#else +#define STBIW_EXTERN extern +#endif +STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); + +STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbiw__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) + return 0; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + static int stbi__start_write_file(stbi__write_context *s, const char *filename) { - FILE *f = fopen(filename, "wb"); + FILE *f = stbiw__fopen(filename, "wb"); stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); return f != NULL; } @@ -234,12 +346,6 @@ static void stbi__end_write_file(stbi__write_context *s) typedef unsigned int stbiw_uint32; typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; -#ifdef STB_IMAGE_WRITE_STATIC -static int stbi_write_tga_with_rle = 1; -#else -int stbi_write_tga_with_rle = 1; -#endif - static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) { while (*fmt) { @@ -277,11 +383,36 @@ static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) va_end(v); } +static void stbiw__write_flush(stbi__write_context *s) +{ + if (s->buf_used) { + s->func(s->context, &s->buffer, s->buf_used); + s->buf_used = 0; + } +} + +static void stbiw__putc(stbi__write_context *s, unsigned char c) +{ + s->func(s->context, &c, 1); +} + +static void stbiw__write1(stbi__write_context *s, unsigned char a) +{ + if ((size_t)s->buf_used + 1 > sizeof(s->buffer)) + stbiw__write_flush(s); + s->buffer[s->buf_used++] = a; +} + static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) { - unsigned char arr[3]; - arr[0] = a, arr[1] = b, arr[2] = c; - s->func(s->context, arr, 3); + int n; + if ((size_t)s->buf_used + 3 > sizeof(s->buffer)) + stbiw__write_flush(s); + n = s->buf_used; + s->buf_used = n+3; + s->buffer[n+0] = a; + s->buffer[n+1] = b; + s->buffer[n+2] = c; } static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) @@ -290,17 +421,15 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in int k; if (write_alpha < 0) - s->func(s->context, &d[comp - 1], 1); + stbiw__write1(s, d[comp - 1]); switch (comp) { + case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case case 1: - s->func(s->context,d,1); - break; - case 2: if (expand_mono) stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp else - s->func(s->context, d, 1); // monochrome TGA + stbiw__write1(s, d[0]); // monochrome TGA break; case 4: if (!write_alpha) { @@ -316,7 +445,7 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in break; } if (write_alpha > 0) - s->func(s->context, &d[comp - 1], 1); + stbiw__write1(s, d[comp - 1]); } static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) @@ -327,16 +456,21 @@ static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, i if (y <= 0) return; - if (vdir < 0) - j_end = -1, j = y-1; - else - j_end = y, j = 0; + if (stbi__flip_vertically_on_write) + vdir *= -1; + + if (vdir < 0) { + j_end = -1; j = y-1; + } else { + j_end = y; j = 0; + } for (; j != j_end; j += vdir) { for (i=0; i < x; ++i) { unsigned char *d = (unsigned char *) data + (j*x+i)*comp; stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); } + stbiw__write_flush(s); s->func(s->context, &zero, scanline_pad); } } @@ -357,16 +491,27 @@ static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) { - int pad = (-x*3) & 3; - return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, - "11 4 22 4" "4 44 22 444444", - 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header - 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header + if (comp != 4) { + // write RGB bitmap + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header + } else { + // RGBA bitmaps need a v4 header + // use BI_BITFIELDS mode with 32bpp and alpha mask + // (straight BI_RGB with alpha mask doesn't work in most readers) + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *)data,1,0, + "11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444", + 'B', 'M', 14+108+x*y*4, 0, 0, 14+108, // file header + 108, x,y, 1,32, 3,0,0,0,0,0, 0xff0000,0xff00,0xff,0xff000000u, 0, 0,0,0, 0,0,0, 0,0,0, 0,0,0); // bitmap V4 header + } } STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) { - stbi__write_context s; + stbi__write_context s = { 0 }; stbi__start_write_callbacks(&s, func, context); return stbi_write_bmp_core(&s, x, y, comp, data); } @@ -374,7 +519,7 @@ STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, #ifndef STBI_WRITE_NO_STDIO STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) { - stbi__write_context s; + stbi__write_context s = { 0 }; if (stbi__start_write_file(&s,filename)) { int r = stbi_write_bmp_core(&s, x, y, comp, data); stbi__end_write_file(&s); @@ -398,11 +543,21 @@ static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, v "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); } else { int i,j,k; + int jend, jdir; stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); - for (j = y - 1; j >= 0; --j) { - unsigned char *row = (unsigned char *) data + j * x * comp; + if (stbi__flip_vertically_on_write) { + j = 0; + jend = y; + jdir = 1; + } else { + j = y-1; + jend = -1; + jdir = -1; + } + for (; j != jend; j += jdir) { + unsigned char *row = (unsigned char *) data + j * x * comp; int len; for (i = 0; i < x; i += len) { @@ -437,32 +592,33 @@ static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, v if (diff) { unsigned char header = STBIW_UCHAR(len - 1); - s->func(s->context, &header, 1); + stbiw__write1(s, header); for (k = 0; k < len; ++k) { stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); } } else { unsigned char header = STBIW_UCHAR(len - 129); - s->func(s->context, &header, 1); + stbiw__write1(s, header); stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); } } } + stbiw__write_flush(s); } return 1; } -int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) { - stbi__write_context s; + stbi__write_context s = { 0 }; stbi__start_write_callbacks(&s, func, context); return stbi_write_tga_core(&s, x, y, comp, (void *) data); } #ifndef STBI_WRITE_NO_STDIO -int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) { - stbi__write_context s; + stbi__write_context s = { 0 }; if (stbi__start_write_file(&s,filename)) { int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); stbi__end_write_file(&s); @@ -475,11 +631,12 @@ int stbi_write_tga(char const *filename, int x, int y, int comp, const void *dat // ************************************************************************************************* // Radiance RGBE HDR writer // by Baldur Karlsson -#ifndef STBI_WRITE_NO_STDIO #define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) -void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) +#ifndef STBI_WRITE_NO_STDIO + +static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) { int exponent; float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); @@ -496,7 +653,7 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) } } -void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) +static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) { unsigned char lengthbyte = STBIW_UCHAR(length+128); STBIW_ASSERT(length+128 <= 255); @@ -504,7 +661,7 @@ void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char dat s->func(s->context, &databyte, 1); } -void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) +static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) { unsigned char lengthbyte = STBIW_UCHAR(length); STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code @@ -512,7 +669,7 @@ void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *d s->func(s->context, data, length); } -void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) +static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) { unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; unsigned char rgbe[4]; @@ -613,26 +770,30 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; s->func(s->context, header, sizeof(header)-1); +#ifdef __STDC_LIB_EXT1__ + len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); +#else len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); +#endif s->func(s->context, buffer, len); for(i=0; i < y; i++) - stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x); + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i)); STBIW_FREE(scratch); return 1; } } -int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) { - stbi__write_context s; + stbi__write_context s = { 0 }; stbi__start_write_callbacks(&s, func, context); return stbi_write_hdr_core(&s, x, y, comp, (float *) data); } -int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) { - stbi__write_context s; + stbi__write_context s = { 0 }; if (stbi__start_write_file(&s,filename)) { int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); stbi__end_write_file(&s); @@ -648,8 +809,9 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da // PNG writer // +#ifndef STBIW_ZLIB_COMPRESS // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() -#define stbiw__sbraw(a) ((int *) (a) - 2) +#define stbiw__sbraw(a) ((int *) (void *) (a) - 2) #define stbiw__sbm(a) stbiw__sbraw(a)[0] #define stbiw__sbn(a) stbiw__sbraw(a)[1] @@ -728,8 +890,14 @@ static unsigned int stbiw__zhash(unsigned char *data) #define stbiw__ZHASH 16384 -unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +#endif // STBIW_ZLIB_COMPRESS + +STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) { +#ifdef STBIW_ZLIB_COMPRESS + // user provided a zlib compress implementation, use that + return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality); +#else // use builtin static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; @@ -737,7 +905,9 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l unsigned int bitbuf=0; int i,j, bitcount=0; unsigned char *out = NULL; - unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**)); + if (hash_table == NULL) + return NULL; if (quality < 5) quality = 5; stbiw__sbpush(out, 0x78); // DEFLATE 32K window @@ -758,7 +928,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l for (j=0; j < n; ++j) { if (hlist[j]-data > i-32768) { // if entry lies within window int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); - if (d >= best) best=d,bestloc=hlist[j]; + if (d >= best) { best=d; bestloc=hlist[j]; } } } // when hash table entry is too long, delete half the entries @@ -811,14 +981,31 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l (void) stbiw__sbfree(hash_table[i]); STBIW_FREE(hash_table); + // store uncompressed instead if compression was worse + if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) { + stbiw__sbn(out) = 2; // truncate to DEFLATE 32K window and FLEVEL = 1 + for (j = 0; j < data_len;) { + int blocklen = data_len - j; + if (blocklen > 32767) blocklen = 32767; + stbiw__sbpush(out, data_len - j == blocklen); // BFINAL = ?, BTYPE = 0 -- no compression + stbiw__sbpush(out, STBIW_UCHAR(blocklen)); // LEN + stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(~blocklen)); // NLEN + stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8)); + memcpy(out+stbiw__sbn(out), data+j, blocklen); + stbiw__sbn(out) += blocklen; + j += blocklen; + } + } + { // compute adler32 on input unsigned int s1=1, s2=0; int blocklen = (int) (data_len % 5552); j=0; while (j < data_len) { - for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; - s1 %= 65521, s2 %= 65521; + for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; } + s1 %= 65521; s2 %= 65521; j += blocklen; blocklen = 5552; } @@ -831,10 +1018,14 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l // make returned pointer freeable STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); return (unsigned char *) stbiw__sbraw(out); +#endif // STBIW_ZLIB_COMPRESS } static unsigned int stbiw__crc32(unsigned char *buffer, int len) { +#ifdef STBIW_CRC32 + return STBIW_CRC32(buffer, len); +#else static unsigned int crc_table[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, @@ -876,6 +1067,7 @@ static unsigned int stbiw__crc32(unsigned char *buffer, int len) for (i=0; i < len; ++i) crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; return ~crc; +#endif } #define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) @@ -896,61 +1088,92 @@ static unsigned char stbiw__paeth(int a, int b, int c) return STBIW_UCHAR(c); } -unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +// @OPTIMIZE: provide an option that always forces left-predict or paeth predict +static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int width, int height, int y, int n, int filter_type, signed char *line_buffer) { + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = (y != 0) ? mapping : firstmap; + int i; + int type = mymap[filter_type]; + unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y); + int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes; + + if (type==0) { + memcpy(line_buffer, z, width*n); + return; + } + + // first loop isn't optimized since it's just one pixel + for (i = 0; i < n; ++i) { + switch (type) { + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + } + switch (type) { + case 1: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n]; break; + case 2: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break; + case 4: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break; + case 5: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } +} + +STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int force_filter = stbi_write_force_png_filter; int ctype[5] = { -1, 0, 4, 2, 6 }; unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; unsigned char *out,*o, *filt, *zlib; signed char *line_buffer; - int i,j,k,p,zlen; + int j,zlen; if (stride_bytes == 0) stride_bytes = x * n; + if (force_filter >= 5) { + force_filter = -1; + } + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } for (j=0; j < y; ++j) { - static int mapping[] = { 0,1,2,3,4 }; - static int firstmap[] = { 0,1,0,5,6 }; - int *mymap = j ? mapping : firstmap; - int best = 0, bestval = 0x7fffffff; - for (p=0; p < 2; ++p) { - for (k= p?best:0; k < 5; ++k) { - int type = mymap[k],est=0; - unsigned char *z = pixels + stride_bytes*j; - for (i=0; i < n; ++i) - switch (type) { - case 0: line_buffer[i] = z[i]; break; - case 1: line_buffer[i] = z[i]; break; - case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; - case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break; - case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break; - case 5: line_buffer[i] = z[i]; break; - case 6: line_buffer[i] = z[i]; break; - } - for (i=n; i < x*n; ++i) { - switch (type) { - case 0: line_buffer[i] = z[i]; break; - case 1: line_buffer[i] = z[i] - z[i-n]; break; - case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; - case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break; - case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break; - case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; - case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; - } - } - if (p) break; - for (i=0; i < x*n; ++i) + int filter_type; + if (force_filter > -1) { + filter_type = force_filter; + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer); + } else { // Estimate the best filter by running through all of them: + int best_filter = 0, best_filter_val = 0x7fffffff, est, i; + for (filter_type = 0; filter_type < 5; filter_type++) { + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer); + + // Estimate the entropy of the line using this filter; the less, the better. + est = 0; + for (i = 0; i < x*n; ++i) { est += abs((signed char) line_buffer[i]); - if (est < bestval) { bestval = est; best = k; } + } + if (est < best_filter_val) { + best_filter_val = est; + best_filter = filter_type; + } + } + if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer); + filter_type = best_filter; } } - // when we get here, best contains the filter type, and line_buffer contains the data - filt[j*(x*n+1)] = (unsigned char) best; + // when we get here, filter_type contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) filter_type; STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); } STBIW_FREE(line_buffer); - zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level); STBIW_FREE(filt); if (!zlib) return 0; @@ -993,9 +1216,10 @@ STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const { FILE *f; int len; - unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); if (png == NULL) return 0; - f = fopen(filename, "wb"); + + f = stbiw__fopen(filename, "wb"); if (!f) { STBIW_FREE(png); return 0; } fwrite(png, 1, len, f); fclose(f); @@ -1007,16 +1231,426 @@ STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) { int len; - unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); if (png == NULL) return 0; func(context, png, len); STBIW_FREE(png); return 1; } + +/* *************************************************************************** + * + * JPEG writer + * + * This is based on Jon Olick's jo_jpeg.cpp: + * public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html + */ + +static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18, + 24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 }; + +static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) { + int bitBuf = *bitBufP, bitCnt = *bitCntP; + bitCnt += bs[1]; + bitBuf |= bs[0] << (24 - bitCnt); + while(bitCnt >= 8) { + unsigned char c = (bitBuf >> 16) & 255; + stbiw__putc(s, c); + if(c == 255) { + stbiw__putc(s, 0); + } + bitBuf <<= 8; + bitCnt -= 8; + } + *bitBufP = bitBuf; + *bitCntP = bitCnt; +} + +static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) { + float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p; + float z1, z2, z3, z4, z5, z11, z13; + + float tmp0 = d0 + d7; + float tmp7 = d0 - d7; + float tmp1 = d1 + d6; + float tmp6 = d1 - d6; + float tmp2 = d2 + d5; + float tmp5 = d2 - d5; + float tmp3 = d3 + d4; + float tmp4 = d3 - d4; + + // Even part + float tmp10 = tmp0 + tmp3; // phase 2 + float tmp13 = tmp0 - tmp3; + float tmp11 = tmp1 + tmp2; + float tmp12 = tmp1 - tmp2; + + d0 = tmp10 + tmp11; // phase 3 + d4 = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * 0.707106781f; // c4 + d2 = tmp13 + z1; // phase 5 + d6 = tmp13 - z1; + + // Odd part + tmp10 = tmp4 + tmp5; // phase 2 + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + // The rotator is modified from fig 4-8 to avoid extra negations. + z5 = (tmp10 - tmp12) * 0.382683433f; // c6 + z2 = tmp10 * 0.541196100f + z5; // c2-c6 + z4 = tmp12 * 1.306562965f + z5; // c2+c6 + z3 = tmp11 * 0.707106781f; // c4 + + z11 = tmp7 + z3; // phase 5 + z13 = tmp7 - z3; + + *d5p = z13 + z2; // phase 6 + *d3p = z13 - z2; + *d1p = z11 + z4; + *d7p = z11 - z4; + + *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6; +} + +static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) { + int tmp1 = val < 0 ? -val : val; + val = val < 0 ? val-1 : val; + bits[1] = 1; + while(tmp1 >>= 1) { + ++bits[1]; + } + bits[0] = val & ((1<0)&&(DU[end0pos]==0); --end0pos) { + } + // end0pos = first element in reverse order !=0 + if(end0pos == 0) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + return DU[0]; + } + for(i = 1; i <= end0pos; ++i) { + int startpos = i; + int nrzeroes; + unsigned short bits[2]; + for (; DU[i]==0 && i<=end0pos; ++i) { + } + nrzeroes = i-startpos; + if ( nrzeroes >= 16 ) { + int lng = nrzeroes>>4; + int nrmarker; + for (nrmarker=1; nrmarker <= lng; ++nrmarker) + stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes); + nrzeroes &= 15; + } + stbiw__jpg_calcBits(DU[i], bits); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits); + } + if(end0pos != 63) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + } + return DU[0]; +} + +static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) { + // Constants that don't pollute global namespace + static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0}; + static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d}; + static const unsigned char std_ac_luminance_values[] = { + 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08, + 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28, + 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59, + 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6, + 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2, + 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0}; + static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77}; + static const unsigned char std_ac_chrominance_values[] = { + 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91, + 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26, + 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58, + 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4, + 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda, + 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + // Huffman tables + static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}}; + static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}}; + static const unsigned short YAC_HT[256][2] = { + {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const unsigned short UVAC_HT[256][2] = { + {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22, + 37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99}; + static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99, + 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99}; + static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f, + 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f }; + + int row, col, i, k, subsample; + float fdtbl_Y[64], fdtbl_UV[64]; + unsigned char YTable[64], UVTable[64]; + + if(!data || !width || !height || comp > 4 || comp < 1) { + return 0; + } + + quality = quality ? quality : 90; + subsample = quality <= 90 ? 1 : 0; + quality = quality < 1 ? 1 : quality > 100 ? 100 : quality; + quality = quality < 50 ? 5000 / quality : 200 - quality * 2; + + for(i = 0; i < 64; ++i) { + int uvti, yti = (YQT[i]*quality+50)/100; + YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti); + uvti = (UVQT[i]*quality+50)/100; + UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti); + } + + for(row = 0, k = 0; row < 8; ++row) { + for(col = 0; col < 8; ++col, ++k) { + fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + } + } + + // Write Headers + { + static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 }; + static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 }; + const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width), + 3,1,(unsigned char)(subsample?0x22:0x11),0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 }; + s->func(s->context, (void*)head0, sizeof(head0)); + s->func(s->context, (void*)YTable, sizeof(YTable)); + stbiw__putc(s, 1); + s->func(s->context, UVTable, sizeof(UVTable)); + s->func(s->context, (void*)head1, sizeof(head1)); + s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1); + s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values)); + stbiw__putc(s, 0x10); // HTYACinfo + s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1); + s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values)); + stbiw__putc(s, 1); // HTUDCinfo + s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values)); + stbiw__putc(s, 0x11); // HTUACinfo + s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values)); + s->func(s->context, (void*)head2, sizeof(head2)); + } + + // Encode 8x8 macroblocks + { + static const unsigned short fillBits[] = {0x7F, 7}; + int DCY=0, DCU=0, DCV=0; + int bitBuf=0, bitCnt=0; + // comp == 2 is grey+alpha (alpha is ignored) + int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0; + const unsigned char *dataR = (const unsigned char *)data; + const unsigned char *dataG = dataR + ofsG; + const unsigned char *dataB = dataR + ofsB; + int x, y, pos; + if(subsample) { + for(y = 0; y < height; y += 16) { + for(x = 0; x < width; x += 16) { + float Y[256], U[256], V[256]; + for(row = y, pos = 0; row < y+16; ++row) { + // row >= height => use last input row + int clamped_row = (row < height) ? row : height - 1; + int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp; + for(col = x; col < x+16; ++col, ++pos) { + // if col >= width => use pixel from last input column + int p = base_p + ((col < width) ? col : (width-1))*comp; + float r = dataR[p], g = dataG[p], b = dataB[p]; + Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128; + U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b; + V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b; + } + } + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); + + // subsample U,V + { + float subU[64], subV[64]; + int yy, xx; + for(yy = 0, pos = 0; yy < 8; ++yy) { + for(xx = 0; xx < 8; ++xx, ++pos) { + int j = yy*32+xx*2; + subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f; + subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f; + } + } + DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + } + } + } + } else { + for(y = 0; y < height; y += 8) { + for(x = 0; x < width; x += 8) { + float Y[64], U[64], V[64]; + for(row = y, pos = 0; row < y+8; ++row) { + // row >= height => use last input row + int clamped_row = (row < height) ? row : height - 1; + int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp; + for(col = x; col < x+8; ++col, ++pos) { + // if col >= width => use pixel from last input column + int p = base_p + ((col < width) ? col : (width-1))*comp; + float r = dataR[p], g = dataG[p], b = dataB[p]; + Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128; + U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b; + V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b; + } + } + + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + } + } + } + + // Do the bit alignment of the EOI marker + stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits); + } + + // EOI + stbiw__putc(s, 0xFF); + stbiw__putc(s, 0xD9); + + return 1; +} + +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality); +} + + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_jpg_core(&s, x, y, comp, data, quality); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history + 1.16 (2021-07-11) + make Deflate code emit uncompressed blocks when it would otherwise expand + support writing BMPs with alpha channel + 1.15 (2020-07-13) unknown + 1.14 (2020-02-02) updated JPEG writer to downsample chroma channels + 1.13 + 1.12 + 1.11 (2019-08-11) + + 1.10 (2019-02-07) + support utf8 filenames in Windows; fix warnings and platform ifdefs + 1.09 (2018-02-11) + fix typo in zlib quality API, improve STB_I_W_STATIC in C++ + 1.08 (2018-01-29) + add stbi__flip_vertically_on_write, external zlib, zlib quality, choose PNG filter + 1.07 (2017-07-24) + doc fix + 1.06 (2017-07-23) + writing JPEG (using Jon Olick's code) + 1.05 ??? + 1.04 (2017-03-03) + monochrome BMP expansion + 1.03 ??? 1.02 (2016-04-02) avoid allocating large structures on the stack 1.01 (2016-01-16) @@ -1035,7 +1669,7 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, add HDR output fix monochrome BMP 0.95 (2014-08-17) - add monochrome TGA output + add monochrome TGA output 0.94 (2014-05-31) rename private functions to avoid conflicts with stb_image.h 0.93 (2014-05-27) @@ -1046,3 +1680,45 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, first public release 0.90 first internal release */ + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 11ddf09b..050c1bed 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -351,8 +351,8 @@ __Note:__ If you haven't already implemented the feature, check first if there already is an open issue for it and if it's already being developed in an [experimental branch](https://github.com/glfw/glfw/branches/all). -__There is no preferred patch size__. A one character change is just as welcome -as one adding a thousand line one, if that is the appropriate size for the +__There is no preferred patch size__. A one-character change is just as welcome +as one adding a thousand lines, if that is the appropriate size for the feature. In addition to the code, a complete feature includes: diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in index f5504a83..6505aa33 100644 --- a/docs/Doxyfile.in +++ b/docs/Doxyfile.in @@ -1,4 +1,4 @@ -# Doxyfile 1.8.18 +# Doxyfile 1.9.5 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -12,6 +12,16 @@ # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). +# +# Note: +# +# Use doxygen to compare the used configuration file with the template +# configuration file: +# doxygen -x [configFile] +# Use doxygen to compare the used configuration file with the template +# configuration file without replacing the environment variables or CMake type +# replacement variables: +# doxygen -x_noenv [configFile] #--------------------------------------------------------------------------- # Project related configuration options @@ -60,16 +70,28 @@ PROJECT_LOGO = OUTPUT_DIRECTORY = "@GLFW_BINARY_DIR@/docs" -# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 +# sub-directories (in 2 levels) under the output directory of each output format +# and will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes -# performance problems for the file system. +# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to +# control the number of sub-directories. # The default value is: NO. CREATE_SUBDIRS = NO +# Controls the number of sub-directories that will be created when +# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every +# level increment doubles the number of directories, resulting in 4096 +# directories at level 8 which is the default and also the maximum value. The +# sub-directories are organized in 2 levels, the first level always has a fixed +# numer of 16 directories. +# Minimum value: 0, maximum value: 8, default value: 8. +# This tag requires that the tag CREATE_SUBDIRS is set to YES. + +CREATE_SUBDIRS_LEVEL = 8 + # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode @@ -81,26 +103,18 @@ ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, +# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English +# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek, +# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with +# English messages), Korean, Korean-en (Korean with English messages), Latvian, +# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, +# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, +# Swedish, Turkish, Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English -# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all generated output in the proper direction. -# Possible values are: None, LTR, RTL and Context. -# The default value is: None. - -OUTPUT_TEXT_DIRECTION = None - # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. @@ -217,6 +231,14 @@ QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. @@ -240,16 +262,16 @@ TAB_SIZE = 8 # the documentation. An alias has the form: # name=value # For example adding -# "sideeffect=@par Side Effects:\n" +# "sideeffect=@par Side Effects:^^" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines (in the resulting output). You can put ^^ in the value part of an -# alias to insert a newline as if a physical newline was in the original file. -# When you need a literal { or } or , in the value part of an alias you have to -# escape them by means of a backslash (\), this can lead to conflicts with the -# commands \{ and \} for these it is advised to use the version @{ and @} or use -# a double escape (\\{ and \\}) +# "Side Effects:". Note that you cannot put \n's in the value part of an alias +# to insert newlines (in the resulting output). You can put ^^ in the value part +# of an alias to insert a newline as if a physical newline was in the original +# file. When you need a literal { or } or , in the value part of an alias you +# have to escape them by means of a backslash (\), this can lead to conflicts +# with the commands \{ and \} for these it is advised to use the version @{ and +# @} or use a double escape (\\{ and \\}) ALIASES = "thread_safety=@par Thread safety^^" \ "pointer_lifetime=@par Pointer lifetime^^" \ @@ -305,8 +327,8 @@ OPTIMIZE_OUTPUT_SLICE = NO # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, JavaScript, -# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, -# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, +# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # tries to guess whether the code is fixed or free formatted code, this is the # default for Fortran type files). For instance to make doxygen treat .inc files @@ -316,7 +338,10 @@ OPTIMIZE_OUTPUT_SLICE = NO # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. EXTENSION_MAPPING = @@ -450,6 +475,19 @@ TYPEDEF_HIDES_STRUCT = NO LOOKUP_CACHE_SIZE = 0 +# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which effectively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- @@ -513,6 +551,13 @@ EXTRACT_LOCAL_METHODS = NO EXTRACT_ANON_NSPACES = NO +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation @@ -550,14 +595,22 @@ HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES, upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# (including Cygwin) ands Mac users are advised to set this option to NO. -# The default value is: system dependent. +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. +# Possible values are: SYSTEM, NO and YES. +# The default value is: SYSTEM. -CASE_SENSE_NAMES = YES +CASE_SENSE_NAMES = SYSTEM # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the @@ -573,6 +626,12 @@ HIDE_SCOPE_NAMES = NO HIDE_COMPOUND_REFERENCE= NO +# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class +# will show which file needs to be included to use the class. +# The default value is: YES. + +SHOW_HEADERFILE = NO + # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. @@ -730,7 +789,8 @@ FILE_VERSION_FILTER = # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. +# will be used as the name of the layout file. See also section "Changing the +# layout of pages" for information. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE @@ -776,24 +836,35 @@ WARNINGS = YES WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. +# potential errors in the documentation, such as documenting some parameters in +# a documented function twice, or documenting parameters that don't exist or +# using markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES +# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete +# function parameter documentation. If set to NO, doxygen will accept that some +# parameters have no documentation without warning. +# The default value is: YES. + +WARN_IF_INCOMPLETE_DOC = YES + # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. If -# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# value. If set to NO, doxygen will only warn about wrong parameter +# documentation, but not about the absence of documentation. If EXTRACT_ALL is +# set to YES then this flag will automatically be disabled. See also +# WARN_IF_INCOMPLETE_DOC # The default value is: NO. WARN_NO_PARAMDOC = YES # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when -# a warning is encountered. +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# Possible values are: NO, YES and FAIL_ON_WARNINGS. # The default value is: NO. WARN_AS_ERROR = NO @@ -804,13 +875,27 @@ WARN_AS_ERROR = NO # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) +# See also: WARN_LINE_FORMAT # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" +# In the $text part of the WARN_FORMAT command it is possible that a reference +# to a more specific place is given. To make it easier to jump to this place +# (outside of doxygen) the user can define a custom "cut" / "paste" string. +# Example: +# WARN_LINE_FORMAT = "'vi $file +$line'" +# See also: WARN_FORMAT +# The default value is: at line $line of file $file. + +WARN_LINE_FORMAT = "at line $line of file $file" + # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard -# error (stderr). +# error (stderr). In case the file specified cannot be opened for writing the +# warning and error messages are written to standard error. When as file - is +# specified the warning and error messages are written to standard output +# (stdout). WARN_LOGFILE = "@GLFW_BINARY_DIR@/docs/warnings.txt" @@ -829,12 +914,23 @@ INPUT = @GLFW_DOXYGEN_INPUT@ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: https://www.gnu.org/software/libiconv/) for the list of -# possible encodings. +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# See also: INPUT_FILE_ENCODING # The default value is: UTF-8. INPUT_ENCODING = UTF-8 +# This tag can be used to specify the character encoding of the source files +# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify +# character encoding on a per file pattern basis. Doxygen will compare the file +# name with each pattern and apply the encoding instead of the default +# INPUT_ENCODING) if there is a match. The character encodings are a list of the +# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding +# "INPUT_ENCODING" for further information on supported encodings. + +INPUT_FILE_ENCODING = + # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. @@ -843,12 +939,14 @@ INPUT_ENCODING = UTF-8 # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), -# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen -# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, +# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, +# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C +# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, # *.vhdl, *.ucf, *.qsf and *.ice. FILE_PATTERNS = *.h *.dox @@ -888,7 +986,7 @@ EXCLUDE_PATTERNS = # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test +# ANamespace::AClass, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* @@ -936,6 +1034,11 @@ IMAGE_PATH = # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # +# Note that doxygen will use the data processed and written to standard output +# for further processing, therefore nothing else, like debug statements or used +# commands (so in case of a Windows batch file always use @echo OFF), should be +# written to standard output. +# # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. @@ -977,6 +1080,15 @@ FILTER_SOURCE_PATTERNS = USE_MDFILE_AS_MAINPAGE = +# The Fortran standard specifies that for fixed formatted Fortran code all +# characters from position 72 are to be considered as comment. A common +# extension is to allow longer lines before the automatic comment starts. The +# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can +# be processed before the automatic comment starts. +# Minimum value: 7, maximum value: 10000, default value: 72. + +FORTRAN_COMMENT_AFTER = 72 + #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- @@ -1171,9 +1283,26 @@ HTML_EXTRA_STYLESHEET = "@GLFW_SOURCE_DIR@/docs/extra.css" HTML_EXTRA_FILES = "@GLFW_SOURCE_DIR@/docs/spaces.svg" +# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output +# should be rendered with a dark or light theme. Default setting AUTO_LIGHT +# enables light output unless the user preference is dark output. Other options +# are DARK to always use dark mode, LIGHT to always use light mode, AUTO_DARK to +# default to dark mode unless the user prefers light mode, and TOGGLE to let the +# user toggle between dark and light mode via a button. +# Possible values are: LIGHT Always generate light output., DARK Always generate +# dark output., AUTO_LIGHT Automatically set the mode according to the user +# preference, use light mode if no preference is set (the default)., AUTO_DARK +# Automatically set the mode according to the user preference, use dark mode if +# no preference is set. and TOGGLE Allow to user to switch between light and +# dark mode via a button.. +# The default value is: AUTO_LIGHT. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE = LIGHT + # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see +# this color. Hue is specified as an angle on a color-wheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. @@ -1183,7 +1312,7 @@ HTML_EXTRA_FILES = "@GLFW_SOURCE_DIR@/docs/spaces.svg" HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A +# in the HTML output. For a value of 0 the output will use gray-scales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1244,10 +1373,11 @@ HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: https://developer.apple.com/xcode/), introduced with OSX -# 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy # genXcode/_index.html for more information. @@ -1264,6 +1394,13 @@ GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" +# This tag determines the URL of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDURL = + # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. @@ -1289,8 +1426,12 @@ DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. +# on Windows. In the beginning of 2021 Microsoft took the original page, with +# a.o. the download links, offline the HTML help workshop was already many years +# in maintenance mode). You can download the HTML help workshop from the web +# archives at Installation executable (see: +# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo +# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML @@ -1320,7 +1461,7 @@ CHM_FILE = HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated -# (YES) or that it should be included in the master .chm file (NO). +# (YES) or that it should be included in the main .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. @@ -1365,7 +1506,8 @@ QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace -# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1373,8 +1515,8 @@ QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- -# folders). +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1382,16 +1524,16 @@ QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom -# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- -# filters). +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- -# filters). +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = @@ -1403,9 +1545,9 @@ QHP_CUST_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS = -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = @@ -1448,16 +1590,28 @@ DISABLE_INDEX = NO # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. +# further fine tune the look of the index (see "Fine-tuning the output"). As an +# example, the default style sheet generated by doxygen has an example that +# shows how to put an image at the root of the tree instead of the PROJECT_NAME. +# Since the tree basically has the same information as the tab index, you could +# consider setting DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO +# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the +# FULL_SIDEBAR option determines if the side bar is limited to only the treeview +# area (value NO) or if it should extend to the full height of the window (value +# YES). Setting this to YES gives a layout similar to +# https://docs.readthedocs.io with more room for contents, but less room for the +# project logo, title, and description. If either GENERATE_TREEVIEW or +# DISABLE_INDEX is set to NO, this option has no effect. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FULL_SIDEBAR = NO + # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # @@ -1482,12 +1636,19 @@ TREEVIEW_WIDTH = 300 EXT_LINKS_IN_WINDOW = NO +# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email +# addresses. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +OBFUSCATE_EMAILS = YES + # If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg # tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see # https://inkscape.org) to generate formulas as SVG images instead of PNGs for # the HTML output. These images will generally look nicer at scaled resolutions. -# Possible values are: png The default and svg Looks nicer but requires the -# pdf2svg tool. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). # The default value is: png. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1502,17 +1663,6 @@ HTML_FORMULA_FORMAT = png FORMULA_FONTSIZE = 10 -# Use the FORMULA_TRANSPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - # The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands # to create new LaTeX commands to be used in formulas as building blocks. See # the section "Including formulas" for details. @@ -1530,11 +1680,29 @@ FORMULA_MACROFILE = USE_MATHJAX = NO +# With MATHJAX_VERSION it is possible to specify the MathJax version to be used. +# Note that the different versions of MathJax have different requirements with +# regards to the different settings, so it is possible that also other MathJax +# settings have to be changed when switching between the different MathJax +# versions. +# Possible values are: MathJax_2 and MathJax_3. +# The default value is: MathJax_2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_VERSION = MathJax_2 + # When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. +# the MathJax output. For more details about the output format see MathJax +# version 2 (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 +# (see: +# http://docs.mathjax.org/en/latest/web/components/output.html). # Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. +# compatibility. This is the name for Mathjax version 2, for MathJax version 3 +# this will be translated into chtml), NativeMML (i.e. MathML. Only supported +# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This +# is the name for Mathjax version 3, for MathJax version 2 this will be +# translated into HTML-CSS) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. @@ -1547,22 +1715,29 @@ MATHJAX_FORMAT = HTML-CSS # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of -# MathJax from https://www.mathjax.org before deployment. -# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. +# MathJax from https://www.mathjax.org before deployment. The default value is: +# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 +# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 # This tag requires that the tag USE_MATHJAX is set to YES. -MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2 +MATHJAX_RELPATH = # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example +# for MathJax version 2 (see +# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# For example for MathJax version 3 (see +# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): +# MATHJAX_EXTENSIONS = ams # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. @@ -1609,7 +1784,8 @@ SERVER_BASED_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: https://xapian.org/). +# Xapian (see: +# https://xapian.org/). # # See the section "External Indexing and Searching" for details. # The default value is: NO. @@ -1622,8 +1798,9 @@ EXTERNAL_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: https://xapian.org/). See the section "External Indexing and -# Searching" for details. +# Xapian (see: +# https://xapian.org/). See the section "External Indexing and Searching" for +# details. # This tag requires that the tag SEARCHENGINE is set to YES. SEARCHENGINE_URL = @@ -1732,29 +1909,31 @@ PAPER_TYPE = a4 EXTRA_PACKAGES = -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the -# generated LaTeX document. The header should contain everything until the first -# chapter. If it is left blank doxygen will generate a standard header. See -# section "Doxygen usage" for information on how to let doxygen write the -# default header to a separate file. +# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for +# the generated LaTeX document. The header should contain everything until the +# first chapter. If it is left blank doxygen will generate a standard header. It +# is highly recommended to start with a default header using +# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty +# and then modify the file new_header.tex. See also section "Doxygen usage" for +# information on how to generate the default header that doxygen normally uses. # -# Note: Only use a user-defined header if you know what you are doing! The -# following commands have a special meaning inside the header: $title, -# $datetime, $date, $doxygenversion, $projectname, $projectnumber, -# $projectbrief, $projectlogo. Doxygen will replace $title with the empty -# string, for the replacement values of the other commands the user is referred -# to HTML_HEADER. +# Note: Only use a user-defined header if you know what you are doing! +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. The following +# commands have a special meaning inside the header (and footer): For a +# description of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_HEADER = -# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the -# generated LaTeX document. The footer should contain everything after the last -# chapter. If it is left blank doxygen will generate a standard footer. See +# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for +# the generated LaTeX document. The footer should contain everything after the +# last chapter. If it is left blank doxygen will generate a standard footer. See # LATEX_HEADER for more information on how to generate a default footer and what -# special commands can be used inside the footer. -# -# Note: Only use a user-defined footer if you know what you are doing! +# special commands can be used inside the footer. See also section "Doxygen +# usage" for information on how to generate the default footer that doxygen +# normally uses. Note: Only use a user-defined footer if you know what you are +# doing! # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_FOOTER = @@ -1787,9 +1966,11 @@ LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES -# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate -# the PDF file directly from the LaTeX files. Set this option to YES, to get a -# higher quality PDF documentation. +# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as +# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX +# files. Set this option to YES, to get a higher quality PDF documentation. +# +# See also section LATEX_CMD_NAME for selecting the engine. # The default value is: YES. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1797,8 +1978,7 @@ USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode # command to the generated LaTeX files. This will instruct LaTeX to keep running -# if errors occur, instead of asking the user for help. This option is also used -# when generating formulas in HTML. +# if errors occur, instead of asking the user for help. # The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1811,16 +1991,6 @@ LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO -# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source -# code with syntax highlighting in the LaTeX output. -# -# Note that which sources are shown also depends on other settings such as -# SOURCE_BROWSER. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_SOURCE_CODE = NO - # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See # https://en.wikipedia.org/wiki/BibTeX and \cite for more info. @@ -1901,16 +2071,6 @@ RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = -# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code -# with syntax highlighting in the RTF output. -# -# Note that which sources are shown also depends on other settings such as -# SOURCE_BROWSER. -# The default value is: NO. -# This tag requires that the tag GENERATE_RTF is set to YES. - -RTF_SOURCE_CODE = NO - #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- @@ -2007,15 +2167,6 @@ GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook -# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the -# program listings (including syntax highlighting and cross-referencing -# information) to the DOCBOOK output. Note that enabling this will significantly -# increase the size of the DOCBOOK output. -# The default value is: NO. -# This tag requires that the tag GENERATE_DOCBOOK is set to YES. - -DOCBOOK_PROGRAMLISTING = NO - #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- @@ -2102,7 +2253,8 @@ SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by the -# preprocessor. +# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of +# RECURSIVE has no effect here. # This tag requires that the tag SEARCH_INCLUDES is set to YES. INCLUDE_PATH = @@ -2204,15 +2356,6 @@ EXTERNAL_PAGES = YES # Configuration options related to the dot tool #--------------------------------------------------------------------------- -# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram -# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to -# NO turns the diagrams off. Note that this option also works with HAVE_DOT -# disabled, but it is recommended to install and use dot, since it yields more -# powerful graphs. -# The default value is: YES. - -CLASS_DIAGRAMS = YES - # You can include diagrams made with dia in doxygen documentation. Doxygen will # then run dia to produce the diagram and insert it in the documentation. The # DIA_PATH tag allows you to specify the directory where the dia binary resides. @@ -2245,35 +2388,50 @@ HAVE_DOT = NO DOT_NUM_THREADS = 0 -# When you want a differently looking font in the dot files that doxygen -# generates you can specify the font name using DOT_FONTNAME. You need to make -# sure dot is able to find the font, which can be done by putting it in a -# standard location or by setting the DOTFONTPATH environment variable or by -# setting DOT_FONTPATH to the directory containing the font. -# The default value is: Helvetica. +# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of +# subgraphs. When you want a differently looking font in the dot files that +# doxygen generates you can specify fontname, fontcolor and fontsize attributes. +# For details please see Node, +# Edge and Graph Attributes specification You need to make sure dot is able +# to find the font, which can be done by putting it in a standard location or by +# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. Default graphviz fontsize is 14. +# The default value is: fontname=Helvetica,fontsize=10. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTNAME = Helvetica +DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10" -# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of -# dot graphs. -# Minimum value: 4, maximum value: 24, default value: 10. +# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can +# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. Complete documentation about +# arrows shapes. +# The default value is: labelfontname=Helvetica,labelfontsize=10. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTSIZE = 10 +DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10" -# By default doxygen will tell dot to use the default font as specified with -# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set -# the path where dot can find it using this tag. +# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes +# around nodes set 'shape=plain' or 'shape=plaintext' Shapes specification +# The default value is: shape=box,height=0.2,width=0.4. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4" + +# You can set the path where dot can find font specified with fontname in +# DOT_COMMON_ATTR and others dot attributes. # This tag requires that the tag HAVE_DOT is set to YES. DOT_FONTPATH = -# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for -# each documented class showing the direct and indirect inheritance relations. -# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. +# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a +# graph for each documented class showing the direct and indirect inheritance +# relations. In case HAVE_DOT is set as well dot will be used to draw the graph, +# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set +# to TEXT the direct and indirect inheritance relations will be shown as texts / +# links. +# Possible values are: NO, YES, TEXT and GRAPH. # The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. CLASS_GRAPH = YES @@ -2287,7 +2445,8 @@ CLASS_GRAPH = YES COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for -# groups, showing the direct groups dependencies. +# groups, showing the direct groups dependencies. See also the chapter Grouping +# in the manual. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2310,10 +2469,32 @@ UML_LOOK = NO # but if the number exceeds 15, the total amount of fields shown is limited to # 10. # Minimum value: 0, maximum value: 100, default value: 10. -# This tag requires that the tag HAVE_DOT is set to YES. +# This tag requires that the tag UML_LOOK is set to YES. UML_LIMIT_NUM_FIELDS = 10 +# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and +# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS +# tag is set to YES, doxygen will add type and arguments for attributes and +# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen +# will not generate fields with class member information in the UML graphs. The +# class diagrams will look similar to the default class diagrams but using UML +# notation for the relationships. +# Possible values are: NO, YES and NONE. +# The default value is: NO. +# This tag requires that the tag UML_LOOK is set to YES. + +DOT_UML_DETAILS = NO + +# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters +# to display on a single line. If the actual line length exceeds this threshold +# significantly it will wrapped across multiple lines. Some heuristics are apply +# to avoid ugly line breaks. +# Minimum value: 0, maximum value: 1000, default value: 17. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_WRAP_THRESHOLD = 17 + # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and # collaboration graphs will show the relations between templates and their # instances. @@ -2380,6 +2561,13 @@ GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES +# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels +# of child directories generated in directory dependency graphs by dot. +# Minimum value: 1, maximum value: 25, default value: 1. +# This tag requires that the tag DIRECTORY_GRAPH is set to YES. + +DIR_GRAPH_MAX_DEPTH = 1 + # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. For an explanation of the image formats see the section # output formats in the documentation of the dot tool (Graphviz (see: @@ -2433,10 +2621,10 @@ MSCFILE_DIRS = DIAFILE_DIRS = # When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the -# path where java can find the plantuml.jar file. If left blank, it is assumed -# PlantUML is not used or called during a preprocessing step. Doxygen will -# generate a warning when it encounters a \startuml command in this case and -# will not generate output for the diagram. +# path where java can find the plantuml.jar file or to the filename of jar file +# to be used. If left blank, it is assumed PlantUML is not used or called during +# a preprocessing step. Doxygen will generate a warning when it encounters a +# \startuml command in this case and will not generate output for the diagram. PLANTUML_JAR_PATH = @@ -2474,18 +2662,6 @@ DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not seem -# to support this out of the box. -# -# Warning: Depending on the platform used, enabling this option may lead to -# badly anti-aliased labels on the edges of a graph (i.e. they become hard to -# read). -# The default value is: NO. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_TRANSPARENT = NO - # Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) support @@ -2498,14 +2674,18 @@ DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page # explaining the meaning of the various boxes and arrows in the dot generated # graphs. +# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal +# graphical representation for inheritance and collaboration diagrams is used. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot +# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate # files that are used to generate the various graphs. +# +# Note: This setting is not only used for dot files but also for msc temporary +# files. # The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. DOT_CLEANUP = YES diff --git a/docs/build.dox b/docs/build.dox index aa06b0f4..a1625d60 100644 --- a/docs/build.dox +++ b/docs/build.dox @@ -26,7 +26,7 @@ GLFW. @endcode This header defines all the constants and declares all the types and function -prototypes of the GLFW API. By default it also includes the OpenGL header from +prototypes of the GLFW API. By default, it also includes the OpenGL header from your development environment. See [option macros](@ref build_macros) below for how to select OpenGL ES headers and more. @@ -57,7 +57,7 @@ macros that disable similar headers below it. Both of these mechanisms depend on the extension loader header defining a known macro. If yours doesn't or you don't know which one your users will pick, the -@ref GLFW_INCLUDE_NONE macro will explicitly to prevent the GLFW header from +@ref GLFW_INCLUDE_NONE macro will explicitly prevent the GLFW header from including the OpenGL header. This will also allow you to include the two headers in any order. diff --git a/docs/compat.dox b/docs/compat.dox index 5b264b3f..94372197 100644 --- a/docs/compat.dox +++ b/docs/compat.dox @@ -104,9 +104,8 @@ integration by libwayland-egl, and keyboard handling by from wayland-protocols to provide additional features if the compositor supports them. -GLFW uses xkbcommon 0.5.0 to provide compose key support. When it has been -built against an older xkbcommon, the compose key will be disabled even if it -has been configured in the compositor. +GLFW uses xkbcommon 0.5.0 to provide key and text input support. Earlier +versions are not supported. GLFW uses the [xdg-shell protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/xdg-shell/xdg-shell.xml) @@ -153,7 +152,7 @@ formats. If GLX 1.3 is not supported, @ref glfwInit will fail. GLFW uses the `GLX_MESA_swap_control,` `GLX_EXT_swap_control` and `GLX_SGI_swap_control` extensions to provide vertical retrace synchronization -(or _vsync_), in that order of preference. Where none of these extension are +(or _vsync_), in that order of preference. When none of these extensions are available, calling @ref glfwSwapInterval will have no effect. GLFW uses the `GLX_ARB_multisample` extension to create contexts with @@ -220,8 +219,8 @@ extension is unavailable, the `GLFW_CONTEXT_RELEASE_BEHAVIOR` hint will have no effect and the context will always be flushed when released. GLFW uses the `WGL_ARB_framebuffer_sRGB` and `WGL_EXT_framebuffer_sRGB` -extensions to provide support for sRGB framebuffers. Where both of these -extension are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect. +extensions to provide support for sRGB framebuffers. When both of these +extensions are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect. @section compat_osx OpenGL on macOS diff --git a/docs/compile.dox b/docs/compile.dox index d5b839d6..3490eb15 100644 --- a/docs/compile.dox +++ b/docs/compile.dox @@ -10,8 +10,8 @@ build applications that use GLFW, see @ref build_guide. @section compile_cmake Using CMake -@note GLFW behaves like most other libraries that use CMake so this guide mostly -describes the basic configure/generate/compile sequence. If you are already +GLFW behaves like most other libraries that use CMake so this guide mostly +describes the standard configure, generate and compile sequence. If you are already familiar with this from other projects, you may want to focus on the @ref compile_deps and @ref compile_options sections for GLFW-specific information. @@ -40,12 +40,12 @@ all necessary dependencies for compiling GLFW, but on Unix-like systems like Linux and FreeBSD you will need a few extra packages. -@subsubsection compile_deps_x11 Dependencies for X11 on Unix-like systems +@subsubsection compile_deps_x11 Dependencies for X11 To compile GLFW for X11, you need to have the X11 development packages installed. They are not needed to build or run programs that use GLFW. -On Debian and derivates like Ubuntu and Linux Mint the `xorg-dev` meta-package +On Debian and derivatives like Ubuntu and Linux Mint the `xorg-dev` meta-package pulls in the development packages for all of X11. @code{.sh} @@ -68,40 +68,47 @@ install the `xorgproto` package. pkg install xorgproto @endcode -On Cygwin the `xorgproto` package in the Devel section of the GUI installer will -install the headers and other development related files for all of X11. +On Cygwin the `libXcursor-devel`, `libXi-devel`, `libXinerama-devel`, +`libXrandr-devel` and `libXrender-devel` packages in the Libs section of the GUI +installer will install all the headers and other development related files GLFW +requires for X11. -Once you have the required depdendencies, move on to @ref compile_generate. +Once you have the required dependencies, move on to @ref compile_generate. -@subsubsection compile_deps_wayland Dependencies for Wayland on Unix-like systems +@subsubsection compile_deps_wayland Dependencies for Wayland and X11 -To compile GLFW for Wayland, you need to have the Wayland and xkbcommon -development packages installed. They are not needed to build or run programs -that use GLFW. +To compile GLFW for both Wayland and X11, you need to have the X11, Wayland and xkbcommon +development packages installed. They are not needed to build or run programs that use +GLFW. You will also need to set the @ref GLFW_BUILD_WAYLAND CMake option in the next +step when generating build files. -On Debian and derivates like Ubuntu and Linux Mint you will need the -`libwayland-dev`, `libxkbcommon-dev` and `wayland-protocols` packages. +On Debian and derivatives like Ubuntu and Linux Mint you will need the `libwayland-dev`, +`libxkbcommon-dev` and `wayland-protocols` packages and the `xorg-dev` meta-package. +These will pull in all other dependencies. @code{.sh} -sudo apt install libwayland-dev libxkbcommon-dev wayland-protocols +sudo apt install libwayland-dev libxkbcommon-dev wayland-protocols xorg-dev @endcode On Fedora and derivatives like Red Hat you will need the `wayland-devel`, -`libxkbcommon-devel` and `wayland-protocols-devel` packages. +`libxkbcommon-devel`, `wayland-protocols-devel`, `libXcursor-devel`, `libXi-devel`, +`libXinerama-devel` and `libXrandr-devel` packages. These will pull in all other +dependencies. @code{.sh} -sudo dnf install wayland-devel libxkbcommon-devel wayland-protocols-devel +sudo dnf install wayland-devel libxkbcommon-devel wayland-protocols-devel libXcursor-devel libXi-devel libXinerama-devel libXrandr-devel @endcode -On FreeBSD you will need the `wayland`, `libxkbcommon` and `wayland-protocols` -packages. +On FreeBSD you will need the `wayland`, `libxkbcommon` and `wayland-protocols` packages. +The X11 headers are installed along the end-user X11 packages, so if you have an X server +running you should have the headers as well. If not, install the `xorgproto` package. @code{.sh} -pkg install wayland libxkbcommon wayland-protocols +pkg install wayland libxkbcommon wayland-protocols xorgproto @endcode -Once you have the required depdendencies, move on to @ref compile_generate. +Once you have the required dependencies, move on to @ref compile_generate. @subsection compile_generate Generating build files with CMake @@ -126,7 +133,7 @@ A common pattern when building a single configuration is to have a build directory named `build` in the root of the source tree. -@subsubsection compile_generate_gui Generating files with the CMake GUI +@subsubsection compile_generate_gui Generating with the CMake GUI Start the CMake GUI and set the paths to the source and build directories described above. Then press _Configure_ and _Generate_. @@ -135,15 +142,15 @@ If you wish change any CMake variables in the list, press _Configure_ and then _Generate_ to have the new values take effect. The variable list will be populated after the first configure step. -By default GLFW will use X11 on Linux and other Unix-like systems other -than macOS. To use Wayland instead, set the `GLFW_USE_WAYLAND` option in the -GLFW section of the variable list, then apply the new value as described above. +By default, GLFW will use X11 on Linux and other Unix-like systems other than macOS. To +include support for Wayland as well, set the @ref GLFW_BUILD_WAYLAND option in the GLFW +section of the variable list, then apply the new value as described above. Once you have generated the project files or makefiles for your chosen development environment, move on to @ref compile_compile. -@subsubsection compile_generate_cli Generating files with the CMake command-line tool +@subsubsection compile_generate_cli Generating with command-line CMake To make a build directory, pass the source and build directories to the `cmake` command. These can be relative or absolute paths. The build directory is @@ -169,11 +176,12 @@ flag. cmake -S path/to/glfw -B path/to/build -G Xcode @endcode -By default GLFW will use X11 on Linux and other Unix-like systems other -than macOS. To use Wayland instead, set the `GLFW_USE_WAYLAND` CMake option. +By default, GLFW will use X11 on Linux and other Unix-like systems other +than macOS. To also include support for Wayland, set the @ref GLFW_BUILD_WAYLAND CMake +option. @code{.sh} -cmake -S path/to/glfw -B path/to/build -D GLFW_USE_WAYLAND=1 +cmake -S path/to/glfw -B path/to/build -D GLFW_BUILD_WAYLAND=1 @endcode Once you have generated the project files or makefiles for your chosen @@ -255,24 +263,25 @@ build GLFW as a static library, `SHARED` to build it as a shared library @anchor GLFW_BUILD_EXAMPLES __GLFW_BUILD_EXAMPLES__ determines whether the GLFW examples are built along with the library. This is enabled by default unless GLFW is being built -as a sub-project of a larger CMake project. +as a subproject of a larger CMake project. @anchor GLFW_BUILD_TESTS __GLFW_BUILD_TESTS__ determines whether the GLFW test programs are built along with the library. This is enabled by default unless GLFW is being -built as a sub-project of a larger CMake project. +built as a subproject of a larger CMake project. @anchor GLFW_BUILD_DOCS __GLFW_BUILD_DOCS__ determines whether the GLFW documentation is built along with the library. This is enabled by default if [Doxygen](https://www.doxygen.nl/) is found by CMake during configuration. -@anchor GLFW_VULKAN_STATIC -__GLFW_VULKAN_STATIC__ determines whether to use the Vulkan loader linked -directly with the application. This is disabled by default. +@subsection compile_options_win32 Win32 specific CMake options -@subsection compile_options_win32 Windows specific CMake options +@anchor GLFW_BUILD_WIN32 +__GLFW_BUILD_WIN32__ determines whether to include support for Win32 when compiling the +library. This option is only available when compiling for Windows. This is enabled by +default. @anchor USE_MSVC_RUNTIME_LIBRARY_DLL __USE_MSVC_RUNTIME_LIBRARY_DLL__ determines whether to use the DLL version or the @@ -292,12 +301,25 @@ will not work if GLFW is built as a DLL. This is disabled by default, letting the operating system and driver decide. -@subsection compile_options_wayland Wayland specific CMake options +@subsection compile_options_macos macOS specific CMake options -@anchor GLFW_USE_WAYLAND -__GLFW_USE_WAYLAND__ determines whether to compile the library for Wayland. -This option is only available on Linux and other Unix-like systems other than -macOS. This is disabled by default. +@anchor GLFW_BUILD_COCOA +__GLFW_BUILD_COCOA__ determines whether to include support for Cocoa when compiling the +library. This option is only available when compiling for macOS. This is enabled by +default. + + +@subsection compile_options_unix Unix-like system specific CMake options + +@anchor GLFW_BUILD_WAYLAND +__GLFW_BUILD_WAYLAND__ determines whether to include support for Wayland when compiling +the library. This option is only available when compiling for Linux and other Unix-like +systems other than macOS. This is disabled by default. + +@anchor GLFW_BUILD_X11 +__GLFW_BUILD_X11__ determines whether to include support for X11 when compiling the +library. This option is only available when compiling for Linux and other Unix-like +systems other than macOS. This is enabled by default. @section compile_mingw_cross Cross-compilation with CMake and MinGW @@ -335,34 +357,30 @@ For more details see the @section compile_manual Compiling GLFW manually -If you wish to compile GLFW without its CMake build environment then you will -have to do at least some of the platform detection yourself. GLFW needs -a configuration macro to be defined in order to know what window system it is -being compiled for and also has optional, platform-specific ones for various -features. +If you wish to compile GLFW without its CMake build environment then you will have to do +at least some platform-detection yourself. There are preprocessor macros for +enabling support for the platforms (window systems) available. There are also optional, +platform-specific macros for various features. -When building with CMake, the `glfw_config.h` configuration header is generated -based on the current platform and CMake options. The GLFW CMake environment -defines @b GLFW_USE_CONFIG_H, which causes this header to be included by -`internal.h`. Without this macro, GLFW will expect the necessary configuration -macros to be defined on the command-line. +When building, GLFW will expect the necessary configuration macros to be defined +on the command-line. The GLFW CMake files set these as private compile +definitions on the GLFW target but if you compile the GLFW sources manually you +will need to define them yourself. -The window creation API is used to create windows, handle input, monitors, gamma -ramps and clipboard. The options are: +The window system is used to create windows, handle input, monitors, gamma ramps and +clipboard. The options are: - @b _GLFW_COCOA to use the Cocoa frameworks - @b _GLFW_WIN32 to use the Win32 API - @b _GLFW_X11 to use the X Window System - - @b _GLFW_WAYLAND to use the Wayland API (experimental and incomplete) - - @b _GLFW_OSMESA to use the OSMesa API (headless and non-interactive) + - @b _GLFW_WAYLAND to use the Wayland API (incomplete) + +The @b _GLFW_WAYLAND and @b _GLFW_X11 macros may be combined and produces a library that +attempts to detect the appropriate platform at initialization. If you are building GLFW as a shared library / dynamic library / DLL then you must also define @b _GLFW_BUILD_DLL. Otherwise, you must not define it. -If you are linking the Vulkan loader directly with your application then you -must also define @b _GLFW_VULKAN_STATIC. Otherwise, GLFW will attempt to use the -external version. - If you are using a custom name for the Vulkan, EGL, GLX, OSMesa, OpenGL, GLESv1 or GLESv2 library, you can override the default names by defining those you need of @b _GLFW_VULKAN_LIBRARY, @b _GLFW_EGL_LIBRARY, @b _GLFW_GLX_LIBRARY, @b diff --git a/docs/context.dox b/docs/context.dox index c51e268c..c64a0709 100644 --- a/docs/context.dox +++ b/docs/context.dox @@ -61,7 +61,7 @@ information. The name and number of this chapter unfortunately varies between versions and APIs, but has at times been named _Shared Objects and Multiple Contexts_. -GLFW comes with a barebones object sharing example program called `sharing`. +GLFW comes with a bare-bones object sharing example program called `sharing`. @subsection context_offscreen Offscreen contexts @@ -189,7 +189,7 @@ it suppresses the development environment's OpenGL or OpenGL ES header. #include @endcode -Finally you need to initialize glad once you have a suitable current context. +Finally, you need to initialize glad once you have a suitable current context. @code window = glfwCreateWindow(640, 480, "My Window", NULL, NULL); @@ -205,7 +205,7 @@ gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); Once glad has been loaded, you have access to all OpenGL core and extension functions supported by both the context you created and the glad loader you -generated and you are ready to start rendering. +generated. After that, you are ready to start rendering. You can specify a minimum required OpenGL or OpenGL ES version with [context hints](@ref window_hints_ctx). If your needs are more complex, you can diff --git a/docs/extra.css b/docs/extra.css index 05c1938c..1a287343 100644 --- a/docs/extra.css +++ b/docs/extra.css @@ -1 +1,2 @@ -.sm-dox,.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted,.sm-dox ul a:hover{background:none;text-shadow:none}.sm-dox a span.sub-arrow{border-color:#f2f2f2 transparent transparent transparent}.sm-dox a span.sub-arrow:active,.sm-dox a span.sub-arrow:focus,.sm-dox a span.sub-arrow:hover,.sm-dox a:hover span.sub-arrow{border-color:#f60 transparent transparent transparent}.sm-dox ul a span.sub-arrow:active,.sm-dox ul a span.sub-arrow:focus,.sm-dox ul a span.sub-arrow:hover,.sm-dox ul a:hover span.sub-arrow{border-color:transparent transparent transparent #f60}.sm-dox ul a:hover{background:#666;text-shadow:none}.sm-dox ul.sm-nowrap a{color:#4d4d4d;text-shadow:none}#main-nav,#main-menu,#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li,.memdoc,dl.reflist dd,div.toc li,.ah,span.lineno,span.lineno a,span.lineno a:hover,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,.doxtable code,.markdownTable code{background:none}#titlearea,.footer,.contents,div.header,.memdoc,table.doxtable td,table.doxtable th,table.markdownTable td,table.markdownTable th,hr,.memSeparator{border:none}#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li,.reflist dt a.el,.levels span,.directory .levels span{text-shadow:none}.memdoc,dl.reflist dd{box-shadow:none}div.headertitle,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,table.doxtable code,table.markdownTable code{padding:0}#nav-path,.directory .levels,span.lineno{display:none}html,#titlearea,.footer,tr.even,.directory tr.even,.doxtable tr:nth-child(even),tr.markdownTableBody:nth-child(even),.mdescLeft,.mdescRight,.memItemLeft,.memItemRight,code,.markdownTableRowEven{background:#f2f2f2}body{color:#4d4d4d}h1,h2,h2.groupheader,h3,div.toc h3,h4,h5,h6,strong,em{color:#1a1a1a;border-bottom:none}h1{padding-top:.5em;font-size:180%}h2{padding-top:.5em;margin-bottom:0;font-size:140%}h3{padding-top:.5em;margin-bottom:0;font-size:110%}.glfwheader{font-size:16px;min-height:64px;max-width:920px;padding:0 32px;margin:0 auto;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:center;align-content:stretch}#glfwhome{line-height:64px;padding-right:48px;color:#666;font-size:2.5em;background:url("https://www.glfw.org/css/arrow.png") no-repeat right}.glfwnavbar{list-style-type:none;margin:0 0 0 auto;float:right}#glfwhome,.glfwnavbar li{float:left}.glfwnavbar a,.glfwnavbar a:visited{line-height:64px;margin-left:2em;display:block;color:#666}.glfwnavbar{padding-left:0}#glfwhome,.glfwnavbar a,.glfwnavbar a:visited{transition:.35s ease}#titlearea,.footer{color:#666}address.footer{text-align:center;padding:2em;margin-top:3em}#top{background:#666}#main-nav{max-width:960px;margin:0 auto;font-size:13px}#main-menu{max-width:920px;margin:0 auto;font-size:13px}.memtitle{display:none}.memproto,.memname{font-weight:bold;text-shadow:none}#main-menu{min-height:36px;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:center;align-content:stretch}#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li{color:#f2f2f2}#main-menu li ul.sm-nowrap li a{color:#4d4d4d}#main-menu li ul.sm-nowrap li a:hover{color:#f60}#main-menu>li:last-child{margin:0 0 0 auto}.contents{min-height:590px}div.contents,div.header{max-width:920px;margin:0 auto;padding:0 32px;background:#fff none}table.doxtable th,table.markdownTable th,dl.reflist dt{background:linear-gradient(to bottom, #ffa733 0%, #ff6600 100%);box-shadow:inset 0 0 32px #f60;text-shadow:0 -1px 1px #b34700;text-align:left;color:#fff}dl.reflist dt a.el{color:#f60;padding:.2em;border-radius:4px;background-color:#ffe0cc}div.toc{float:none;width:auto}div.toc h3{font-size:1.17em}div.toc ul{padding-left:1.5em}div.toc li{font-size:1em;padding-left:0;list-style-type:disc}div.toc,.memproto,div.qindex,div.ah{background:linear-gradient(to bottom, #f2f2f2 0%, #e6e6e6 100%);box-shadow:inset 0 0 32px #e6e6e6;text-shadow:0 1px 1px #fff;color:#1a1a1a;border:2px solid #e6e6e6;border-radius:4px}.paramname{color:#803300}dl.reflist dt{border:2px solid #f60;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom:none}dl.reflist dd{border:2px solid #f60;border-bottom-right-radius:4px;border-bottom-left-radius:4px;border-top:none}table.doxtable,table.markdownTable{border-collapse:inherit;border-spacing:0;border:2px solid #f60;border-radius:4px}a,a:hover,a:visited,a:visited:hover,.contents a:visited,.el,a.el:visited,#glfwhome:hover,#main-menu a:hover,span.lineno a:hover{color:#f60;text-decoration:none}div.directory{border-collapse:inherit;border-spacing:0;border:2px solid #f60;border-radius:4px}hr,.memSeparator{height:2px;background:linear-gradient(to right, #f2f2f2 0%, #d9d9d9 50%, #f2f2f2 100%)}dl.note,dl.pre,dl.post,dl.invariant{background:linear-gradient(to bottom, #ddfad1 0%, #cbf7ba 100%);box-shadow:inset 0 0 32px #baf5a3;color:#1e5309;border:2px solid #afe699}dl.warning,dl.attention{background:linear-gradient(to bottom, #fae8d1 0%, #f7ddba 100%);box-shadow:inset 0 0 32px #f5d1a3;color:#533309;border:2px solid #e6c499}dl.deprecated,dl.bug{background:linear-gradient(to bottom, #fad1e3 0%, #f7bad6 100%);box-shadow:inset 0 0 32px #f5a3c8;color:#53092a;border:2px solid #e699bb}dl.todo,dl.test{background:linear-gradient(to bottom, #d1ecfa 0%, #bae3f7 100%);box-shadow:inset 0 0 32px #a3daf5;color:#093a53;border:2px solid #99cce6}dl.note,dl.pre,dl.post,dl.invariant,dl.warning,dl.attention,dl.deprecated,dl.bug,dl.todo,dl.test{border-radius:4px;padding:1em;text-shadow:0 1px 1px #fff;margin:1em 0}.note a,.pre a,.post a,.invariant a,.warning a,.attention a,.deprecated a,.bug a,.todo a,.test a,.note a:visited,.pre a:visited,.post a:visited,.invariant a:visited,.warning a:visited,.attention a:visited,.deprecated a:visited,.bug a:visited,.todo a:visited,.test a:visited{color:inherit}div.line{line-height:inherit}div.fragment,pre.fragment{background:#f2f2f2;border-radius:4px;border:none;padding:1em;overflow:auto;border-left:4px solid #ccc;margin:1em 0}.lineno a,.lineno a:visited,.line,pre.fragment{color:#4d4d4d}span.preprocessor,span.comment{color:#007899}a.code,a.code:visited{color:#e64500}span.keyword,span.keywordtype,span.keywordflow{color:#404040;font-weight:bold}span.stringliteral{color:#360099}code{padding:.1em;border-radius:4px}/*# sourceMappingURL=extra.css.map */ +.sm-dox,.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted,.sm-dox ul a:hover{background:none;text-shadow:none}.sm-dox a span.sub-arrow{border-color:#f2f2f2 transparent transparent transparent}.sm-dox a span.sub-arrow:active,.sm-dox a span.sub-arrow:focus,.sm-dox a span.sub-arrow:hover,.sm-dox a:hover span.sub-arrow{border-color:#f60 transparent transparent transparent}.sm-dox ul a span.sub-arrow:active,.sm-dox ul a span.sub-arrow:focus,.sm-dox ul a span.sub-arrow:hover,.sm-dox ul a:hover span.sub-arrow{border-color:transparent transparent transparent #f60}.sm-dox ul a:hover{background:#666;text-shadow:none}.sm-dox ul.sm-nowrap a{color:#4d4d4d;text-shadow:none}#main-nav,#main-menu,#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li,.memdoc,dl.reflist dd,div.toc li,.ah,span.lineno,span.lineno a,span.lineno a:hover,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,.doxtable code,.markdownTable code{background:none}#titlearea,.footer,.contents,div.header,.memdoc,table.doxtable td,table.doxtable th,table.markdownTable td,table.markdownTable th,hr,.memSeparator{border:none}#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li,.reflist dt a.el,.levels span,.directory .levels span{text-shadow:none}.memdoc,dl.reflist dd{box-shadow:none}div.headertitle,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,table.doxtable code,table.markdownTable code{padding:0}#nav-path,.directory .levels,span.lineno{display:none}html,#titlearea,.footer,tr.even,.directory tr.even,.doxtable tr:nth-child(even),tr.markdownTableBody:nth-child(even),.mdescLeft,.mdescRight,.memItemLeft,.memItemRight,code,.markdownTableRowEven{background:#f2f2f2}body{color:#4d4d4d}div.title{font-size:170%;margin:1em 0 0.5em 0}h1,h2,h2.groupheader,h3,div.toc h3,h4,h5,h6,strong,em{color:#1a1a1a;border-bottom:none}h1{padding-top:0.5em;font-size:150%}h2{padding-top:0.5em;margin-bottom:0;font-size:130%}h3{padding-top:0.5em;margin-bottom:0;font-size:110%}.glfwheader{font-size:16px;min-height:64px;max-width:920px;padding:0 32px;margin:0 auto;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:center;align-content:stretch}#glfwhome{line-height:64px;padding-right:48px;color:#666;font-size:2.5em;background:url("https://www.glfw.org/css/arrow.png") no-repeat right}.glfwnavbar{list-style-type:none;margin:0 0 0 auto;float:right}#glfwhome,.glfwnavbar li{float:left}.glfwnavbar a,.glfwnavbar a:visited{line-height:64px;margin-left:2em;display:block;color:#666}.glfwnavbar{padding-left:0}#glfwhome,.glfwnavbar a,.glfwnavbar a:visited{transition:.35s ease}#titlearea,.footer{color:#666}address.footer{text-align:center;padding:2em;margin-top:3em}#top{background:#666}#main-nav{max-width:960px;margin:0 auto;font-size:13px}#main-menu{max-width:920px;margin:0 auto;font-size:13px}.memtitle{display:none}.memproto,.memname{font-weight:bold;text-shadow:none}#main-menu{min-height:36px;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:center;align-content:stretch}#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li{color:#f2f2f2}#main-menu li ul.sm-nowrap li a{color:#4d4d4d}#main-menu li ul.sm-nowrap li a:hover{color:#f60}#main-menu>li:last-child{margin:0 0 0 auto}.contents{min-height:590px}div.contents,div.header{max-width:920px;margin:0 auto;padding:0 32px;background:#fff none}table.doxtable th,table.markdownTable th,dl.reflist dt{background:linear-gradient(to bottom, #ffa733 0%, #f60 100%);box-shadow:inset 0 0 32px #f60;text-shadow:0 -1px 1px #b34700;text-align:left;color:#fff}dl.reflist dt a.el{color:#f60;padding:.2em;border-radius:4px;background-color:#ffe0cc}div.toc{float:right;width:35%}@media screen and (max-width: 600px){div.toc{float:none;width:inherit;margin:0}}div.toc h3{font-size:1.17em}div.toc ul{padding-left:1.5em}div.toc li{font-size:1em;padding-left:0;list-style-type:disc}div.toc li.level2,div.toc li.level3{margin-left:0.5em}div.toc,.memproto,div.qindex,div.ah{background:linear-gradient(to bottom, #f2f2f2 0%, #e6e6e6 100%);box-shadow:inset 0 0 32px #e6e6e6;text-shadow:0 1px 1px #fff;color:#1a1a1a;border:2px solid #e6e6e6;border-radius:4px}.paramname{color:#803300}dl.reflist dt{border:2px solid #f60;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom:none}dl.reflist dd{border:2px solid #f60;border-bottom-right-radius:4px;border-bottom-left-radius:4px;border-top:none}table.doxtable,table.markdownTable{border-collapse:inherit;border-spacing:0;border:2px solid #f60;border-radius:4px}a,a:hover,a:visited,a:visited:hover,.contents a:visited,.el,a.el:visited,#glfwhome:hover,#main-menu a:hover,span.lineno a:hover{color:#f60;text-decoration:none}div.directory{border-collapse:inherit;border-spacing:0;border:2px solid #f60;border-radius:4px}hr,.memSeparator{height:2px;background:linear-gradient(to right, #f2f2f2 0%, #d9d9d9 50%, #f2f2f2 100%)}dl.note,dl.pre,dl.post,dl.invariant{background:linear-gradient(to bottom, #ddfad1 0%, #cbf7ba 100%);box-shadow:inset 0 0 32px #baf5a3;color:#1e5309;border:2px solid #afe699}dl.warning,dl.attention{background:linear-gradient(to bottom, #fae8d1 0%, #f7ddba 100%);box-shadow:inset 0 0 32px #f5d1a3;color:#533309;border:2px solid #e6c499}dl.deprecated,dl.bug{background:linear-gradient(to bottom, #fad1e3 0%, #f7bad6 100%);box-shadow:inset 0 0 32px #f5a3c8;color:#53092a;border:2px solid #e699bb}dl.todo,dl.test{background:linear-gradient(to bottom, #d1ecfa 0%, #bae3f7 100%);box-shadow:inset 0 0 32px #a3daf5;color:#093a53;border:2px solid #99cce6}dl.note,dl.pre,dl.post,dl.invariant,dl.warning,dl.attention,dl.deprecated,dl.bug,dl.todo,dl.test{border-radius:4px;padding:1em;text-shadow:0 1px 1px #fff;margin:1em 0}.note a,.pre a,.post a,.invariant a,.warning a,.attention a,.deprecated a,.bug a,.todo a,.test a,.note a:visited,.pre a:visited,.post a:visited,.invariant a:visited,.warning a:visited,.attention a:visited,.deprecated a:visited,.bug a:visited,.todo a:visited,.test a:visited{color:inherit}div.line{line-height:inherit}div.fragment,pre.fragment{background:#f2f2f2;border-radius:4px;border:none;padding:1em;overflow:auto;border-left:4px solid #ccc;margin:1em 0}.lineno a,.lineno a:visited,.line,pre.fragment{color:#4d4d4d}span.preprocessor,span.comment{color:#007899}a.code,a.code:visited{color:#e64500}span.keyword,span.keywordtype,span.keywordflow{color:#404040;font-weight:bold}span.stringliteral{color:#360099}code{padding:.1em;border-radius:4px} +/*# sourceMappingURL=extra.css.map */ diff --git a/docs/extra.css.map b/docs/extra.css.map index 7d10c5e2..4d9333c2 100644 --- a/docs/extra.css.map +++ b/docs/extra.css.map @@ -1 +1,7 @@ -{"version":3,"sourceRoot":"","sources":["extra.scss"],"names":[],"mappings":"AA8EA,4GACI,gBACA,iBAGJ,yBACC,yDAGD,6HACC,sDAGD,yIACC,sDAGD,mBACI,WA9EuB,KA+EvB,iBAGJ,uBACC,MAzFoB,QA0FjB,iBAGJ,6UACC,gBAGD,mJACC,YAGD,yHACC,iBAGD,sBACC,gBAGD,4LACC,UAGD,yCACC,aAGD,kMACC,WAnHgC,QAsHjC,KACC,MA1HoB,QA6HrB,sDACC,MA/Ge,QAgHf,mBAGD,GACE,iBACA,eAGF,GACE,iBACA,gBACA,eAGF,GACE,iBACA,gBACA,eAGF,YACC,eACA,gBACA,gBACA,eACA,cAEA,aACA,mBACA,eACA,2BACA,mBACA,sBAGD,UACC,iBACA,mBACA,MA/J0B,KAgK1B,gBACA,qEAGD,YACC,qBACA,kBACA,YAGD,yBACC,WAGD,oCACC,iBACA,gBACA,cACA,MAlL0B,KAqL3B,YACC,eAGD,8CACC,qBAGD,mBACC,MA9L0B,KAiM3B,eACC,kBACA,YACA,eAGD,KACC,WAxM0B,KA2M3B,UACC,gBACA,cACA,eAGD,WACC,gBACA,cACA,eAGD,UACI,aAGJ,mBACI,iBACA,iBAGJ,WACC,gBACA,aACA,mBACA,eACA,2BACA,mBACA,sBAGD,mEACC,MA9OgC,QAiPjC,gCACC,MArPoB,QAwPrB,sCACC,MAjOoB,KAoOrB,yBACC,kBAGD,UACC,iBAGD,wBACC,gBACA,cACA,eACA,qBAGD,uDACC,gEACA,+BACA,+BACA,gBACA,MArPgB,KAwPjB,mBACC,MA5PoB,KA6PpB,aACA,kBACA,yBAGD,QACC,WACA,WAGD,WACC,iBAGD,WACC,mBAGD,WACC,cACA,eACA,qBAGD,oCACC,gEACA,kCACA,2BACA,MAlSe,QAmSf,yBACA,kBAGD,WACC,MA3QuB,QA8QxB,cACC,sBACA,2BACA,4BACA,mBAGD,cACC,sBACA,+BACA,8BACA,gBAGD,mCACC,wBACA,iBACA,sBACA,kBAGD,gIACC,MAxToB,KAyTpB,qBAGD,cACC,wBACA,iBACA,sBACA,kBAGD,iBACC,WACA,4EAGD,oCApSC,gEACA,kCACA,cACA,yBAqSD,wBAxSC,gEACA,kCACA,cACA,yBAySD,qBA5SC,gEACA,kCACA,cACA,yBA6SD,gBAhTC,gEACA,kCACA,cACA,yBAiTD,iGACC,kBACA,YACA,2BACA,aAGD,kRACC,cAGD,SACC,oBAGD,0BACC,mBACA,kBACA,YACA,YACA,cACA,2BACA,aAGD,+CACC,MA1YoB,QA6YrB,+BACC,cAGD,sBACC,cAGD,+CACC,cACA,iBAGD,mBACC,cAGD,KACC,aACA","file":"extra.css"} \ No newline at end of file +{ +"version": 3, +"mappings": "AA8EA,2GAA4G,CAC3G,UAAU,CAAC,IAAI,CACf,WAAW,CAAC,IAAI,CAGjB,wBAAyB,CACxB,YAAY,CAAC,2CAAsD,CAGpE,4HAA6H,CAC5H,YAAY,CAAC,wCAAuD,CAGrE,wIAAyI,CACxI,YAAY,CAAC,wCAAuD,CAGrE,kBAAmB,CAClB,UAAU,CA9EgB,IAAa,CA+EvC,WAAW,CAAC,IAAI,CAGjB,sBAAuB,CACtB,KAAK,CAzFe,OAAa,CA0FjC,WAAW,CAAC,IAAI,CAGjB,4UAA6U,CAC5U,UAAU,CAAC,IAAI,CAGhB,kJAAmJ,CAClJ,MAAM,CAAC,IAAI,CAGZ,wHAAyH,CACxH,WAAW,CAAC,IAAI,CAGjB,qBAAsB,CACrB,UAAU,CAAC,IAAI,CAGhB,2LAA4L,CAC3L,OAAO,CAAC,CAAC,CAGV,wCAAyC,CACxC,OAAO,CAAC,IAAI,CAGb,iMAAkM,CACjM,UAAU,CApGW,OAA+B,CAuGrD,IAAK,CACJ,KAAK,CA1He,OAAa,CA6HlC,SAAU,CACN,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,aAAa,CAGzB,qDAAsD,CACrD,KAAK,CApHU,OAAa,CAqH5B,aAAa,CAAC,IAAI,CAGnB,EAAG,CACF,WAAW,CAAC,KAAK,CACjB,SAAS,CAAC,IAAI,CAGf,EAAG,CACF,WAAW,CAAC,KAAK,CACjB,aAAa,CAAC,CAAC,CACf,SAAS,CAAC,IAAI,CAGf,EAAG,CACF,WAAW,CAAC,KAAK,CACjB,aAAa,CAAC,CAAC,CACf,SAAS,CAAC,IAAI,CAGf,WAAY,CACX,SAAS,CAAC,IAAI,CACd,UAAU,CAAC,IAAI,CACf,SAAS,CAAC,KAAK,CACf,OAAO,CAAC,MAAM,CACd,MAAM,CAAC,MAAM,CAEb,OAAO,CAAE,IAAI,CACb,cAAc,CAAE,GAAG,CACnB,SAAS,CAAE,IAAI,CACf,eAAe,CAAE,UAAU,CAC3B,WAAW,CAAE,MAAM,CACnB,aAAa,CAAE,OAAO,CAGvB,SAAU,CACT,WAAW,CAAC,IAAI,CAChB,aAAa,CAAC,IAAI,CAClB,KAAK,CApKqB,IAAa,CAqKvC,SAAS,CAAC,KAAK,CACf,UAAU,CAAC,yDAAyD,CAGrE,WAAY,CACX,eAAe,CAAC,IAAI,CACpB,MAAM,CAAC,UAAU,CACjB,KAAK,CAAC,KAAK,CAGZ,wBAAyB,CACxB,KAAK,CAAC,IAAI,CAGX,mCAAoC,CACnC,WAAW,CAAC,IAAI,CAChB,WAAW,CAAC,GAAG,CACf,OAAO,CAAC,KAAK,CACb,KAAK,CAvLqB,IAAa,CA0LxC,WAAY,CACX,YAAY,CAAE,CAAC,CAGhB,6CAA8C,CAC7C,UAAU,CAAC,SAAS,CAGrB,kBAAmB,CAClB,KAAK,CAnMqB,IAAa,CAsMxC,cAAe,CACd,UAAU,CAAC,MAAM,CACjB,OAAO,CAAC,GAAG,CACX,UAAU,CAAC,GAAG,CAGf,IAAK,CACJ,UAAU,CA7MgB,IAAa,CAgNxC,SAAU,CACT,SAAS,CAAC,KAAK,CACf,MAAM,CAAC,MAAM,CACb,SAAS,CAAC,IAAI,CAGf,UAAW,CACV,SAAS,CAAC,KAAK,CACf,MAAM,CAAC,MAAM,CACb,SAAS,CAAC,IAAI,CAGf,SAAU,CACT,OAAO,CAAC,IAAI,CAGb,kBAAmB,CAClB,WAAW,CAAC,IAAI,CAChB,WAAW,CAAC,IAAI,CAGjB,UAAW,CACV,UAAU,CAAC,IAAI,CACf,OAAO,CAAE,IAAI,CACb,cAAc,CAAE,GAAG,CACnB,SAAS,CAAE,IAAI,CACf,eAAe,CAAE,UAAU,CAC3B,WAAW,CAAE,MAAM,CACnB,aAAa,CAAE,OAAO,CAGvB,kEAAmE,CAClE,KAAK,CApOgB,OAA+B,CAuOrD,+BAAgC,CAC/B,KAAK,CA1Pe,OAAa,CA6PlC,qCAAsC,CACrC,KAAK,CA1NoB,IAAsB,CA6NhD,wBAA2B,CAC1B,MAAM,CAAE,UAAU,CAGnB,SAAU,CACT,UAAU,CAAC,KAAK,CAGjB,uBAAwB,CACvB,SAAS,CAAC,KAAK,CACf,MAAM,CAAC,MAAM,CACb,OAAO,CAAC,MAAM,CACd,UAAU,CAAC,SAA8B,CAG1C,sDAAuD,CACtD,UAAU,CAAC,iDAAoF,CAC/F,UAAU,CAAC,mBAAuC,CAClD,WAAW,CAAC,kBAAgD,CAC5D,UAAU,CAAC,IAAI,CACf,KAAK,CAlPa,IAAe,CAqPlC,kBAAmB,CAClB,KAAK,CArPoB,IAAsB,CAsP/C,OAAO,CAAC,IAAI,CACZ,aAAa,CAAC,GAAG,CACjB,gBAAgB,CAAC,OAAiC,CAGnD,OAAQ,CACP,KAAK,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CAGV,oCAAoC,CACnC,OAAQ,CACP,KAAK,CAAC,IAAI,CACV,KAAK,CAAC,OAAO,CACb,MAAM,CAAC,CAAC,EAIV,UAAW,CACV,SAAS,CAAC,MAAM,CAGjB,UAAW,CACV,YAAY,CAAC,KAAK,CAGnB,UAAW,CACV,SAAS,CAAC,GAAG,CACb,YAAY,CAAC,CAAC,CACd,eAAe,CAAC,IAAI,CAIjB,mCAAqB,CACjB,WAAW,CAAC,KAAK,CAIzB,mCAAoC,CACnC,UAAU,CAAC,oDAAgF,CAC3F,UAAU,CAAC,sBAAqC,CAChD,WAAW,CAAC,cAA8C,CAC1D,KAAK,CArTU,OAAa,CAsT5B,MAAM,CAAC,iBAAgC,CACvC,aAAa,CAAC,GAAG,CAGlB,UAAW,CACV,KAAK,CA9RkB,OAAgC,CAiSxD,aAAc,CACb,MAAM,CAAC,cAA+B,CACtC,sBAAsB,CAAC,GAAG,CAC1B,uBAAuB,CAAC,GAAG,CAC3B,aAAa,CAAC,IAAI,CAGnB,aAAc,CACb,MAAM,CAAC,cAA+B,CACtC,0BAA0B,CAAC,GAAG,CAC9B,yBAAyB,CAAC,GAAG,CAC7B,UAAU,CAAC,IAAI,CAGhB,kCAAmC,CAClC,eAAe,CAAC,OAAO,CACvB,cAAc,CAAC,CAAC,CAChB,MAAM,CAAC,cAA+B,CACtC,aAAa,CAAC,GAAG,CAGlB,+HAAgI,CAC/H,KAAK,CA/ToB,IAAsB,CAgU/C,eAAe,CAAC,IAAI,CAGrB,aAAc,CACb,eAAe,CAAC,OAAO,CACvB,cAAc,CAAC,CAAC,CAChB,MAAM,CAAC,cAA+B,CACtC,aAAa,CAAC,GAAG,CAGlB,gBAAiB,CAChB,MAAM,CAAC,GAAG,CACV,UAAU,CAAC,gEAAiH,CAG7H,mCAAoC,CAvTnC,UAAU,CAAC,oDAAuE,CAClF,UAAU,CAAC,sBAAsC,CACjD,KAAK,CAAC,OAAwB,CAC9B,MAAM,CAAC,iBAAmD,CAwT3D,uBAAwB,CA3TvB,UAAU,CAAC,oDAAuE,CAClF,UAAU,CAAC,sBAAsC,CACjD,KAAK,CAAC,OAAwB,CAC9B,MAAM,CAAC,iBAAmD,CA4T3D,oBAAqB,CA/TpB,UAAU,CAAC,oDAAuE,CAClF,UAAU,CAAC,sBAAsC,CACjD,KAAK,CAAC,OAAwB,CAC9B,MAAM,CAAC,iBAAmD,CAgU3D,eAAgB,CAnUf,UAAU,CAAC,oDAAuE,CAClF,UAAU,CAAC,sBAAsC,CACjD,KAAK,CAAC,OAAwB,CAC9B,MAAM,CAAC,iBAAmD,CAoU3D,gGAAiG,CAChG,aAAa,CAAC,GAAG,CACjB,OAAO,CAAC,GAAG,CACX,WAAW,CAAC,cAAwB,CACpC,MAAM,CAAC,KAAK,CAGb,iRAAkR,CACjR,KAAK,CAAC,OAAO,CAGd,QAAS,CACR,WAAW,CAAC,OAAO,CAGpB,yBAA0B,CACzB,UAAU,CAAC,OAAa,CACxB,aAAa,CAAC,GAAG,CACjB,MAAM,CAAC,IAAI,CACX,OAAO,CAAC,GAAG,CACX,QAAQ,CAAC,IAAI,CACb,WAAW,CAAC,cAAuB,CACnC,MAAM,CAAC,KAAK,CAGb,8CAA+C,CAC9C,KAAK,CA7Ze,OAAa,CAgalC,8BAA+B,CAC9B,KAAK,CAAC,OAAiB,CAGxB,qBAAsB,CACrB,KAAK,CAAC,OAAgB,CAGvB,8CAA+C,CAC9C,KAAK,CAAC,OAA+B,CACrC,WAAW,CAAC,IAAI,CAGjB,kBAAmB,CAClB,KAAK,CAAC,OAAiB,CAGxB,IAAK,CACJ,OAAO,CAAC,IAAI,CACZ,aAAa,CAAC,GAAG", +"sources": ["extra.scss"], +"names": [], +"file": "extra.css" +} diff --git a/docs/extra.scss b/docs/extra.scss index 6c5f3c25..43fe9831 100644 --- a/docs/extra.scss +++ b/docs/extra.scss @@ -135,6 +135,11 @@ body { color:$default-text-color; } +div.title { + font-size: 170%; + margin: 1em 0 0.5em 0; +} + h1,h2,h2.groupheader,h3,div.toc h3,h4,h5,h6,strong,em { color:$heading-color; border-bottom:none; @@ -142,13 +147,13 @@ h1,h2,h2.groupheader,h3,div.toc h3,h4,h5,h6,strong,em { h1 { padding-top:0.5em; - font-size:180%; + font-size:150%; } h2 { padding-top:0.5em; margin-bottom:0; - font-size:140%; + font-size:130%; } h3 { @@ -293,8 +298,16 @@ dl.reflist dt a.el { } div.toc { - float:none; - width:auto; + float:right; + width:35%; +} + +@media screen and (max-width:600px) { + div.toc { + float:none; + width:inherit; + margin:0; + } } div.toc h3 { @@ -311,6 +324,12 @@ div.toc li { list-style-type:disc; } +div.toc { + li.level2, li.level3 { + margin-left:0.5em; + } +} + div.toc,.memproto,div.qindex,div.ah { background:linear-gradient(to bottom,$toc-background-color2 0%,$toc-background-color1 100%); box-shadow:inset 0 0 32px $toc-background-color1; diff --git a/docs/input.dox b/docs/input.dox index dcd8f670..d3904f46 100644 --- a/docs/input.dox +++ b/docs/input.dox @@ -24,7 +24,7 @@ All input callbacks receive a window handle. By using the or objects from your callbacks. To get a better feel for how the various events callbacks behave, run the -`events` test program. It register every callback supported by GLFW and prints +`events` test program. It registers every callback supported by GLFW and prints out all arguments provided for every event, along with time and sequence information. @@ -123,9 +123,21 @@ void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod } @endcode -The action is one of `GLFW_PRESS`, `GLFW_REPEAT` or `GLFW_RELEASE`. The key -will be `GLFW_KEY_UNKNOWN` if GLFW lacks a key token for it, for example -_E-mail_ and _Play_ keys. +The action is one of `GLFW_PRESS`, `GLFW_REPEAT` or `GLFW_RELEASE`. Events with +`GLFW_PRESS` and `GLFW_RELEASE` actions are emitted for every key press. Most +keys will also emit events with `GLFW_REPEAT` actions while a key is held down. + +Key events with `GLFW_REPEAT` actions are intended for text input. They are +emitted at the rate set in the user's keyboard settings. At most one key is +repeated even if several keys are held down. `GLFW_REPEAT` actions should not +be relied on to know which keys are being held down or to drive animation. +Instead you should either save the state of relevant keys based on `GLFW_PRESS` +and `GLFW_RELEASE` actions, or call @ref glfwGetKey, which provides basic cached +key state. + +The key will be one of the existing [key tokens](@ref keys), or +`GLFW_KEY_UNKNOWN` if GLFW lacks a token for it, for example _E-mail_ and _Play_ +keys. The scancode is unique for every key, regardless of whether it has a key token. Scancodes are platform-specific but consistent over time, so keys will have @@ -300,6 +312,16 @@ glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); This mode puts no limit on the motion of the cursor. +If you wish the cursor to be visible but confined to the content area of the +window, set the cursor mode to `GLFW_CURSOR_CAPTURED`. + +@code +glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_CAPTURED); +@endcode + +The cursor will behave normally inside the content area but will not be able to +leave unless the window loses focus. + To exit out of either of these special modes, restore the `GLFW_CURSOR_NORMAL` cursor mode. @@ -307,6 +329,8 @@ cursor mode. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); @endcode +If the cursor was disabled, this will move it back to its last visible position. + @anchor GLFW_RAW_MOUSE_MOTION @subsection raw_mouse_motion Raw mouse motion @@ -370,7 +394,7 @@ sequential rows, starting from the top-left corner. @subsubsection cursor_standard Standard cursor creation A cursor with a [standard shape](@ref shapes) from the current system cursor -theme can be can be created with @ref glfwCreateStandardCursor. +theme can be created with @ref glfwCreateStandardCursor. @code GLFWcursor* url_cursor = glfwCreateStandardCursor(GLFW_POINTING_HAND_CURSOR); @@ -821,7 +845,7 @@ The second value is always the human-readable name of the gamepad. All subsequent values are in the form `:` and describe the layout of the mapping. These fields may not all be present and may occur in any order. -The button fields are `a`, `b`, `c`, `d`, `back`, `start`, `guide`, `dpup`, +The button fields are `a`, `b`, `x`, `y`, `back`, `start`, `guide`, `dpup`, `dpright`, `dpdown`, `dpleft`, `leftshoulder`, `rightshoulder`, `leftstick` and `rightstick`. diff --git a/docs/internal.dox b/docs/internal.dox index 685c6d13..69227568 100644 --- a/docs/internal.dox +++ b/docs/internal.dox @@ -61,12 +61,21 @@ application-provided callbacks. It is also prohibited from modifying the platform-independent part of the internal structs. Instead, it calls the event interface when events interesting to GLFW are received. -The platform interface mirrors those parts of the public interface that needs to -perform platform-specific operations on some or all platforms. The are also -named the same except that the glfw function prefix is replaced by -_glfwPlatform. +The platform interface mostly mirrors those parts of the public interface that needs to +perform platform-specific operations on some or all platforms. -Examples: `_glfwPlatformCreateWindow` +The window system bits of the platform API is called through the `_GLFWplatform` struct of +function pointers, to allow runtime selection of platform. This includes the window and +context creation, input and event processing, monitor and Vulkan surface creation parts of +GLFW. This is located in the global `_glfw` struct. + +Examples: `_glfw.platform.createWindow` + +The timer, threading and module loading bits of the platform API are plain functions with +a `_glfwPlatform` prefix, as these things are independent of what window system is being +used. + +Examples: `_glfwPlatformGetTimerValue` The platform interface also defines structs that contain platform-specific global and per-object state. Their names mirror those of the internal @@ -104,8 +113,7 @@ Examples: `isValidElementForJoystick` @section internals_config Configuration macros GLFW uses a number of configuration macros to select at compile time which -interfaces and code paths to use. They are defined in the glfw_config.h header file, -which is generated from the `glfw_config.h.in` file by CMake. +interfaces and code paths to use. They are defined in the GLFW CMake target. Configuration macros the same style as tokens in the public interface, except with a leading underscore. diff --git a/docs/intro.dox b/docs/intro.dox index 4134c84d..79348323 100644 --- a/docs/intro.dox +++ b/docs/intro.dox @@ -30,10 +30,12 @@ successfully initialized, and only from the main thread. - @ref glfwGetVersion - @ref glfwGetVersionString + - @ref glfwPlatformSupported - @ref glfwGetError - @ref glfwSetErrorCallback - @ref glfwInitHint - @ref glfwInitAllocator + - @ref glfwInitVulkanLoader - @ref glfwInit - @ref glfwTerminate @@ -89,6 +91,15 @@ Setting these hints requires no platform specific headers or functions. @subsubsection init_hints_shared Shared init hints +@anchor GLFW_PLATFORM +__GLFW_PLATFORM__ specifies the platform to use for windowing and input. +Possible values are `GLFW_ANY_PLATFORM`, `GLFW_PLATFORM_WIN32`, +`GLFW_PLATFORM_COCOA`, `GLFW_PLATFORM_X11`, `GLFW_PLATFORM_WAYLAND` and +`GLFW_PLATFORM_NULL`. The default value is `GLFW_ANY_PLATFORM`, which will +choose any platform the library includes support for except for the Null +backend. + + @anchor GLFW_JOYSTICK_HAT_BUTTONS __GLFW_JOYSTICK_HAT_BUTTONS__ specifies whether to also expose joystick hats as buttons, for compatibility with earlier versions of GLFW that did not have @ref @@ -137,6 +148,7 @@ the `VK_KHR_xlib_surface` extension. Possible values are `GLFW_TRUE` and Initialization hint | Default value | Supported values -------------------------------- | ------------------------------- | ---------------- +@ref GLFW_PLATFORM | `GLFW_ANY_PLATFORM` | `GLFW_ANY_PLATFORM`, `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, `GLFW_PLATFORM_X11`, `GLFW_PLATFORM_WAYLAND` or `GLFW_PLATFORM_NULL` @ref GLFW_JOYSTICK_HAT_BUTTONS | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` @ref GLFW_ANGLE_PLATFORM_TYPE | `GLFW_ANGLE_PLATFORM_TYPE_NONE` | `GLFW_ANGLE_PLATFORM_TYPE_NONE`, `GLFW_ANGLE_PLATFORM_TYPE_OPENGL`, `GLFW_ANGLE_PLATFORM_TYPE_OPENGLES`, `GLFW_ANGLE_PLATFORM_TYPE_D3D9`, `GLFW_ANGLE_PLATFORM_TYPE_D3D11`, `GLFW_ANGLE_PLATFORM_TYPE_VULKAN` or `GLFW_ANGLE_PLATFORM_TYPE_METAL` @ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` @@ -144,6 +156,48 @@ Initialization hint | Default value | Supported v @ref GLFW_X11_XCB_VULKAN_SURFACE | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` +@subsection platform Runtime platform selection + +GLFW can be compiled for more than one platform (window system) at once. This lets +a single library binary support both X11 and Wayland on Linux and other Unix-like systems. + +You can control platform selection via the @ref GLFW_PLATFORM initialization hint. By +default, this is set to @ref GLFW_ANY_PLATFORM, which will look for supported window +systems in order of priority and select the first one it finds. It can also be set to any +specific platform to have GLFW only look for that one. + +@code +glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11); +@endcode + +This mechanism also provides the Null platform, which is always supported but needs to be +explicitly requested. This platform is effectively a stub, emulating a window system on +a single 1080p monitor, but will not interact with any actual window system. + +@code +glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_NULL); +@endcode + +You can test whether a library binary was compiled with support for a specific platform +with @ref glfwPlatformSupported. + +@code +if (glfwPlatformSupported(GLFW_PLATFORM_WAYLAND)) + glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_WAYLAND); +@endcode + +Once GLFW has been initialized, you can query which platform was selected with @ref +glfwGetPlatform. + +@code +int platform = glfwGetPlatform(); +@endcode + +If you are using any [native access functions](@ref native), especially on Linux and other +Unix-like systems, then you may need to check that you are calling the ones matching the +selected platform. + + @subsection init_allocator Custom heap memory allocator The heap memory allocator can be customized before initialization with @ref @@ -215,9 +269,9 @@ This will destroy any remaining window, monitor and cursor objects, restore any modified gamma ramps, re-enable the screensaver if it had been disabled and free any other resources allocated by GLFW. -Once the library is terminated, it is as if it had never been initialized and +Once the library is terminated, it is as if it had never been initialized, therefore you will need to initialize it again before being able to use GLFW. If the -library was not initialized or had already been terminated, it return +library was not initialized or had already been terminated, it returns immediately. @@ -337,14 +391,14 @@ which monitor the window is currently considered to be on. This section describes the conditions under which GLFW can be expected to function, barring bugs in the operating system or drivers. Use of GLFW outside -of these limits may work on some platforms, or on some machines, or some of the +these limits may work on some platforms, or on some machines, or some of the time, or on some versions of GLFW, but it may break at any time and this will not be considered a bug. @subsection lifetime Pointer lifetimes -GLFW will never free any pointer you provide to it and you must never free any +GLFW will never free any pointer you provide to it, and you must never free any pointer it provides to you. Many GLFW functions return pointers to dynamically allocated structures, strings @@ -437,6 +491,11 @@ Library version information may be queried from any thread. - @ref glfwGetVersion - @ref glfwGetVersionString +Platform information may be queried from any thread. + + - @ref glfwPlatformSupported + - @ref glfwGetPlatform + All Vulkan related functions may be called from any thread. - @ref glfwVulkanSupported @@ -529,17 +588,32 @@ __Do not use the version string__ to parse the GLFW library version. The @ref glfwGetVersion function already provides the version of the running library binary. +__Do not use the version string__ to parse what platforms are supported. The @ref +glfwPlatformSupported function lets you query platform support. + +__GLFW 3.4:__ The format of this string was changed to support the addition of +[runtime platform selection](@ref platform). + The format of the string is as follows: - The version of GLFW - - The name of the window system API - - The name of the context creation API - - Any additional options or APIs + - For each supported platform: + - The name of the window system API + - The name of the window system specific context creation API, if applicable + - The names of the always supported context creation APIs EGL and OSMesa + - Any additional compile-time options, APIs and (on Windows) what compiler was used -For example, when compiling GLFW 3.0 with MinGW using the Win32 and WGL -back ends, the version string may look something like this: +For example, compiling GLFW 3.4 with MinGW as a DLL for Windows, may result in a version string +like this: @code -3.0.0 Win32 WGL MinGW +3.4.0 Win32 WGL Null EGL OSMesa MinGW DLL +@endcode + +Compiling GLFW as a static library for Linux, with both Wayland and X11 enabled, may +result in a version string like this: + +@code +3.4.0 Wayland X11 GLX Null EGL OSMesa monotonic @endcode */ diff --git a/docs/monitor.dox b/docs/monitor.dox index 86eb4540..b4099dbf 100644 --- a/docs/monitor.dox +++ b/docs/monitor.dox @@ -138,7 +138,7 @@ glfwGetMonitorPhysicalSize(monitor, &width_mm, &height_mm); @endcode While this can be used to calculate the raw DPI of a monitor, this is often not -useful. Instead use the [monitor content scale](@ref monitor_scale) and +useful. Instead, use the [monitor content scale](@ref monitor_scale) and [window content scale](@ref window_scale) to scale your content. @@ -261,7 +261,7 @@ To experiment with gamma correction via the @ref glfwSetGamma function, run the `gamma` test program. @note The software controlled gamma ramp is applied _in addition_ to the -hardware gamma correction, which today is usually an approximation of sRGB +hardware gamma correction, which today is typically an approximation of sRGB gamma. This means that setting a perfectly linear ramp, or gamma 1.0, will produce the default (usually sRGB-like) behavior. diff --git a/docs/moving.dox b/docs/moving.dox index b80d84a2..705b4fa8 100644 --- a/docs/moving.dox +++ b/docs/moving.dox @@ -243,7 +243,7 @@ while (!glfwWindowShouldClose(window)) @endcode The close callback no longer returns a value. Instead, it is called after the -close flag has been set so it can override its value, if it chooses to, before +close flag has been set, so it can optionally override its value, before event processing completes. You may however not call @ref glfwDestroyWindow from the close callback (or any other window related callback). @@ -350,11 +350,11 @@ from a repeat. Note that @ref glfwGetKey still returns only `GLFW_PRESS` or GLFW 3 key tokens map to physical keys, unlike in GLFW 2 where they mapped to the values generated by the current keyboard layout. The tokens are named -according to the values they would have using the standard US layout, but this +according to the values they would have in the standard US layout, but this is only a convenience, as most programmers are assumed to know that layout. This means that (for example) `GLFW_KEY_LEFT_BRACKET` is always a single key and is the same key in the same place regardless of what keyboard layouts the users -of your program has. +of your program have. The key input facility was never meant for text input, although using it that way worked slightly better in GLFW 2. If you were using it to input text, you diff --git a/docs/news.dox b/docs/news.dox index 6b1367d5..b8854a0a 100644 --- a/docs/news.dox +++ b/docs/news.dox @@ -9,11 +9,19 @@ @subsection features_34 New features in version 3.4 +@subsubsection runtime_platform_34 Runtime platform selection + +GLFW now supports being compiled for multiple backends and selecting between +them at runtime with the @ref GLFW_PLATFORM init hint. After initialization the +selected platform can be queried with @ref glfwGetPlatform. You can check if +support for a given platform is compiled in with @ref glfwPlatformSupported. + + @subsubsection standard_cursors_34 More standard cursors GLFW now provides the standard cursor shapes @ref GLFW_RESIZE_NWSE_CURSOR and @ref GLFW_RESIZE_NESW_CURSOR for diagonal resizing, @ref GLFW_RESIZE_ALL_CURSOR -for omni-directional resizing and @ref GLFW_NOT_ALLOWED_CURSOR for showing an +for omnidirectional resizing and @ref GLFW_NOT_ALLOWED_CURSOR for showing an action is not allowed. Unlike the original set, these shapes may not be available everywhere and @@ -35,6 +43,12 @@ to whatever window is behind it. This can also be changed after window creation with the matching [window attribute](@ref GLFW_MOUSE_PASSTHROUGH_attrib). +@subsubsection wayland_app_id_34 Wayland app_id specification + +GLFW now supports specifying the app_id for a Wayland window using the +[GLFW_WAYLAND_APP_ID](@ref GLFW_WAYLAND_APP_ID_hint) window hint string. + + @subsubsection features_34_angle_backend Support for ANGLE rendering backend selection GLFW now provides the @@ -44,6 +58,14 @@ requesting a specific rendering backend when using contexts. +@subsubsection captured_cursor_34 Captured cursor mode + +GLFW now supports confining the cursor to the window content area with the @ref +GLFW_CURSOR_CAPTURED cursor mode. + +For more information see @ref cursor_mode. + + @subsubsection features_34_init_allocator Support for custom memory allocator GLFW now supports plugging a custom memory allocator at initialization with @ref @@ -54,6 +76,14 @@ function pointers corresponding to the standard library functions `malloc`, For more information see @ref init_allocator. +@subsubsection features_34_position_hint Window hints for initial position + +GLFW now provides the @ref GLFW_POSITION_X and @ref GLFW_POSITION_Y window hints for +specifying the initial position of the window. This removes the need to create a hidden +window, move it and then show it. The default value of these hints is +`GLFW_ANY_POSITION`, which selects the previous behavior. + + @subsubsection features_34_win32_keymenu Support for keyboard access to Windows window menu GLFW now provides the @@ -63,7 +93,23 @@ Alt-and-then-Space shortcuts. This may be useful for more GUI-oriented applications. -@subsection caveats_34 Caveats for version 3.4 +@subsection caveats Caveats for version 3.4 + +@subsubsection native_34 Multiple sets of native access functions + +Because GLFW now supports runtime selection of platform (window system), a library binary +may export native access functions for multiple platforms. Starting with version 3.4 you +must not assume that GLFW is running on a platform just because it exports native access +functions for it. After initialization, you can query the selected platform with @ref +glfwGetPlatform. + + +@subsubsection version_string_34 Version string format has been changed + +Because GLFW now supports runtime selection of platform (window system), the version +string returned by @ref glfwGetVersionString has been expanded. It now contains the names +of all APIs for all the platforms that the library binary supports. + @subsubsection joysticks_34 Joystick support is initialized on demand @@ -80,7 +126,20 @@ To work around this, call any joystick function before waiting for events, for example by setting a [joystick callback](@ref joystick_event). -@subsubsection standalone_34 Tests and examples are disabled when built as a sub-project +@subsubsection wayland_alpha_34 Frambuffer may lack alpha channel on older Wayland systems + +On Wayland, when creating an EGL context on a machine lacking the new +`EGL_EXT_present_opaque` extension, the @ref GLFW_ALPHA_BITS window hint will be +ignored and the framebuffer will have no alpha channel. This is because some +Wayland compositors treat any buffer with an alpha channel as per-pixel +transparent. + +If you want a per-pixel transparent window, see the +[GLFW_TRANSPARENT_FRAMEBUFFER](@ref GLFW_TRANSPARENT_FRAMEBUFFER_hint) window +hint. + + +@subsubsection standalone_34 Tests and examples are disabled when built as a subproject GLFW now does not build the tests and examples when it is added as a subdirectory of another CMake project. To enable these, set the @ref @@ -114,10 +173,39 @@ GLFW_TRANSPARENT_FRAMEBUFFER on Windows 7 if DWM transparency is off (the Transparency setting under Personalization > Window Color). +@subsubsection emptyevents_34 Empty events on X11 no longer round-trip to server + +Events posted with @ref glfwPostEmptyEvent now use a separate unnamed pipe +instead of sending an X11 client event to the helper window. + + @subsection deprecations_34 Deprecations in version 3.4 @subsection removals_34 Removals in 3.4 +@subsubsection vulkan_static_34 GLFW_VULKAN_STATIC CMake option has been removed + +This option was used to compile GLFW directly linked with the Vulkan loader, instead of +using dynamic loading to get hold of `vkGetInstanceProcAddr` at initialization. This is +now done by calling the @ref glfwInitVulkanLoader function before initialization. + +If you need backward compatibility, this macro can still be defined for GLFW 3.4 and will +have no effect. The call to @ref glfwInitVulkanLoader can be conditionally enabled in +your code by checking the @ref GLFW_VERSION_MAJOR and @ref GLFW_VERSION_MINOR macros. + + +@subsubsection osmesa_option_34 GLFW_USE_OSMESA CMake option has been removed + +This option was used to compile GLFW for the Null platform. The Null platform is now +always supported. To produce a library binary that only supports this platform, the way +this CMake option used to do, you will instead need to disable the default platform for +the target OS. This means setting the @ref GLFW_BUILD_WIN32, @ref GLFW_BUILD_COCOA or +@ref GLFW_BUILD_X11 CMake option to false. + +You can set all of them to false and the ones that don't apply for the target OS will be +ignored. + + @subsubsection wl_shell_34 Support for the wl_shell protocol has been removed Support for the wl_shell protocol has been removed and GLFW now only supports @@ -130,6 +218,9 @@ then GLFW will fail to initialize. @subsubsection functions_34 New functions in version 3.4 - @ref glfwInitAllocator + - @ref glfwGetPlatform + - @ref glfwPlatformSupported + - @ref glfwInitVulkanLoader @subsubsection types_34 New types in version 3.4 @@ -142,6 +233,14 @@ then GLFW will fail to initialize. @subsubsection constants_34 New constants in version 3.4 + - @ref GLFW_PLATFORM + - @ref GLFW_ANY_PLATFORM + - @ref GLFW_PLATFORM_WIN32 + - @ref GLFW_PLATFORM_COCOA + - @ref GLFW_PLATFORM_WAYLAND + - @ref GLFW_PLATFORM_X11 + - @ref GLFW_PLATFORM_NULL + - @ref GLFW_PLATFORM_UNAVAILABLE - @ref GLFW_POINTING_HAND_CURSOR - @ref GLFW_RESIZE_EW_CURSOR - @ref GLFW_RESIZE_NS_CURSOR @@ -164,6 +263,10 @@ then GLFW will fail to initialize. - @ref GLFW_ANGLE_PLATFORM_TYPE_VULKAN - @ref GLFW_ANGLE_PLATFORM_TYPE_METAL - @ref GLFW_X11_XCB_VULKAN_SURFACE + - @ref GLFW_CURSOR_CAPTURED + - @ref GLFW_POSITION_X + - @ref GLFW_POSITION_Y + - @ref GLFW_ANY_POSITION @section news_archive Release notes for earlier versions diff --git a/docs/quick.dox b/docs/quick.dox index c3f47aa1..8824ff5b 100644 --- a/docs/quick.dox +++ b/docs/quick.dox @@ -149,10 +149,6 @@ if (!window) } @endcode -The window handle is passed to all window related functions and is provided to -along to all window related callbacks, so they can tell which window received -the event. - When a window and context is no longer needed, destroy it. @code @@ -238,7 +234,7 @@ events as described below. @subsection quick_render Rendering with OpenGL Once you have a current OpenGL context, you can use OpenGL normally. In this -tutorial, a multi-colored rotating triangle will be rendered. The framebuffer +tutorial, a multicolored rotating triangle will be rendered. The framebuffer size needs to be retrieved for `glViewport`. @code diff --git a/docs/vulkan.dox b/docs/vulkan.dox index 68e3d5fe..5e38c014 100644 --- a/docs/vulkan.dox +++ b/docs/vulkan.dox @@ -29,28 +29,34 @@ are also guides for the other areas of the GLFW API. - @ref input_guide -@section vulkan_loader Linking against the Vulkan loader +@section vulkan_loader Finding the Vulkan loader -By default, GLFW will look for the Vulkan loader on demand at runtime via its -standard name (`vulkan-1.dll` on Windows, `libvulkan.so.1` on Linux and other -Unix-like systems and `libvulkan.1.dylib` on macOS). This means that GLFW does -not need to be linked against the loader. However, it also means that if you -are using the static library form of the Vulkan loader GLFW will either fail to -find it or (worse) use the wrong one. +GLFW itself does not ever need to be linked against the Vulkan loader. -The @ref GLFW_VULKAN_STATIC CMake option makes GLFW call the Vulkan loader -directly instead of dynamically loading it at runtime. Not linking against the -Vulkan loader will then be a compile-time error. +By default, GLFW will load the Vulkan loader dynamically at runtime via its standard name: +`vulkan-1.dll` on Windows, `libvulkan.so.1` on Linux and other Unix-like systems and +`libvulkan.1.dylib` on macOS. -@macos Because the Vulkan loader and ICD are not installed globally on macOS, -you need to set up the application bundle according to the LunarG SDK -documentation. This is explained in more detail in the +@macos GLFW will also look up and search the `Frameworks` subdirectory of your +application bundle. + +If your code is using a Vulkan loader with a different name or in a non-standard location +you will need to direct GLFW to it. Pass your version of `vkGetInstanceProcAddr` to @ref +glfwInitVulkanLoader before initializing GLFW and it will use that function for all Vulkan +entry point retrieval. This prevents GLFW from dynamically loading the Vulkan loader. + +@code +glfwInitVulkanLoader(vkGetInstanceProcAddr); +@endcode + +@macos To make your application be redistributable you will need to set up the application +bundle according to the LunarG SDK documentation. This is explained in more detail in the [SDK documentation for macOS](https://vulkan.lunarg.com/doc/sdk/latest/mac/getting_started.html). -@section vulkan_include Including the Vulkan and GLFW header files +@section vulkan_include Including the Vulkan header file -To include the Vulkan header, define @ref GLFW_INCLUDE_VULKAN before including +To have GLFW include the Vulkan header, define @ref GLFW_INCLUDE_VULKAN before including the GLFW header. @code @@ -66,8 +72,13 @@ your own custom Vulkan header then do this before the GLFW header. #include @endcode -Unless a Vulkan header is included, either by the GLFW header or above it, any -GLFW functions that take or return Vulkan types will not be declared. +Unless a Vulkan header is included, either by the GLFW header or above it, the following +GLFW functions will not be declared, as depend on Vulkan types. + + - @ref glfwInitVulkanLoader + - @ref glfwGetInstanceProcAddress + - @ref glfwGetPhysicalDevicePresentationSupport + - @ref glfwCreateWindowSurface The `VK_USE_PLATFORM_*_KHR` macros do not need to be defined for the Vulkan part of GLFW to work. Define them only if you are using these extensions directly. @@ -131,7 +142,7 @@ PFN_vkGetDeviceProcAddr pfnGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr) glfwGetInstanceProcAddress(instance, "vkGetDeviceProcAddr"); @endcode -Device-specific functions may execute a little bit faster, due to not having to +Device-specific functions may execute a little faster, due to not having to dispatch internally based on the device passed to them. For more information about `vkGetDeviceProcAddr`, see the Vulkan documentation. @@ -177,6 +188,13 @@ check whether any extensions you wish to enable are already in the returned array, as it is an error to specify an extension more than once in the `VkInstanceCreateInfo` struct. +@macos MoltenVK is (as of July 2022) not yet a fully conformant implementation +of Vulkan. As of Vulkan SDK 1.3.216.0, this means you must also enable the +`VK_KHR_portability_enumeration` instance extension and set the +`VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR` bit in the instance creation +info flags for MoltenVK to show up in the list of physical devices. For more +information, see the Vulkan and MoltenVK documentation. + @section vulkan_present Querying for Vulkan presentation support diff --git a/docs/window.dox b/docs/window.dox index 5e482431..3cec6358 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -256,6 +256,14 @@ This is only supported for undecorated windows. Decorated windows with this enabled will behave differently between platforms. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. +@anchor GLFW_POSITION_X +@anchor GLFW_POSITION_Y +__GLFW_POSITION_X__ and __GLFW_POSITION_Y__ specify the desired initial position +of the window. The window manager may modify or ignore these coordinates. If +either or both of these hints are set to `GLFW_ANY_POSITION` then the window +manager will position the window where it thinks the user will prefer it. +Possible values are any valid screen coordinates and `GLFW_ANY_POSITION`. + @subsubsection window_hints_fb Framebuffer related hints @@ -447,7 +455,7 @@ The no error mode for OpenGL and OpenGL ES is described in detail by the extension. -@subsubsection window_hints_win32 Windows specific window hints +@subsubsection window_hints_win32 Win32 specific hints @anchor GLFW_WIN32_KEYBOARD_MENU_hint __GLFW_WIN32_KEYBOARD_MENU__ specifies whether to allow access to the window @@ -455,7 +463,7 @@ menu via the Alt+Space and Alt-and-then-Space keyboard shortcuts. This is ignored on other platforms. -@subsubsection window_hints_osx macOS specific window hints +@subsubsection window_hints_osx macOS specific hints @anchor GLFW_COCOA_RETINA_FRAMEBUFFER_hint __GLFW_COCOA_RETINA_FRAMEBUFFER__ specifies whether to use full resolution @@ -489,9 +497,17 @@ should also declare this in its `Info.plist` by setting the @anchor GLFW_X11_CLASS_NAME_hint @anchor GLFW_X11_INSTANCE_NAME_hint __GLFW_X11_CLASS_NAME__ and __GLFW_X11_INSTANCE_NAME__ specifies the desired -ASCII encoded class and instance parts of the ICCCM `WM_CLASS` window property. +ASCII encoded class and instance parts of the ICCCM `WM_CLASS` window property. Both +hints need to be set to something other than an empty string for them to take effect. These are set with @ref glfwWindowHintString. +@subsubsection window_hints_wayland Wayland specific window hints + +@anchor GLFW_WAYLAND_APP_ID_hint +__GLFW_WAYLAND_APP_ID__ specifies the Wayland app_id for a window, used +by window managers to identify types of windows. This is set with +@ref glfwWindowHintString. + @subsubsection window_hints_values Supported and default values @@ -509,6 +525,8 @@ GLFW_TRANSPARENT_FRAMEBUFFER | `GLFW_FALSE` | `GLFW_TRUE` or `GL GLFW_FOCUS_ON_SHOW | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_SCALE_TO_MONITOR | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_MOUSE_PASSTHROUGH | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` +GLFW_POSITION_X | `GLFW_ANY_POSITION` | Any valid screen x-coordinate or `GLFW_ANY_POSITION` +GLFW_POSITION_Y | `GLFW_ANY_POSITION` | Any valid screen y-coordinate or `GLFW_ANY_POSITION` GLFW_RED_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` GLFW_GREEN_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` GLFW_BLUE_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` @@ -540,6 +558,7 @@ GLFW_COCOA_FRAME_NAME | `""` | A UTF-8 encoded fr GLFW_COCOA_GRAPHICS_SWITCHING | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_X11_CLASS_NAME | `""` | An ASCII encoded `WM_CLASS` class name GLFW_X11_INSTANCE_NAME | `""` | An ASCII encoded `WM_CLASS` instance name +GLFW_WAYLAND_APP_ID | `""` | An ASCII encoded Wayland `app_id` name @section window_events Window event processing @@ -790,7 +809,20 @@ are undefined if they conflict. @subsection window_pos Window position -The position of a windowed-mode window can be changed with @ref +By default, the window manager chooses the position of new windowed mode +windows, based on its size and which monitor the user appears to be working on. +This is most often the right choice. If you need to create a window at +a specific position, you can set the desired position with the @ref +GLFW_POSITION_X and @ref GLFW_POSITION_Y window hints. + +@code +glfwWindowHint(GLFW_POSITION_X, 70); +glfwWindowHint(GLFW_POSITION_Y, 83); +@endcode + +To restore the previous behavior, set these hints to `GLFW_ANY_POSITION`. + +The position of a windowed mode window can be changed with @ref glfwSetWindowPos. This moves the window so that the upper-left corner of its content area has the specified [screen coordinates](@ref coordinate_systems). The window system may put limitations on window placement. diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index be8927db..e7a03797 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -50,11 +50,6 @@ set_target_properties(${GUI_ONLY_BINARIES} ${CONSOLE_BINARIES} PROPERTIES C_STANDARD 99 FOLDER "GLFW3/Examples") -if (GLFW_USE_OSMESA) - find_package(OSMesa REQUIRED) - target_compile_definitions(offscreen PRIVATE USE_NATIVE_OSMESA) -endif() - if (MSVC) # Tell MSVC to use main instead of WinMain set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES diff --git a/examples/offscreen.c b/examples/offscreen.c index b7cd2fd7..e2852860 100644 --- a/examples/offscreen.c +++ b/examples/offscreen.c @@ -28,11 +28,6 @@ #define GLFW_INCLUDE_NONE #include -#if USE_NATIVE_OSMESA - #define GLFW_EXPOSE_NATIVE_OSMESA - #include -#endif - #include "linmath.h" #include @@ -151,12 +146,8 @@ int main(void) glDrawArrays(GL_TRIANGLES, 0, 3); glFinish(); -#if USE_NATIVE_OSMESA - glfwGetOSMesaColorBuffer(window, &width, &height, NULL, (void**) &buffer); -#else buffer = calloc(4, width * height); glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); -#endif // Write image Y-flipped because OpenGL stbi_write_png("offscreen.png", @@ -164,11 +155,7 @@ int main(void) buffer + (width * 4 * (height - 1)), -width * 4); -#if USE_NATIVE_OSMESA - // Here is where there's nothing -#else free(buffer); -#endif glfwDestroyWindow(window); diff --git a/examples/splitview.c b/examples/splitview.c index 4f0a8a98..990df12c 100644 --- a/examples/splitview.c +++ b/examples/splitview.c @@ -2,7 +2,7 @@ // This is an example program for the GLFW library // // The program uses a "split window" view, rendering four views of the -// same scene in one window (e.g. uesful for 3D modelling software). This +// same scene in one window (e.g. useful for 3D modelling software). This // demo uses scissors to separate the four different rendering areas from // each other. // diff --git a/examples/windows.c b/examples/windows.c index 598e5218..1589ffbf 100644 --- a/examples/windows.c +++ b/examples/windows.c @@ -44,7 +44,6 @@ int main(int argc, char** argv) exit(EXIT_FAILURE); } - glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); glfwGetMonitorWorkarea(glfwGetPrimaryMonitor(), &xpos, &ypos, NULL, &height); @@ -66,6 +65,9 @@ int main(int argc, char** argv) if (i > 0) glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_FALSE); + glfwWindowHint(GLFW_POSITION_X, xpos + size * (1 + (i & 1))); + glfwWindowHint(GLFW_POSITION_Y, ypos + size * (1 + (i >> 1))); + windows[i] = glfwCreateWindow(size, size, "Multi-Window Example", NULL, NULL); if (!windows[i]) { @@ -75,9 +77,6 @@ int main(int argc, char** argv) exit(EXIT_FAILURE); } - glfwSetWindowPos(windows[i], - xpos + size * (1 + (i & 1)), - ypos + size * (1 + (i >> 1))); glfwSetInputMode(windows[i], GLFW_STICKY_KEYS, GLFW_TRUE); glfwMakeContextCurrent(windows[i]); @@ -85,9 +84,6 @@ int main(int argc, char** argv) glClearColor(colors[i].r, colors[i].g, colors[i].b, 1.f); } - for (int i = 0; i < 4; i++) - glfwShowWindow(windows[i]); - for (;;) { for (int i = 0; i < 4; i++) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 94ae786c..8e30fd2f 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -190,6 +190,9 @@ extern "C" { #else /*__APPLE__*/ #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif #endif /*__APPLE__*/ @@ -259,13 +262,12 @@ extern "C" { /* We are building GLFW as a Win32 DLL */ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) - /* We are calling GLFW as a Win32 DLL */ + /* We are calling a GLFW Win32 DLL */ #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) - /* We are building GLFW as a shared / dynamic library */ + /* We are building GLFW as a Unix shared library */ #define GLFWAPI __attribute__((visibility("default"))) #else - /* We are building or calling GLFW as a static library */ #define GLFWAPI #endif @@ -372,7 +374,7 @@ extern "C" { * * The naming of the key codes follow these rules: * - The US keyboard layout is used - * - Names of printable alpha-numeric characters are used (e.g. "A", "R", + * - Names of printable alphanumeric characters are used (e.g. "A", "R", * "3", etc.) * - For non-alphanumeric characters, Unicode:ish names are used (e.g. * "COMMA", "LEFT_SQUARE_BRACKET", etc.). Note that some names do not @@ -717,7 +719,7 @@ extern "C" { * GLFW could not find support for the requested API on the system. * * @analysis The installed graphics driver does not support the requested - * API, or does not support it via the chosen context creation backend. + * API, or does not support it via the chosen context creation API. * Below are a few examples. * * @par @@ -786,7 +788,7 @@ extern "C" { /*! @brief The specified cursor shape is not available. * * The specified standard cursor shape is not available, either because the - * current system cursor theme does not provide it or because it is not + * current platform cursor theme does not provide it or because it is not * available on the platform. * * @analysis Platform or system settings limitation. Pick another @@ -821,6 +823,28 @@ extern "C" { * updating any existing out parameters. */ #define GLFW_FEATURE_UNIMPLEMENTED 0x0001000D +/*! @brief Platform unavailable or no matching platform was found. + * + * If emitted during initialization, no matching platform was found. If @ref + * GLFW_PLATFORM is set to `GLFW_ANY_PLATFORM`, GLFW could not detect any of the + * platforms supported by this library binary, except for the Null platform. If set to + * a specific platform, it is either not supported by this library binary or GLFW was not + * able to detect it. + * + * If emitted by a native access function, GLFW was initialized for a different platform + * than the function is for. + * + * @analysis Failure to detect any platform usually only happens on non-macOS Unix + * systems, either when no window system is running or the program was run from + * a terminal that does not have the necessary environment variables. Fall back to + * a different platform if possible or notify the user that no usable platform was + * detected. + * + * Failure to detect a specific platform may have the same cause as above or be because + * support for that platform was not compiled in. Call @ref glfwPlatformSupported to + * check whether a specific platform is supported by a library binary. + */ +#define GLFW_PLATFORM_UNAVAILABLE 0x0001000E /*! @} */ /*! @addtogroup window @@ -903,6 +927,18 @@ extern "C" { */ #define GLFW_MOUSE_PASSTHROUGH 0x0002000D +/*! @brief Initial position x-coordinate window hint. + * + * Initial position x-coordinate [window hint](@ref GLFW_POSITION_X). + */ +#define GLFW_POSITION_X 0x0002000E + +/*! @brief Initial position y-coordinate window hint. + * + * Initial position y-coordinate [window hint](@ref GLFW_POSITION_Y). + */ +#define GLFW_POSITION_Y 0x0002000F + /*! @brief Framebuffer bit depth hint. * * Framebuffer bit depth [hint](@ref GLFW_RED_BITS). @@ -1003,7 +1039,7 @@ extern "C" { * and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib). */ #define GLFW_CONTEXT_VERSION_MINOR 0x00022003 -/*! @brief Context client API revision number hint and attribute. +/*! @brief Context client API revision number attribute. * * Context client API revision number * [attribute](@ref GLFW_CONTEXT_REVISION_attrib). @@ -1081,6 +1117,12 @@ extern "C" { */ #define GLFW_X11_INSTANCE_NAME 0x00024002 #define GLFW_WIN32_KEYBOARD_MENU 0x00025001 +/*! @brief Wayland specific + * [window hint](@ref GLFW_WAYLAND_APP_ID_hint). + * + * Allows specification of the Wayland app_id. + */ +#define GLFW_WAYLAND_APP_ID 0x00026001 /*! @} */ #define GLFW_NO_API 0 @@ -1104,6 +1146,7 @@ extern "C" { #define GLFW_CURSOR_NORMAL 0x00034001 #define GLFW_CURSOR_HIDDEN 0x00034002 #define GLFW_CURSOR_DISABLED 0x00034003 +#define GLFW_CURSOR_CAPTURED 0x00034004 #define GLFW_ANY_RELEASE_BEHAVIOR 0 #define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001 @@ -1121,11 +1164,13 @@ extern "C" { #define GLFW_ANGLE_PLATFORM_TYPE_VULKAN 0x00037007 #define GLFW_ANGLE_PLATFORM_TYPE_METAL 0x00037008 +#define GLFW_ANY_POSITION 0x80000000 + /*! @defgroup shapes Standard cursor shapes * @brief Standard system cursor shapes. * * These are the [standard cursor shapes](@ref cursor_standard) that can be - * requested from the window system. + * requested from the platform (window system). * * @ingroup input * @{ */ @@ -1242,6 +1287,11 @@ extern "C" { * ANGLE rendering backend [init hint](@ref GLFW_ANGLE_PLATFORM_TYPE_hint). */ #define GLFW_ANGLE_PLATFORM_TYPE 0x00050002 +/*! @brief Platform selection init hint. + * + * Platform selection [init hint](@ref GLFW_PLATFORM). + */ +#define GLFW_PLATFORM 0x00050003 /*! @brief macOS specific init hint. * * macOS specific [init hint](@ref GLFW_COCOA_CHDIR_RESOURCES_hint). @@ -1259,6 +1309,20 @@ extern "C" { #define GLFW_X11_XCB_VULKAN_SURFACE 0x00052001 /*! @} */ +/*! @addtogroup init + * @{ */ +/*! @brief Hint value that enables automatic platform selection. + * + * Hint value for @ref GLFW_PLATFORM that enables automatic platform selection. + */ +#define GLFW_ANY_PLATFORM 0x00060000 +#define GLFW_PLATFORM_WIN32 0x00060001 +#define GLFW_PLATFORM_COCOA 0x00060002 +#define GLFW_PLATFORM_WAYLAND 0x00060003 +#define GLFW_PLATFORM_X11 0x00060004 +#define GLFW_PLATFORM_NULL 0x00060005 +/*! @} */ + #define GLFW_DONT_CARE -1 @@ -1770,7 +1834,7 @@ typedef void (* GLFWscrollfun)(GLFWwindow* window, double xoffset, double yoffse * * @param[in] window The window that received the event. * @param[in] key The [keyboard key](@ref keys) that was pressed or released. - * @param[in] scancode The system-specific scancode of the key. + * @param[in] scancode The platform-specific scancode of the key. * @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`. Future * releases may add more actions. * @param[in] mods Bit field describing which [modifier keys](@ref mods) were @@ -2149,10 +2213,15 @@ typedef struct GLFWallocator * Additional calls to this function after successful initialization but before * termination will return `GLFW_TRUE` immediately. * + * The @ref GLFW_PLATFORM init hint controls which platforms are considered during + * initialization. This also depends on which platforms the library was compiled to + * support. + * * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * @errors Possible errors include @ref GLFW_PLATFORM_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * * @remark @macos This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's @@ -2277,6 +2346,54 @@ GLFWAPI void glfwInitHint(int hint, int value); */ GLFWAPI void glfwInitAllocator(const GLFWallocator* allocator); +#if defined(VK_VERSION_1_0) + +/*! @brief Sets the desired Vulkan `vkGetInstanceProcAddr` function. + * + * This function sets the `vkGetInstanceProcAddr` function that GLFW will use for all + * Vulkan related entry point queries. + * + * This feature is mostly useful on macOS, if your copy of the Vulkan loader is in + * a location where GLFW cannot find it through dynamic loading, or if you are still + * using the static library version of the loader. + * + * If set to `NULL`, GLFW will try to load the Vulkan loader dynamically by its standard + * name and get this function from there. This is the default behavior. + * + * The standard name of the loader is `vulkan-1.dll` on Windows, `libvulkan.so.1` on + * Linux and other Unix-like systems and `libvulkan.1.dylib` on macOS. If your code is + * also loading it via these names then you probably don't need to use this function. + * + * The function address you set is never reset by GLFW, but it only takes effect during + * initialization. Once GLFW has been initialized, any updates will be ignored until the + * library is terminated and initialized again. + * + * @param[in] loader The address of the function to use, or `NULL`. + * + * @par Loader function signature + * @code + * PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance instance, const char* name) + * @endcode + * For more information about this function, see the + * [Vulkan Registry](https://www.khronos.org/registry/vulkan/). + * + * @errors None. + * + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref vulkan_loader + * @sa @ref glfwInit + * + * @since Added in version 3.4. + * + * @ingroup init + */ +GLFWAPI void glfwInitVulkanLoader(PFN_vkGetInstanceProcAddr loader); + +#endif /*VK_VERSION_1_0*/ + /*! @brief Retrieves the version of the GLFW library. * * This function retrieves the major, minor and revision numbers of the GLFW @@ -2307,15 +2424,18 @@ GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev); /*! @brief Returns a string describing the compile-time configuration. * * This function returns the compile-time generated - * [version string](@ref intro_version_string) of the GLFW library binary. It - * describes the version, platform, compiler and any platform-specific - * compile-time options. It should not be confused with the OpenGL or OpenGL - * ES version string, queried with `glGetString`. + * [version string](@ref intro_version_string) of the GLFW library binary. It describes + * the version, platforms, compiler and any platform or operating system specific + * compile-time options. It should not be confused with the OpenGL or OpenGL ES version + * string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The * @ref glfwGetVersion function provides the version of the running library * binary in numerical format. * + * __Do not use the version string__ to parse what platforms are supported. The @ref + * glfwPlatformSupported function lets you query platform support. + * * @return The ASCII encoded GLFW version string. * * @errors None. @@ -2412,6 +2532,51 @@ GLFWAPI int glfwGetError(const char** description); */ GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun callback); +/*! @brief Returns the currently selected platform. + * + * This function returns the platform that was selected during initialization. The + * returned value will be one of `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, + * `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` or `GLFW_PLATFORM_NULL`. + * + * @return The currently selected platform, or zero if an error occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref platform + * @sa @ref glfwPlatformSupported + * + * @since Added in version 3.4. + * + * @ingroup init + */ +GLFWAPI int glfwGetPlatform(void); + +/*! @brief Returns whether the library includes support for the specified platform. + * + * This function returns whether the library was compiled with support for the specified + * platform. The platform must be one of `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, + * `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` or `GLFW_PLATFORM_NULL`. + * + * @param[in] platform The platform to query. + * @return `GLFW_TRUE` if the platform is supported, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_INVALID_ENUM. + * + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref platform + * @sa @ref glfwGetPlatform + * + * @since Added in version 3.4. + * + * @ingroup init + */ +GLFWAPI int glfwPlatformSupported(int platform); + /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected @@ -2495,7 +2660,7 @@ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos); * This function returns the position, in screen coordinates, of the upper-left * corner of the work area of the specified monitor along with the work area * size in screen coordinates. The work area is defined as the area of the - * monitor not occluded by the operating system task bar where present. If no + * monitor not occluded by the window system task bar where present. If no * task bar exists then the work area is the monitor resolution in screen * coordinates. * @@ -2526,7 +2691,7 @@ GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* monitor, int* xpos, int* ypos, * This function returns the size, in millimetres, of the display area of the * specified monitor. * - * Some systems do not provide accurate monitor size information, either + * Some platforms do not provide accurate monitor size information, either * because the monitor * [EDID](https://en.wikipedia.org/wiki/Extended_display_identification_data) * data is incorrect or because the driver does not report it accurately. @@ -2542,8 +2707,8 @@ GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* monitor, int* xpos, int* ypos, * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @remark @win32 calculates the returned physical size from the - * current resolution and system DPI instead of querying the monitor EDID data. + * @remark @win32 On Windows 8 and earlier the physical size is calculated from + * the current resolution and system DPI instead of querying the monitor EDID data. * * @thread_safety This function must only be called from the main thread. * @@ -2772,11 +2937,11 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor); * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_INVALID_VALUE, + * @ref GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * * @remark @wayland Gamma handling is a privileged protocol, this function - * will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR. + * will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE. * * @thread_safety This function must only be called from the main thread. * @@ -2796,11 +2961,11 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma); * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR + * and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * * @remark @wayland Gamma handling is a privileged protocol, this function - * will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR while + * will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE while * returning `NULL`. * * @pointer_lifetime The returned structure and its arrays are allocated and @@ -2835,8 +3000,8 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor); * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR + * and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * * @remark The size of the specified gamma ramp should match the size of the * current ramp for that monitor. @@ -2844,7 +3009,7 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor); * @remark @win32 The gamma ramp size must be 256. * * @remark @wayland Gamma handling is a privileged protocol, this function - * will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR. + * will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE. * * @pointer_lifetime The specified gamma ramp is copied before this function * returns. @@ -2987,10 +3152,10 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value); * OpenGL or OpenGL ES context. * * By default, newly created windows use the placement recommended by the - * window system. To create the window at a specific position, make it - * initially invisible using the [GLFW_VISIBLE](@ref GLFW_VISIBLE_hint) window - * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) - * it. + * window system. To create the window at a specific position, set the @ref + * GLFW_POSITION_X and @ref GLFW_POSITION_Y window hints before creation. To + * restore the default behavior, set either or both hints back to + * `GLFW_ANY_POSITION`. * * As long as at least one full screen window is not iconified, the screensaver * is prohibited from starting. @@ -3215,7 +3380,8 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); * count is zero. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). + * GLFW_INVALID_VALUE, @ref GLFW_PLATFORM_ERROR and @ref + * GLFW_FEATURE_UNAVAILABLE (see remarks). * * @pointer_lifetime The specified image data is copied before this function * returns. @@ -3540,7 +3706,7 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int * regardless of their DPI and scaling settings. This relies on the system DPI * and scaling settings being somewhat correct. * - * On systems where each monitors can have its own content scale, the window + * On platforms where each monitors can have its own content scale, the window * content scale will depend on which monitor the system considers the window * to be on. * @@ -3628,8 +3794,9 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity); * previously restored. If the window is already iconified, this function does * nothing. * - * If the specified window is a full screen window, the original monitor - * resolution is restored until the window is restored. + * If the specified window is a full screen window, GLFW restores the original + * video mode of the monitor. The window's desired video mode is set again + * when the window is restored. * * @param[in] window The window to iconify. * @@ -3659,8 +3826,8 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow* window); * (minimized) or maximized. If the window is already restored, this function * does nothing. * - * If the specified window is a full screen window, the resolution chosen for - * the window is restored on the selected monitor. + * If the specified window is an iconified full screen window, its desired + * video mode is set again for its monitor when the window is restored. * * @param[in] window The window to restore. * @@ -3721,6 +3888,11 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * GLFW_PLATFORM_ERROR. * + * @remark @wayland Because Wayland wants every frame of the desktop to be + * complete, this function does not immediately make the window visible. + * Instead it will become visible the next time the window framebuffer is + * updated after this call. + * * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide @@ -3923,6 +4095,9 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int * errors. However, this function should not fail as long as it is passed * valid arguments and the library has been [initialized](@ref intro_init). * + * @remark @wayland The Wayland protocol provides no way to check whether a + * window is iconfied, so @ref GLFW_ICONIFIED always returns `GLFW_FALSE`. + * * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs @@ -3957,7 +4132,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib); * @param[in] value `GLFW_TRUE` or `GLFW_FALSE`. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_PLATFORM_ERROR and @ref + * GLFW_FEATURE_UNAVAILABLE. * * @remark Calling @ref glfwGetWindowAttrib will always return the latest * value, even if that value is ignored by the current mode of the window. @@ -4508,6 +4684,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode); * - `GLFW_CURSOR_DISABLED` hides and grabs the cursor, providing virtual * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. + * - `GLFW_CURSOR_CAPTURED` makes the cursor visible and confines it to the + * content area of the window. * * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are @@ -4682,8 +4860,7 @@ GLFWAPI int glfwGetKeyScancode(int key); * * This function returns the last state reported for the specified key to the * specified window. The returned state is one of `GLFW_PRESS` or - * `GLFW_RELEASE`. The higher-level action `GLFW_REPEAT` is only reported to - * the key callback. + * `GLFW_RELEASE`. The action `GLFW_REPEAT` is only reported to the key callback. * * If the @ref GLFW_STICKY_KEYS input mode is enabled, this function returns * `GLFW_PRESS` the first time you call it for a key that was pressed, even if @@ -4807,11 +4984,11 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos); * @param[in] ypos The desired y-coordinate, relative to the top edge of the * content area. * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * * @remark @wayland This function will only work when the cursor mode is - * `GLFW_CURSOR_DISABLED`, otherwise it will do nothing. + * `GLFW_CURSOR_DISABLED`, otherwise it will emit @ref GLFW_FEATURE_UNAVAILABLE. * * @thread_safety This function must only be called from the main thread. * @@ -4844,8 +5021,8 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos); * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. * * @pointer_lifetime The specified image data is copied before this function * returns. @@ -5794,6 +5971,8 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string); * joystick is not present, does not have a mapping or an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref GLFW_INVALID_ENUM. + * * @pointer_lifetime The returned string is allocated and freed by GLFW. You * should not free it yourself. It is valid until the specified joystick is * disconnected, the gamepad mappings are updated or the library is terminated. @@ -5883,8 +6062,8 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string); * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. * * @pointer_lifetime The returned string is allocated and freed by GLFW. You * should not free it yourself. It is valid until the next call to @ref @@ -5913,7 +6092,7 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window); * * The resolution of the timer is system dependent, but is usually on the order * of a few micro- or nanoseconds. It uses the highest-resolution monotonic - * time source on each supported platform. + * time source on each operating system. * * @return The current time, in seconds, or zero if an * [error](@ref error_handling) occurred. @@ -6124,7 +6303,7 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* window); * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. * * @remark This function is not called during context creation, leaving the - * swap interval set to whatever is the default on that platform. This is done + * swap interval set to whatever is the default for that API. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * @@ -6228,13 +6407,11 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); * This function returns whether the Vulkan loader and any minimally functional * ICD have been found. * - * The availability of a Vulkan loader and even an ICD does not by itself - * guarantee that surface creation or even instance creation is possible. - * For example, on Fermi systems Nvidia will install an ICD that provides no - * actual Vulkan support. Call @ref glfwGetRequiredInstanceExtensions to check - * whether the extensions necessary for Vulkan surface creation are available - * and @ref glfwGetPhysicalDevicePresentationSupport to check whether a queue - * family of a physical device supports image presentation. + * The availability of a Vulkan loader and even an ICD does not by itself guarantee that + * surface creation or even instance creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary for Vulkan + * surface creation are available and @ref glfwGetPhysicalDevicePresentationSupport to + * check whether a queue family of a physical device supports image presentation. * * @return `GLFW_TRUE` if Vulkan is minimally available, or `GLFW_FALSE` * otherwise. @@ -6280,9 +6457,6 @@ GLFWAPI int glfwVulkanSupported(void); * returned array, as it is an error to specify an extension more than once in * the `VkInstanceCreateInfo` struct. * - * @remark @macos GLFW currently supports both the `VK_MVK_macos_surface` and - * the newer `VK_EXT_metal_surface` extensions. - * * @pointer_lifetime The returned array is allocated and freed by GLFW. You * should not free it yourself. It is guaranteed to be valid only until the * library is terminated. @@ -6421,17 +6595,20 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhys * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should * eliminate almost all occurrences of these errors. * - * @remark @macos This function currently only supports the - * `VK_MVK_macos_surface` extension from MoltenVK. + * @remark @macos GLFW prefers the `VK_EXT_metal_surface` extension, with the + * `VK_MVK_macos_surface` extension as a fallback. The name of the selected + * extension, if any, is included in the array returned by @ref + * glfwGetRequiredInstanceExtensions. * * @remark @macos This function creates and sets a `CAMetalLayer` instance for * the window content view, which is required for MoltenVK to function. * - * @remark @x11 GLFW by default attempts to use the `VK_KHR_xcb_surface` - * extension, if available. You can make it prefer the `VK_KHR_xlib_surface` - * extension by setting the + * @remark @x11 By default GLFW prefers the `VK_KHR_xcb_surface` extension, + * with the `VK_KHR_xlib_surface` extension as a fallback. You can make + * `VK_KHR_xlib_surface` the preferred extension by setting the * [GLFW_X11_XCB_VULKAN_SURFACE](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint) init - * hint. + * hint. The name of the selected extension, if any, is included in the array + * returned by @ref glfwGetRequiredInstanceExtensions. * * @thread_safety This function may be called from any thread. For * synchronization details of Vulkan objects, see the Vulkan specification. @@ -6469,6 +6646,7 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window */ #ifndef GLAPIENTRY #define GLAPIENTRY APIENTRY + #define GLFW_GLAPIENTRY_DEFINED #endif /* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ diff --git a/include/GLFW/glfw3native.h b/include/GLFW/glfw3native.h index 06021ef9..171abe36 100644 --- a/include/GLFW/glfw3native.h +++ b/include/GLFW/glfw3native.h @@ -74,6 +74,16 @@ extern "C" { * and which platform-specific headers to include. It is then up your (by * definition platform-specific) code to handle which of these should be * defined. + * + * If you do not want the platform-specific headers to be included, define + * `GLFW_NATIVE_INCLUDE_NONE` before including the @ref glfw3native.h header. + * + * @code + * #define GLFW_EXPOSE_NATIVE_WIN32 + * #define GLFW_EXPOSE_NATIVE_WGL + * #define GLFW_NATIVE_INCLUDE_NONE + * #include + * @endcode */ @@ -81,44 +91,71 @@ extern "C" { * System headers and types *************************************************************************/ -#if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL) - // This is a workaround for the fact that glfw3.h needs to export APIENTRY (for - // example to allow applications to correctly declare a GL_KHR_debug callback) - // but windows.h assumes no one will define APIENTRY before it does - #if defined(GLFW_APIENTRY_DEFINED) - #undef APIENTRY - #undef GLFW_APIENTRY_DEFINED - #endif - #include -#elif defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL) - #if defined(__OBJC__) - #import - #else - #include - typedef void* id; - #endif -#elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX) - #include - #include -#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) - #include -#endif +#if !defined(GLFW_NATIVE_INCLUDE_NONE) -#if defined(GLFW_EXPOSE_NATIVE_WGL) - /* WGL is declared by windows.h */ -#endif -#if defined(GLFW_EXPOSE_NATIVE_NSGL) - /* NSGL is declared by Cocoa.h */ -#endif -#if defined(GLFW_EXPOSE_NATIVE_GLX) - #include -#endif -#if defined(GLFW_EXPOSE_NATIVE_EGL) - #include -#endif -#if defined(GLFW_EXPOSE_NATIVE_OSMESA) - #include -#endif + #if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL) + /* This is a workaround for the fact that glfw3.h needs to export APIENTRY (for + * example to allow applications to correctly declare a GL_KHR_debug callback) + * but windows.h assumes no one will define APIENTRY before it does + */ + #if defined(GLFW_APIENTRY_DEFINED) + #undef APIENTRY + #undef GLFW_APIENTRY_DEFINED + #endif + #include + #endif + + #if defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL) + #if defined(__OBJC__) + #import + #else + #include + #include + #endif + #endif + + #if defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX) + #include + #include + #endif + + #if defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include + #endif + + #if defined(GLFW_EXPOSE_NATIVE_WGL) + /* WGL is declared by windows.h */ + #endif + #if defined(GLFW_EXPOSE_NATIVE_NSGL) + /* NSGL is declared by Cocoa.h */ + #endif + #if defined(GLFW_EXPOSE_NATIVE_GLX) + /* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by + * default it also acts as an OpenGL header + * However, glx.h will include gl.h, which will define it unconditionally + */ + #if defined(GLFW_GLAPIENTRY_DEFINED) + #undef GLAPIENTRY + #undef GLFW_GLAPIENTRY_DEFINED + #endif + #include + #endif + #if defined(GLFW_EXPOSE_NATIVE_EGL) + #include + #endif + #if defined(GLFW_EXPOSE_NATIVE_OSMESA) + /* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by + * default it also acts as an OpenGL header + * However, osmesa.h will include gl.h, which will define it unconditionally + */ + #if defined(GLFW_GLAPIENTRY_DEFINED) + #undef GLAPIENTRY + #undef GLFW_GLAPIENTRY_DEFINED + #endif + #include + #endif + +#endif /*GLFW_NATIVE_INCLUDE_NONE*/ /************************************************************************* @@ -132,6 +169,8 @@ extern "C" { * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -147,6 +186,8 @@ GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor); * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -161,6 +202,8 @@ GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor); * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * * @remark The `HDC` associated with the window can be queried with the * [GetDC](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc) * function. @@ -185,6 +228,9 @@ GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window); * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref + * GLFW_NOT_INITIALIZED. + * * @remark The `HDC` associated with the window can be queried with the * [GetDC](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc) * function. @@ -209,6 +255,8 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window); * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -223,6 +271,8 @@ GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor); * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -239,6 +289,9 @@ GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window); * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref + * GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -255,6 +308,8 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* window); * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -269,6 +324,8 @@ GLFWAPI Display* glfwGetX11Display(void); * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -283,6 +340,8 @@ GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor); * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -297,6 +356,8 @@ GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor); * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -363,6 +424,9 @@ GLFWAPI const char* glfwGetX11SelectionString(void); * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref + * GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -377,6 +441,9 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); * @return The `GLXWindow` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref + * GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -393,6 +460,8 @@ GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); * @return The `struct wl_display*` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -407,6 +476,8 @@ GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); * @return The `struct wl_output*` of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -421,6 +492,8 @@ GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); * @return The main `struct wl_surface*` of the specified window, or `NULL` if * an [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -437,6 +510,11 @@ GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark Because EGL is initialized on demand, this function will return + * `EGL_NO_DISPLAY` until the first context has been created via EGL. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -451,6 +529,9 @@ GLFWAPI EGLDisplay glfwGetEGLDisplay(void); * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref + * GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -465,6 +546,9 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window); * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref + * GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -488,6 +572,9 @@ GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window); * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref + * GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -509,6 +596,9 @@ GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width, int* height * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref + * GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * @@ -523,6 +613,9 @@ GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width, int* height * @return The `OSMesaContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref + * GLFW_NOT_INITIALIZED. + * * @thread_safety This function may be called from any thread. Access is not * synchronized. * diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ea16f195..01f191c9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,8 +2,23 @@ add_library(glfw ${GLFW_LIBRARY_TYPE} "${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h" "${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h" - internal.h mappings.h context.c init.c input.c monitor.c - vulkan.c window.c) + internal.h platform.h mappings.h + context.c init.c input.c monitor.c platform.c vulkan.c window.c + egl_context.c osmesa_context.c null_platform.h null_joystick.h + null_init.c null_monitor.c null_window.c null_joystick.c) + +# The time, thread and module code is shared between all backends on a given OS, +# including the null backend, which still needs those bits to be functional +if (APPLE) + target_sources(glfw PRIVATE cocoa_time.h cocoa_time.c posix_thread.h + posix_module.c posix_thread.c) +elseif (WIN32) + target_sources(glfw PRIVATE win32_time.h win32_thread.h win32_module.c + win32_time.c win32_thread.c) +else() + target_sources(glfw PRIVATE posix_time.h posix_thread.h posix_module.c + posix_time.c posix_thread.c) +endif() add_custom_target(update_mappings COMMAND "${CMAKE_COMMAND}" -P "${GLFW_SOURCE_DIR}/CMake/GenerateMappings.cmake" mappings.h.in mappings.h @@ -14,48 +29,51 @@ add_custom_target(update_mappings set_target_properties(update_mappings PROPERTIES FOLDER "GLFW3") -if (_GLFW_COCOA) - target_sources(glfw PRIVATE cocoa_platform.h cocoa_joystick.h posix_thread.h - nsgl_context.h egl_context.h osmesa_context.h - cocoa_init.m cocoa_joystick.m cocoa_monitor.m - cocoa_window.m cocoa_time.c posix_thread.c - nsgl_context.m egl_context.c osmesa_context.c) -elseif (_GLFW_WIN32) - target_sources(glfw PRIVATE win32_platform.h win32_joystick.h wgl_context.h - egl_context.h osmesa_context.h win32_init.c - win32_joystick.c win32_monitor.c win32_time.c - win32_thread.c win32_window.c wgl_context.c - egl_context.c osmesa_context.c) -elseif (_GLFW_X11) - target_sources(glfw PRIVATE x11_platform.h xkb_unicode.h posix_time.h - posix_thread.h glx_context.h egl_context.h - osmesa_context.h x11_init.c x11_monitor.c - x11_window.c xkb_unicode.c posix_time.c - posix_thread.c glx_context.c egl_context.c - osmesa_context.c) -elseif (_GLFW_WAYLAND) - target_sources(glfw PRIVATE wl_platform.h posix_time.h posix_thread.h - xkb_unicode.h egl_context.h osmesa_context.h - wl_init.c wl_monitor.c wl_window.c posix_time.c - posix_thread.c xkb_unicode.c egl_context.c - osmesa_context.c) -elseif (_GLFW_OSMESA) - target_sources(glfw PRIVATE null_platform.h null_joystick.h posix_time.h - posix_thread.h osmesa_context.h null_init.c - null_monitor.c null_window.c null_joystick.c - posix_time.c posix_thread.c osmesa_context.c) +if (GLFW_BUILD_COCOA) + target_compile_definitions(glfw PRIVATE _GLFW_COCOA) + target_sources(glfw PRIVATE cocoa_platform.h cocoa_joystick.h cocoa_init.m + cocoa_joystick.m cocoa_monitor.m cocoa_window.m + nsgl_context.m) endif() -if (_GLFW_X11 OR _GLFW_WAYLAND) +if (GLFW_BUILD_WIN32) + target_compile_definitions(glfw PRIVATE _GLFW_WIN32) + target_sources(glfw PRIVATE win32_platform.h win32_joystick.h win32_init.c + win32_joystick.c win32_monitor.c win32_window.c + wgl_context.c) +endif() + +if (GLFW_BUILD_X11) + target_compile_definitions(glfw PRIVATE _GLFW_X11) + target_sources(glfw PRIVATE x11_platform.h xkb_unicode.h x11_init.c + x11_monitor.c x11_window.c xkb_unicode.c + glx_context.c) +endif() + +if (GLFW_BUILD_WAYLAND) + target_compile_definitions(glfw PRIVATE _GLFW_WAYLAND) + target_sources(glfw PRIVATE wl_platform.h xkb_unicode.h wl_init.c + wl_monitor.c wl_window.c xkb_unicode.c) +endif() + +if (GLFW_BUILD_X11 OR GLFW_BUILD_WAYLAND) if (CMAKE_SYSTEM_NAME STREQUAL "Linux") target_sources(glfw PRIVATE linux_joystick.h linux_joystick.c) - else() - target_sources(glfw PRIVATE null_joystick.h null_joystick.c) endif() + target_sources(glfw PRIVATE posix_poll.h posix_poll.c) endif() -if (_GLFW_WAYLAND) +if (GLFW_BUILD_WAYLAND) + include(CheckIncludeFiles) + include(CheckFunctionExists) + check_function_exists(memfd_create HAVE_MEMFD_CREATE) + if (HAVE_MEMFD_CREATE) + target_compile_definitions(glfw PRIVATE HAVE_MEMFD_CREATE) + endif() + find_program(WAYLAND_SCANNER_EXECUTABLE NAMES wayland-scanner) + + include(FindPkgConfig) pkg_check_modules(WAYLAND_PROTOCOLS REQUIRED wayland-protocols>=1.15) pkg_get_variable(WAYLAND_PROTOCOLS_BASE wayland-protocols pkgdatadir) pkg_get_variable(WAYLAND_CLIENT_PKGDATADIR wayland-client pkgdatadir) @@ -102,9 +120,12 @@ if (WIN32 AND GLFW_BUILD_SHARED_LIBRARY) target_sources(glfw PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/glfw.rc") endif() -configure_file(glfw_config.h.in glfw_config.h @ONLY) -target_compile_definitions(glfw PRIVATE _GLFW_USE_CONFIG_H) -target_sources(glfw PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/glfw_config.h") +if (UNIX AND GLFW_BUILD_SHARED_LIBRARY) + # On Unix-like systems, shared libraries can use the soname system. + set(GLFW_LIB_NAME glfw) +else() + set(GLFW_LIB_NAME glfw3) +endif() set_target_properties(glfw PROPERTIES OUTPUT_NAME ${GLFW_LIB_NAME} @@ -121,9 +142,8 @@ target_include_directories(glfw PUBLIC "$") target_include_directories(glfw PRIVATE "${GLFW_SOURCE_DIR}/src" - "${GLFW_BINARY_DIR}/src" - ${glfw_INCLUDE_DIRS}) -target_link_libraries(glfw PRIVATE Threads::Threads ${glfw_LIBRARIES}) + "${GLFW_BINARY_DIR}/src") +target_link_libraries(glfw PRIVATE Threads::Threads) # Workaround for CMake not knowing about .m files before version 3.16 if (CMAKE_VERSION VERSION_LESS "3.16" AND APPLE) @@ -132,17 +152,116 @@ if (CMAKE_VERSION VERSION_LESS "3.16" AND APPLE) LANGUAGE C) endif() +if (GLFW_BUILD_WIN32) + list(APPEND glfw_PKG_LIBS "-lgdi32") +endif() + +if (GLFW_BUILD_COCOA) + target_link_libraries(glfw PRIVATE "-framework Cocoa" + "-framework IOKit" + "-framework CoreFoundation") + + set(glfw_PKG_DEPS "") + set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation") +endif() + +if (GLFW_BUILD_WAYLAND) + pkg_check_modules(Wayland REQUIRED + wayland-client>=0.2.7 + wayland-cursor>=0.2.7 + wayland-egl>=0.2.7 + xkbcommon>=0.5.0) + + target_include_directories(glfw PRIVATE ${Wayland_INCLUDE_DIRS}) + + if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") + find_package(EpollShim) + if (EPOLLSHIM_FOUND) + target_include_directories(glfw PRIVATE ${EPOLLSHIM_INCLUDE_DIRS}) + target_link_libraries(glfw PRIVATE ${EPOLLSHIM_LIBRARIES}) + endif() + endif() +endif() + +if (GLFW_BUILD_X11) + find_package(X11 REQUIRED) + target_include_directories(glfw PRIVATE "${X11_X11_INCLUDE_PATH}") + + # Check for XRandR (modern resolution switching and gamma control) + if (NOT X11_Xrandr_INCLUDE_PATH) + message(FATAL_ERROR "RandR headers not found; install libxrandr development package") + endif() + target_include_directories(glfw PRIVATE "${X11_Xrandr_INCLUDE_PATH}") + + # Check for Xinerama (legacy multi-monitor support) + if (NOT X11_Xinerama_INCLUDE_PATH) + message(FATAL_ERROR "Xinerama headers not found; install libxinerama development package") + endif() + target_include_directories(glfw PRIVATE "${X11_Xinerama_INCLUDE_PATH}") + + # Check for Xkb (X keyboard extension) + if (NOT X11_Xkb_INCLUDE_PATH) + message(FATAL_ERROR "XKB headers not found; install X11 development package") + endif() + target_include_directories(glfw PRIVATE "${X11_Xkb_INCLUDE_PATH}") + + # Check for Xcursor (cursor creation from RGBA images) + if (NOT X11_Xcursor_INCLUDE_PATH) + message(FATAL_ERROR "Xcursor headers not found; install libxcursor development package") + endif() + target_include_directories(glfw PRIVATE "${X11_Xcursor_INCLUDE_PATH}") + + # Check for XInput (modern HID input) + if (NOT X11_Xi_INCLUDE_PATH) + message(FATAL_ERROR "XInput headers not found; install libxi development package") + endif() + target_include_directories(glfw PRIVATE "${X11_Xi_INCLUDE_PATH}") + + # Check for X Shape (custom window input shape) + if (NOT X11_Xshape_INCLUDE_PATH) + message(FATAL_ERROR "X Shape headers not found; install libxext development package") + endif() + target_include_directories(glfw PRIVATE "${X11_Xshape_INCLUDE_PATH}") +endif() + +if (UNIX AND NOT APPLE) + find_library(RT_LIBRARY rt) + mark_as_advanced(RT_LIBRARY) + if (RT_LIBRARY) + target_link_libraries(glfw PRIVATE "${RT_LIBRARY}") + list(APPEND glfw_PKG_LIBS "-lrt") + endif() + + find_library(MATH_LIBRARY m) + mark_as_advanced(MATH_LIBRARY) + if (MATH_LIBRARY) + target_link_libraries(glfw PRIVATE "${MATH_LIBRARY}") + list(APPEND glfw_PKG_LIBS "-lm") + endif() + + if (CMAKE_DL_LIBS) + target_link_libraries(glfw PRIVATE "${CMAKE_DL_LIBS}") + list(APPEND glfw_PKG_LIBS "-l${CMAKE_DL_LIBS}") + endif() +endif() + # Make GCC warn about declarations that VS 2010 and 2012 won't accept for all # source files that VS will build (Clang ignores this because we set -std=c99) if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - set_source_files_properties(context.c init.c input.c monitor.c vulkan.c - window.c win32_init.c win32_joystick.c - win32_monitor.c win32_time.c win32_thread.c - win32_window.c wgl_context.c egl_context.c - osmesa_context.c PROPERTIES + set_source_files_properties(context.c init.c input.c monitor.c platform.c vulkan.c + window.c null_init.c null_joystick.c null_monitor.c + null_window.c win32_init.c win32_joystick.c win32_module.c + win32_monitor.c win32_time.c win32_thread.c win32_window.c + wgl_context.c egl_context.c osmesa_context.c PROPERTIES COMPILE_FLAGS -Wdeclaration-after-statement) endif() +if (WIN32) + if (GLFW_USE_HYBRID_HPG) + target_compile_definitions(glfw PRIVATE _GLFW_USE_HYBRID_HPG) + endif() +endif() + # Enable a reasonable set of warnings # NOTE: The order matters here, Clang-CL matches both MSVC and Clang if (MSVC) @@ -154,7 +273,7 @@ elseif (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR target_compile_options(glfw PRIVATE "-Wall") endif() -if (_GLFW_WIN32) +if (GLFW_BUILD_WIN32) target_compile_definitions(glfw PRIVATE UNICODE _UNICODE) endif() @@ -196,7 +315,7 @@ if (MSVC90) endif() # Workaround for -std=c99 on Linux disabling _DEFAULT_SOURCE (POSIX 2008 and more) -if (_GLFW_X11 OR _GLFW_WAYLAND OR _GLFW_OSMESA) +if (GLFW_BUILD_X11 OR GLFW_BUILD_WAYLAND) if (CMAKE_SYSTEM_NAME STREQUAL "Linux") target_compile_definitions(glfw PRIVATE _DEFAULT_SOURCE) endif() @@ -257,6 +376,20 @@ if (GLFW_BUILD_SHARED_LIBRARY) endif() endif() +foreach(arg ${glfw_PKG_DEPS}) + string(APPEND deps " ${arg}") +endforeach() +foreach(arg ${glfw_PKG_LIBS}) + string(APPEND libs " ${arg}") +endforeach() + +set(GLFW_PKG_CONFIG_REQUIRES_PRIVATE "${deps}" CACHE INTERNAL + "GLFW pkg-config Requires.private") +set(GLFW_PKG_CONFIG_LIBS_PRIVATE "${libs}" CACHE INTERNAL + "GLFW pkg-config Libs.private") + +configure_file("${GLFW_SOURCE_DIR}/CMake/glfw3.pc.in" glfw3.pc @ONLY) + if (GLFW_INSTALL) install(TARGETS glfw EXPORT glfwTargets diff --git a/src/cocoa_init.m b/src/cocoa_init.m index d12f3427..b3831df1 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -27,6 +27,9 @@ //======================================================================== #include "internal.h" + +#if defined(_GLFW_COCOA) + #include // For MAXPATHLEN // Needed for _NSGetProgname @@ -75,7 +78,6 @@ static void changeToResourcesDirectory(void) // static void createMenuBar(void) { - size_t i; NSString* appName = nil; NSDictionary* bundleInfo = [[NSBundle mainBundle] infoDictionary]; NSString* nameKeys[] = @@ -87,7 +89,7 @@ static void createMenuBar(void) // Try to figure out what the calling application is called - for (i = 0; i < sizeof(nameKeys) / sizeof(nameKeys[0]); i++) + for (size_t i = 0; i < sizeof(nameKeys) / sizeof(nameKeys[0]); i++) { id name = bundleInfo[nameKeys[i]]; if (name && @@ -177,8 +179,6 @@ static void createMenuBar(void) // static void createKeyTables(void) { - int scancode; - memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes)); memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes)); @@ -297,7 +297,7 @@ static void createKeyTables(void) _glfw.ns.keycodes[0x43] = GLFW_KEY_KP_MULTIPLY; _glfw.ns.keycodes[0x4E] = GLFW_KEY_KP_SUBTRACT; - for (scancode = 0; scancode < 256; scancode++) + for (int scancode = 0; scancode < 256; scancode++) { // Store the reverse translation for faster key name lookup if (_glfw.ns.keycodes[scancode] >= 0) @@ -307,7 +307,7 @@ static void createKeyTables(void) // Retrieve Unicode data for the current keyboard layout // -static GLFWbool updateUnicodeDataNS(void) +static GLFWbool updateUnicodeData(void) { if (_glfw.ns.inputSource) { @@ -377,7 +377,7 @@ static GLFWbool initializeTIS(void) _glfw.ns.tis.kPropertyUnicodeKeyLayoutData = *kPropertyUnicodeKeyLayoutData; - return updateUnicodeDataNS(); + return updateUnicodeData(); } @interface GLFWHelper : NSObject @@ -387,7 +387,7 @@ static GLFWbool initializeTIS(void) - (void)selectedKeyboardInputSourceChanged:(NSObject* )object { - updateUnicodeDataNS(); + updateUnicodeData(); } - (void)doNothing:(id)object @@ -403,9 +403,7 @@ static GLFWbool initializeTIS(void) - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { - _GLFWwindow* window; - - for (window = _glfw.windowListHead; window; window = window->next) + for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next) _glfwInputWindowCloseRequest(window); return NSTerminateCancel; @@ -413,15 +411,13 @@ static GLFWbool initializeTIS(void) - (void)applicationDidChangeScreenParameters:(NSNotification *) notification { - _GLFWwindow* window; - - for (window = _glfw.windowListHead; window; window = window->next) + for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next) { if (window->context.client != GLFW_NO_API) [window->context.nsgl.object update]; } - _glfwPollMonitorsNS(); + _glfwPollMonitorsCocoa(); } - (void)applicationWillFinishLaunching:(NSNotification *)notification @@ -444,16 +440,14 @@ static GLFWbool initializeTIS(void) - (void)applicationDidFinishLaunching:(NSNotification *)notification { - _glfwPlatformPostEmptyEvent(); + _glfwPostEmptyEventCocoa(); [NSApp stop:nil]; } - (void)applicationDidHide:(NSNotification *)notification { - int i; - - for (i = 0; i < _glfw.monitorCount; i++) - _glfwRestoreVideoModeNS(_glfw.monitors[i]); + for (int i = 0; i < _glfw.monitorCount; i++) + _glfwRestoreVideoModeCocoa(_glfw.monitors[i]); } @end // GLFWApplicationDelegate @@ -463,24 +457,32 @@ static GLFWbool initializeTIS(void) ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// -void* _glfwLoadLocalVulkanLoaderNS(void) +void* _glfwLoadLocalVulkanLoaderCocoa(void) { CFBundleRef bundle = CFBundleGetMainBundle(); if (!bundle) return NULL; - CFURLRef url = - CFBundleCopyAuxiliaryExecutableURL(bundle, CFSTR("libvulkan.1.dylib")); - if (!url) + CFURLRef frameworksUrl = CFBundleCopyPrivateFrameworksURL(bundle); + if (!frameworksUrl) return NULL; + CFURLRef loaderUrl = CFURLCreateCopyAppendingPathComponent( + kCFAllocatorDefault, frameworksUrl, CFSTR("libvulkan.1.dylib"), false); + if (!loaderUrl) + { + CFRelease(frameworksUrl); + return NULL; + } + char path[PATH_MAX]; void* handle = NULL; - if (CFURLGetFileSystemRepresentation(url, true, (UInt8*) path, sizeof(path) - 1)) - handle = _glfw_dlopen(path); + if (CFURLGetFileSystemRepresentation(loaderUrl, true, (UInt8*) path, sizeof(path) - 1)) + handle = _glfwPlatformLoadModule(path); - CFRelease(url); + CFRelease(loaderUrl); + CFRelease(frameworksUrl); return handle; } @@ -489,7 +491,89 @@ void* _glfwLoadLocalVulkanLoaderNS(void) ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -int _glfwPlatformInit(void) +GLFWbool _glfwConnectCocoa(int platformID, _GLFWplatform* platform) +{ + const _GLFWplatform cocoa = + { + GLFW_PLATFORM_COCOA, + _glfwInitCocoa, + _glfwTerminateCocoa, + _glfwGetCursorPosCocoa, + _glfwSetCursorPosCocoa, + _glfwSetCursorModeCocoa, + _glfwSetRawMouseMotionCocoa, + _glfwRawMouseMotionSupportedCocoa, + _glfwCreateCursorCocoa, + _glfwCreateStandardCursorCocoa, + _glfwDestroyCursorCocoa, + _glfwSetCursorCocoa, + _glfwGetScancodeNameCocoa, + _glfwGetKeyScancodeCocoa, + _glfwSetClipboardStringCocoa, + _glfwGetClipboardStringCocoa, + _glfwInitJoysticksCocoa, + _glfwTerminateJoysticksCocoa, + _glfwPollJoystickCocoa, + _glfwGetMappingNameCocoa, + _glfwUpdateGamepadGUIDCocoa, + _glfwFreeMonitorCocoa, + _glfwGetMonitorPosCocoa, + _glfwGetMonitorContentScaleCocoa, + _glfwGetMonitorWorkareaCocoa, + _glfwGetVideoModesCocoa, + _glfwGetVideoModeCocoa, + _glfwGetGammaRampCocoa, + _glfwSetGammaRampCocoa, + _glfwCreateWindowCocoa, + _glfwDestroyWindowCocoa, + _glfwSetWindowTitleCocoa, + _glfwSetWindowIconCocoa, + _glfwGetWindowPosCocoa, + _glfwSetWindowPosCocoa, + _glfwGetWindowSizeCocoa, + _glfwSetWindowSizeCocoa, + _glfwSetWindowSizeLimitsCocoa, + _glfwSetWindowAspectRatioCocoa, + _glfwGetFramebufferSizeCocoa, + _glfwGetWindowFrameSizeCocoa, + _glfwGetWindowContentScaleCocoa, + _glfwIconifyWindowCocoa, + _glfwRestoreWindowCocoa, + _glfwMaximizeWindowCocoa, + _glfwShowWindowCocoa, + _glfwHideWindowCocoa, + _glfwRequestWindowAttentionCocoa, + _glfwFocusWindowCocoa, + _glfwSetWindowMonitorCocoa, + _glfwWindowFocusedCocoa, + _glfwWindowIconifiedCocoa, + _glfwWindowVisibleCocoa, + _glfwWindowMaximizedCocoa, + _glfwWindowHoveredCocoa, + _glfwFramebufferTransparentCocoa, + _glfwGetWindowOpacityCocoa, + _glfwSetWindowResizableCocoa, + _glfwSetWindowDecoratedCocoa, + _glfwSetWindowFloatingCocoa, + _glfwSetWindowOpacityCocoa, + _glfwSetWindowMousePassthroughCocoa, + _glfwPollEventsCocoa, + _glfwWaitEventsCocoa, + _glfwWaitEventsTimeoutCocoa, + _glfwPostEmptyEventCocoa, + _glfwGetEGLPlatformCocoa, + _glfwGetEGLNativeDisplayCocoa, + _glfwGetEGLNativeWindowCocoa, + _glfwGetRequiredInstanceExtensionsCocoa, + _glfwGetPhysicalDevicePresentationSupportCocoa, + _glfwCreateWindowSurfaceCocoa, + }; + + *platform = cocoa; + return GLFW_TRUE; +} + +int _glfwInitCocoa(void) { @autoreleasepool { @@ -547,9 +631,7 @@ int _glfwPlatformInit(void) if (!initializeTIS()) return GLFW_FALSE; - _glfwInitTimerNS(); - - _glfwPollMonitorsNS(); + _glfwPollMonitorsCocoa(); if (![[NSRunningApplication currentApplication] isFinishedLaunching]) [NSApp run]; @@ -563,7 +645,7 @@ int _glfwPlatformInit(void) } // autoreleasepool } -void _glfwPlatformTerminate(void) +void _glfwTerminateCocoa(void) { @autoreleasepool { @@ -605,16 +687,11 @@ void _glfwPlatformTerminate(void) _glfw_free(_glfw.ns.clipboardString); _glfwTerminateNSGL(); + _glfwTerminateEGL(); + _glfwTerminateOSMesa(); } // autoreleasepool } -const char* _glfwPlatformGetVersionString(void) -{ - return _GLFW_VERSION_NUMBER " Cocoa NSGL EGL OSMesa" -#if defined(_GLFW_BUILD_DLL) - " dynamic" -#endif - ; -} +#endif // _GLFW_COCOA diff --git a/src/cocoa_joystick.h b/src/cocoa_joystick.h index 7a121c8b..2f46dfcb 100644 --- a/src/cocoa_joystick.h +++ b/src/cocoa_joystick.h @@ -26,14 +26,10 @@ #include #include -#include #include -#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickNS ns -#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE struct { int dummyJoystick; } - -#define _GLFW_PLATFORM_MAPPING_NAME "Mac OS X" -#define GLFW_BUILD_COCOA_MAPPINGS +#define GLFW_COCOA_JOYSTICK_STATE _GLFWjoystickNS ns; +#define GLFW_COCOA_LIBRARY_JOYSTICK_STATE // Cocoa-specific per-joystick data // @@ -45,3 +41,9 @@ typedef struct _GLFWjoystickNS CFMutableArrayRef hats; } _GLFWjoystickNS; +GLFWbool _glfwInitJoysticksCocoa(void); +void _glfwTerminateJoysticksCocoa(void); +GLFWbool _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode); +const char* _glfwGetMappingNameCocoa(void); +void _glfwUpdateGamepadGUIDCocoa(char* guid); + diff --git a/src/cocoa_joystick.m b/src/cocoa_joystick.m index a8081d2c..865adac7 100644 --- a/src/cocoa_joystick.m +++ b/src/cocoa_joystick.m @@ -29,6 +29,8 @@ #include "internal.h" +#if defined(_GLFW_COCOA) + #include #include #include @@ -96,25 +98,21 @@ static CFComparisonResult compareElements(const void* fp, // static void closeJoystick(_GLFWjoystick* js) { - int i; + _glfwInputJoystick(js, GLFW_DISCONNECTED); - if (!js->present) - return; - - for (i = 0; i < CFArrayGetCount(js->ns.axes); i++) + for (int i = 0; i < CFArrayGetCount(js->ns.axes); i++) _glfw_free((void*) CFArrayGetValueAtIndex(js->ns.axes, i)); CFRelease(js->ns.axes); - for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++) + for (int i = 0; i < CFArrayGetCount(js->ns.buttons); i++) _glfw_free((void*) CFArrayGetValueAtIndex(js->ns.buttons, i)); CFRelease(js->ns.buttons); - for (i = 0; i < CFArrayGetCount(js->ns.hats); i++) + for (int i = 0; i < CFArrayGetCount(js->ns.hats); i++) _glfw_free((void*) CFArrayGetValueAtIndex(js->ns.hats, i)); CFRelease(js->ns.hats); _glfwFreeJoystick(js); - _glfwInputJoystick(js, GLFW_DISCONNECTED); } // Callback for user-initiated joystick addition @@ -127,7 +125,6 @@ static void matchCallback(void* context, int jid; char name[256]; char guid[33]; - CFIndex i; CFTypeRef property; uint32_t vendor = 0, product = 0, version = 0; _GLFWjoystick* js; @@ -185,7 +182,7 @@ static void matchCallback(void* context, CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone); - for (i = 0; i < CFArrayGetCount(elements); i++) + for (CFIndex i = 0; i < CFArrayGetCount(elements); i++) { IOHIDElementRef native = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, i); @@ -290,13 +287,11 @@ static void removeCallback(void* context, void* sender, IOHIDDeviceRef device) { - int jid; - - for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) + for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) { - if (_glfw.joysticks[jid].ns.device == device) + if (_glfw.joysticks[jid].connected && _glfw.joysticks[jid].ns.device == device) { - closeJoystick(_glfw.joysticks + jid); + closeJoystick(&_glfw.joysticks[jid]); break; } } @@ -307,7 +302,7 @@ static void removeCallback(void* context, ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -GLFWbool _glfwPlatformInitJoysticks(void) +GLFWbool _glfwInitJoysticksCocoa(void) { CFMutableArrayRef matching; const long usages[] = @@ -384,12 +379,13 @@ GLFWbool _glfwPlatformInitJoysticks(void) return GLFW_TRUE; } -void _glfwPlatformTerminateJoysticks(void) +void _glfwTerminateJoysticksCocoa(void) { - int jid; - - for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) - closeJoystick(_glfw.joysticks + jid); + for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) + { + if (_glfw.joysticks[jid].connected) + closeJoystick(&_glfw.joysticks[jid]); + } if (_glfw.ns.hidManager) { @@ -399,13 +395,11 @@ void _glfwPlatformTerminateJoysticks(void) } -int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) +GLFWbool _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode) { if (mode & _GLFW_POLL_AXES) { - CFIndex i; - - for (i = 0; i < CFArrayGetCount(js->ns.axes); i++) + for (CFIndex i = 0; i < CFArrayGetCount(js->ns.axes); i++) { _GLFWjoyelementNS* axis = (_GLFWjoyelementNS*) CFArrayGetValueAtIndex(js->ns.axes, i); @@ -430,9 +424,7 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) if (mode & _GLFW_POLL_BUTTONS) { - CFIndex i; - - for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++) + for (CFIndex i = 0; i < CFArrayGetCount(js->ns.buttons); i++) { _GLFWjoyelementNS* button = (_GLFWjoyelementNS*) CFArrayGetValueAtIndex(js->ns.buttons, i); @@ -441,7 +433,7 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) _glfwInputJoystickButton(js, (int) i, state); } - for (i = 0; i < CFArrayGetCount(js->ns.hats); i++) + for (CFIndex i = 0; i < CFArrayGetCount(js->ns.hats); i++) { const int states[9] = { @@ -466,10 +458,15 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) } } - return js->present; + return js->connected; } -void _glfwPlatformUpdateGamepadGUID(char* guid) +const char* _glfwGetMappingNameCocoa(void) +{ + return "Mac OS X"; +} + +void _glfwUpdateGamepadGUIDCocoa(char* guid) { if ((strncmp(guid + 4, "000000000000", 12) == 0) && (strncmp(guid + 20, "000000000000", 12) == 0)) @@ -481,3 +478,5 @@ void _glfwPlatformUpdateGamepadGUID(char* guid) } } +#endif // _GLFW_COCOA + diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index 2462beab..6c7315bd 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -29,6 +29,8 @@ #include "internal.h" +#if defined(_GLFW_COCOA) + #include #include #include @@ -58,7 +60,7 @@ static char* getMonitorName(CGDirectDisplayID displayID, NSScreen* screen) io_service_t service; CFDictionaryRef info; - if (IOServiceGetMatchingServices(kIOMasterPortDefault, + if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("IODisplayConnect"), &it) != 0) { @@ -98,11 +100,7 @@ static char* getMonitorName(CGDirectDisplayID displayID, NSScreen* screen) IOObjectRelease(it); if (!service) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Cocoa: Failed to find service port for display"); return _glfw_strdup("Display"); - } CFDictionaryRef names = CFDictionaryGetValue(info, CFSTR(kDisplayProductName)); @@ -231,7 +229,7 @@ static double getFallbackRefreshRate(CGDirectDisplayID displayID) io_iterator_t it; io_service_t service; - if (IOServiceGetMatchingServices(kIOMasterPortDefault, + if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("IOFramebuffer"), &it) != 0) { @@ -297,7 +295,7 @@ static double getFallbackRefreshRate(CGDirectDisplayID displayID) // Poll for changes in the set of connected monitors // -void _glfwPollMonitorsNS(void) +void _glfwPollMonitorsCocoa(void) { uint32_t displayCount; CGGetOnlineDisplayList(0, NULL, &displayCount); @@ -385,10 +383,10 @@ void _glfwPollMonitorsNS(void) // Change the current video mode // -void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired) +void _glfwSetVideoModeCocoa(_GLFWmonitor* monitor, const GLFWvidmode* desired) { GLFWvidmode current; - _glfwPlatformGetVideoMode(monitor, ¤t); + _glfwGetVideoModeCocoa(monitor, ¤t); const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired); if (_glfwCompareVideoModes(¤t, best) == 0) @@ -428,7 +426,7 @@ void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired) // Restore the previously saved (original) video mode // -void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor) +void _glfwRestoreVideoModeCocoa(_GLFWmonitor* monitor) { if (monitor->ns.previousMode) { @@ -447,11 +445,11 @@ void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor) ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor) +void _glfwFreeMonitorCocoa(_GLFWmonitor* monitor) { } -void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) +void _glfwGetMonitorPosCocoa(_GLFWmonitor* monitor, int* xpos, int* ypos) { @autoreleasepool { @@ -465,8 +463,8 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) } // autoreleasepool } -void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, - float* xscale, float* yscale) +void _glfwGetMonitorContentScaleCocoa(_GLFWmonitor* monitor, + float* xscale, float* yscale) { @autoreleasepool { @@ -487,9 +485,9 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, } // autoreleasepool } -void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, - int* xpos, int* ypos, - int* width, int* height) +void _glfwGetMonitorWorkareaCocoa(_GLFWmonitor* monitor, + int* xpos, int* ypos, + int* width, int* height) { @autoreleasepool { @@ -504,7 +502,7 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, if (xpos) *xpos = frameRect.origin.x; if (ypos) - *ypos = _glfwTransformYNS(frameRect.origin.y + frameRect.size.height - 1); + *ypos = _glfwTransformYCocoa(frameRect.origin.y + frameRect.size.height - 1); if (width) *width = frameRect.size.width; if (height) @@ -513,7 +511,7 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, } // autoreleasepool } -GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) +GLFWvidmode* _glfwGetVideoModesCocoa(_GLFWmonitor* monitor, int* count) { @autoreleasepool { @@ -553,7 +551,7 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) } // autoreleasepool } -void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode) +void _glfwGetVideoModeCocoa(_GLFWmonitor* monitor, GLFWvidmode *mode) { @autoreleasepool { @@ -564,7 +562,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode) } // autoreleasepool } -GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) +GLFWbool _glfwGetGammaRampCocoa(_GLFWmonitor* monitor, GLFWgammaramp* ramp) { @autoreleasepool { @@ -593,7 +591,7 @@ GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) } // autoreleasepool } -void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) +void _glfwSetGammaRampCocoa(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) { @autoreleasepool { @@ -629,3 +627,5 @@ GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* handle) return monitor->ns.displayID; } +#endif // _GLFW_COCOA + diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 64a998ff..9f7d191d 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -25,9 +25,9 @@ //======================================================================== #include -#include #include +#include // NOTE: All of NSGL was deprecated in the 10.14 SDK // This disables the pointless warnings for every symbol we use @@ -42,8 +42,15 @@ typedef void* id; #endif // NOTE: Many Cocoa enum values have been renamed and we need to build across -// SDK versions where one is unavailable or the other deprecated -// We use the newer names in code and these macros to handle compatibility +// SDK versions where one is unavailable or deprecated. +// We use the newer names in code and replace them with the older names if +// the base SDK does not provide the newer names. + +#if MAC_OS_X_VERSION_MAX_ALLOWED < 101400 + #define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval + #define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity +#endif + #if MAC_OS_X_VERSION_MAX_ALLOWED < 101200 #define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat #define NSEventMaskAny NSAnyEventMask @@ -62,6 +69,15 @@ typedef void* id; #define NSWindowStyleMaskTitled NSTitledWindowMask #endif +// NOTE: Many Cocoa dynamically linked constants have been renamed and we need +// to build across SDK versions where one is unavailable or deprecated. +// We use the newer names in code and replace them with the older names if +// the deployment target is older than the newer names. + +#if MAC_OS_X_VERSION_MIN_REQUIRED < 101300 + #define NSPasteboardTypeURL NSURLPboardType +#endif + typedef VkFlags VkMacOSSurfaceCreateFlagsMVK; typedef VkFlags VkMetalSurfaceCreateFlagsEXT; @@ -84,19 +100,13 @@ typedef struct VkMetalSurfaceCreateInfoEXT typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*); typedef VkResult (APIENTRY *PFN_vkCreateMetalSurfaceEXT)(VkInstance,const VkMetalSurfaceCreateInfoEXT*,const VkAllocationCallbacks*,VkSurfaceKHR*); -#include "posix_thread.h" -#include "cocoa_joystick.h" -#include "nsgl_context.h" +#define GLFW_COCOA_WINDOW_STATE _GLFWwindowNS ns; +#define GLFW_COCOA_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns; +#define GLFW_COCOA_MONITOR_STATE _GLFWmonitorNS ns; +#define GLFW_COCOA_CURSOR_STATE _GLFWcursorNS ns; -#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) -#define _glfw_dlclose(handle) dlclose(handle) -#define _glfw_dlsym(handle, name) dlsym(handle, name) - -#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS ns -#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns -#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerNS ns -#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNS ns -#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorNS ns +#define GLFW_NSGL_CONTEXT_STATE _GLFWcontextNSGL nsgl; +#define GLFW_NSGL_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl; // HIToolbox.framework pointer typedefs #define kTISPropertyUnicodeKeyLayoutData _glfw.ns.tis.kPropertyUnicodeKeyLayoutData @@ -108,6 +118,22 @@ typedef UInt8 (*PFN_LMGetKbdType)(void); #define LMGetKbdType _glfw.ns.tis.GetKbdType +// NSGL-specific per-context data +// +typedef struct _GLFWcontextNSGL +{ + id pixelFormat; + id object; +} _GLFWcontextNSGL; + +// NSGL-specific global data +// +typedef struct _GLFWlibraryNSGL +{ + // dlopen handle for OpenGL.framework (for glfwGetProcAddress) + CFBundleRef framework; +} _GLFWlibraryNSGL; + // Cocoa-specific per-window data // typedef struct _GLFWwindowNS @@ -130,7 +156,6 @@ typedef struct _GLFWwindowNS // since the last cursor motion event was processed // This is kept to counteract Cocoa doing the same internally double cursorWarpDeltaX, cursorWarpDeltaY; - } _GLFWwindowNS; // Cocoa-specific global data @@ -164,7 +189,6 @@ typedef struct _GLFWlibraryNS PFN_LMGetKbdType GetKbdType; CFStringRef kPropertyUnicodeKeyLayoutData; } tis; - } _GLFWlibraryNS; // Cocoa-specific per-monitor data @@ -176,7 +200,6 @@ typedef struct _GLFWmonitorNS uint32_t unitNumber; id screen; double fallbackRefreshRate; - } _GLFWmonitorNS; // Cocoa-specific per-cursor data @@ -184,25 +207,96 @@ typedef struct _GLFWmonitorNS typedef struct _GLFWcursorNS { id object; - } _GLFWcursorNS; -// Cocoa-specific global timer data -// -typedef struct _GLFWtimerNS -{ - uint64_t frequency; -} _GLFWtimerNS; +GLFWbool _glfwConnectCocoa(int platformID, _GLFWplatform* platform); +int _glfwInitCocoa(void); +void _glfwTerminateCocoa(void); +GLFWbool _glfwCreateWindowCocoa(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); +void _glfwDestroyWindowCocoa(_GLFWwindow* window); +void _glfwSetWindowTitleCocoa(_GLFWwindow* window, const char* title); +void _glfwSetWindowIconCocoa(_GLFWwindow* window, int count, const GLFWimage* images); +void _glfwGetWindowPosCocoa(_GLFWwindow* window, int* xpos, int* ypos); +void _glfwSetWindowPosCocoa(_GLFWwindow* window, int xpos, int ypos); +void _glfwGetWindowSizeCocoa(_GLFWwindow* window, int* width, int* height); +void _glfwSetWindowSizeCocoa(_GLFWwindow* window, int width, int height); +void _glfwSetWindowSizeLimitsCocoa(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); +void _glfwSetWindowAspectRatioCocoa(_GLFWwindow* window, int numer, int denom); +void _glfwGetFramebufferSizeCocoa(_GLFWwindow* window, int* width, int* height); +void _glfwGetWindowFrameSizeCocoa(_GLFWwindow* window, int* left, int* top, int* right, int* bottom); +void _glfwGetWindowContentScaleCocoa(_GLFWwindow* window, float* xscale, float* yscale); +void _glfwIconifyWindowCocoa(_GLFWwindow* window); +void _glfwRestoreWindowCocoa(_GLFWwindow* window); +void _glfwMaximizeWindowCocoa(_GLFWwindow* window); +void _glfwShowWindowCocoa(_GLFWwindow* window); +void _glfwHideWindowCocoa(_GLFWwindow* window); +void _glfwRequestWindowAttentionCocoa(_GLFWwindow* window); +void _glfwFocusWindowCocoa(_GLFWwindow* window); +void _glfwSetWindowMonitorCocoa(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); +GLFWbool _glfwWindowFocusedCocoa(_GLFWwindow* window); +GLFWbool _glfwWindowIconifiedCocoa(_GLFWwindow* window); +GLFWbool _glfwWindowVisibleCocoa(_GLFWwindow* window); +GLFWbool _glfwWindowMaximizedCocoa(_GLFWwindow* window); +GLFWbool _glfwWindowHoveredCocoa(_GLFWwindow* window); +GLFWbool _glfwFramebufferTransparentCocoa(_GLFWwindow* window); +void _glfwSetWindowResizableCocoa(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowDecoratedCocoa(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowFloatingCocoa(_GLFWwindow* window, GLFWbool enabled); +float _glfwGetWindowOpacityCocoa(_GLFWwindow* window); +void _glfwSetWindowOpacityCocoa(_GLFWwindow* window, float opacity); +void _glfwSetWindowMousePassthroughCocoa(_GLFWwindow* window, GLFWbool enabled); -void _glfwInitTimerNS(void); +void _glfwSetRawMouseMotionCocoa(_GLFWwindow *window, GLFWbool enabled); +GLFWbool _glfwRawMouseMotionSupportedCocoa(void); -void _glfwPollMonitorsNS(void); -void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired); -void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor); +void _glfwPollEventsCocoa(void); +void _glfwWaitEventsCocoa(void); +void _glfwWaitEventsTimeoutCocoa(double timeout); +void _glfwPostEmptyEventCocoa(void); -float _glfwTransformYNS(float y); +void _glfwGetCursorPosCocoa(_GLFWwindow* window, double* xpos, double* ypos); +void _glfwSetCursorPosCocoa(_GLFWwindow* window, double xpos, double ypos); +void _glfwSetCursorModeCocoa(_GLFWwindow* window, int mode); +const char* _glfwGetScancodeNameCocoa(int scancode); +int _glfwGetKeyScancodeCocoa(int key); +GLFWbool _glfwCreateCursorCocoa(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot); +GLFWbool _glfwCreateStandardCursorCocoa(_GLFWcursor* cursor, int shape); +void _glfwDestroyCursorCocoa(_GLFWcursor* cursor); +void _glfwSetCursorCocoa(_GLFWwindow* window, _GLFWcursor* cursor); +void _glfwSetClipboardStringCocoa(const char* string); +const char* _glfwGetClipboardStringCocoa(void); -void* _glfwLoadLocalVulkanLoaderNS(void); +EGLenum _glfwGetEGLPlatformCocoa(EGLint** attribs); +EGLNativeDisplayType _glfwGetEGLNativeDisplayCocoa(void); +EGLNativeWindowType _glfwGetEGLNativeWindowCocoa(_GLFWwindow* window); + +void _glfwGetRequiredInstanceExtensionsCocoa(char** extensions); +GLFWbool _glfwGetPhysicalDevicePresentationSupportCocoa(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); +VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +void _glfwFreeMonitorCocoa(_GLFWmonitor* monitor); +void _glfwGetMonitorPosCocoa(_GLFWmonitor* monitor, int* xpos, int* ypos); +void _glfwGetMonitorContentScaleCocoa(_GLFWmonitor* monitor, float* xscale, float* yscale); +void _glfwGetMonitorWorkareaCocoa(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height); +GLFWvidmode* _glfwGetVideoModesCocoa(_GLFWmonitor* monitor, int* count); +void _glfwGetVideoModeCocoa(_GLFWmonitor* monitor, GLFWvidmode* mode); +GLFWbool _glfwGetGammaRampCocoa(_GLFWmonitor* monitor, GLFWgammaramp* ramp); +void _glfwSetGammaRampCocoa(_GLFWmonitor* monitor, const GLFWgammaramp* ramp); + +void _glfwPollMonitorsCocoa(void); +void _glfwSetVideoModeCocoa(_GLFWmonitor* monitor, const GLFWvidmode* desired); +void _glfwRestoreVideoModeCocoa(_GLFWmonitor* monitor); + +float _glfwTransformYCocoa(float y); + +void* _glfwLoadLocalVulkanLoaderCocoa(void); + +GLFWbool _glfwInitNSGL(void); +void _glfwTerminateNSGL(void); +GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig); +void _glfwDestroyContextNSGL(_GLFWwindow* window); diff --git a/src/cocoa_time.c b/src/cocoa_time.c index 4bf646c8..8da367aa 100644 --- a/src/cocoa_time.c +++ b/src/cocoa_time.c @@ -28,16 +28,16 @@ #include "internal.h" +#if defined(GLFW_BUILD_COCOA_TIMER) + #include ////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// +////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -// Initialise timer -// -void _glfwInitTimerNS(void) +void _glfwPlatformInitTimer(void) { mach_timebase_info_data_t info; mach_timebase_info(&info); @@ -45,11 +45,6 @@ void _glfwInitTimerNS(void) _glfw.timer.ns.frequency = (info.denom * 1e9) / info.numer; } - -////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// - uint64_t _glfwPlatformGetTimerValue(void) { return mach_absolute_time(); @@ -60,3 +55,5 @@ uint64_t _glfwPlatformGetTimerFrequency(void) return _glfw.timer.ns.frequency; } +#endif // GLFW_BUILD_COCOA_TIMER + diff --git a/src/cocoa_time.h b/src/cocoa_time.h new file mode 100644 index 00000000..3512e8b6 --- /dev/null +++ b/src/cocoa_time.h @@ -0,0 +1,35 @@ +//======================================================================== +// GLFW 3.4 macOS - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2009-2021 Camilla Löwy +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#define GLFW_COCOA_LIBRARY_TIMER_STATE _GLFWtimerNS ns; + +// Cocoa-specific global timer data +// +typedef struct _GLFWtimerNS +{ + uint64_t frequency; +} _GLFWtimerNS; + diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 49b50749..6f8aa978 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -28,28 +28,14 @@ #include "internal.h" +#if defined(_GLFW_COCOA) + #include #include -// Returns the style mask corresponding to the window settings -// -static NSUInteger getStyleMask(_GLFWwindow* window) -{ - NSUInteger styleMask = NSWindowStyleMaskMiniaturizable; - - if (window->monitor || !window->decorated) - styleMask |= NSWindowStyleMaskBorderless; - else - { - styleMask |= NSWindowStyleMaskTitled | - NSWindowStyleMaskClosable; - - if (window->resizable) - styleMask |= NSWindowStyleMaskResizable; - } - - return styleMask; -} +// HACK: This enum value is missing from framework headers on OS X 10.11 despite +// having been (according to documentation) added in Mac OS X 10.7 +#define NSWindowCollectionBehaviorFullScreenNone (1 << 9) // Returns whether the cursor is in the content area of the specified window // @@ -105,20 +91,20 @@ static void updateCursorMode(_GLFWwindow* window) if (window->cursorMode == GLFW_CURSOR_DISABLED) { _glfw.ns.disabledCursorWindow = window; - _glfwPlatformGetCursorPos(window, - &_glfw.ns.restoreCursorPosX, - &_glfw.ns.restoreCursorPosY); + _glfwGetCursorPosCocoa(window, + &_glfw.ns.restoreCursorPosX, + &_glfw.ns.restoreCursorPosY); _glfwCenterCursorInContentArea(window); CGAssociateMouseAndMouseCursorPosition(false); } else if (_glfw.ns.disabledCursorWindow == window) { _glfw.ns.disabledCursorWindow = NULL; - _glfwPlatformSetCursorPos(window, - _glfw.ns.restoreCursorPosX, - _glfw.ns.restoreCursorPosY); + _glfwSetCursorPosCocoa(window, + _glfw.ns.restoreCursorPosX, + _glfw.ns.restoreCursorPosY); // NOTE: The matching CGAssociateMouseAndMouseCursorPosition call is - // made in _glfwPlatformSetCursorPos as part of a workaround + // made in _glfwSetCursorPosCocoa as part of a workaround } if (cursorInContentArea(window)) @@ -129,10 +115,10 @@ static void updateCursorMode(_GLFWwindow* window) // static void acquireMonitor(_GLFWwindow* window) { - _glfwSetVideoModeNS(window->monitor, &window->videoMode); + _glfwSetVideoModeCocoa(window->monitor, &window->videoMode); const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID); const NSRect frame = NSMakeRect(bounds.origin.x, - _glfwTransformYNS(bounds.origin.y + bounds.size.height - 1), + _glfwTransformYCocoa(bounds.origin.y + bounds.size.height - 1), bounds.size.width, bounds.size.height); @@ -149,7 +135,7 @@ static void releaseMonitor(_GLFWwindow* window) return; _glfwInputMonitorWindow(window->monitor, NULL); - _glfwRestoreVideoModeNS(window->monitor); + _glfwRestoreVideoModeCocoa(window->monitor); } // Translates macOS key modifiers into GLFW ones @@ -286,7 +272,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; _glfwCenterCursorInContentArea(window); int x, y; - _glfwPlatformGetWindowPos(window, &x, &y); + _glfwGetWindowPosCocoa(window, &x, &y); _glfwInputWindowPos(window, x, y); } @@ -318,7 +304,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)windowDidResignKey:(NSNotification *)notification { if (window->monitor && window->autoIconify) - _glfwPlatformIconifyWindow(window); + _glfwIconifyWindowCocoa(window); _glfwInputWindowFocus(window, GLFW_FALSE); } @@ -361,9 +347,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; markedText = [[NSMutableAttributedString alloc] init]; [self updateTrackingAreas]; - // NOTE: kUTTypeURL corresponds to NSPasteboardTypeURL but is available - // on 10.7 without having been deprecated yet - [self registerForDraggedTypes:@[(__bridge NSString*) kUTTypeURL]]; + [self registerForDraggedTypes:@[NSPasteboardTypeURL]]; } return self; @@ -803,17 +787,41 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, GLFWvidmode mode; int xpos, ypos; - _glfwPlatformGetVideoMode(window->monitor, &mode); - _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos); + _glfwGetVideoModeCocoa(window->monitor, &mode); + _glfwGetMonitorPosCocoa(window->monitor, &xpos, &ypos); contentRect = NSMakeRect(xpos, ypos, mode.width, mode.height); } else - contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height); + { + if (wndconfig->xpos == GLFW_ANY_POSITION || + wndconfig->ypos == GLFW_ANY_POSITION) + { + contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height); + } + else + { + const int xpos = wndconfig->xpos; + const int ypos = _glfwTransformYCocoa(wndconfig->ypos + wndconfig->height - 1); + contentRect = NSMakeRect(xpos, ypos, wndconfig->width, wndconfig->height); + } + } + + NSUInteger styleMask = NSWindowStyleMaskMiniaturizable; + + if (window->monitor || !window->decorated) + styleMask |= NSWindowStyleMaskBorderless; + else + { + styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable); + + if (window->resizable) + styleMask |= NSWindowStyleMaskResizable; + } window->ns.object = [[GLFWWindow alloc] initWithContentRect:contentRect - styleMask:getStyleMask(window) + styleMask:styleMask backing:NSBackingStoreBuffered defer:NO]; @@ -827,10 +835,14 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, [window->ns.object setLevel:NSMainMenuWindowLevel + 1]; else { - [(NSWindow*) window->ns.object center]; - _glfw.ns.cascadePoint = - NSPointToCGPoint([window->ns.object cascadeTopLeftFromPoint: - NSPointFromCGPoint(_glfw.ns.cascadePoint)]); + if (wndconfig->xpos == GLFW_ANY_POSITION || + wndconfig->ypos == GLFW_ANY_POSITION) + { + [(NSWindow*) window->ns.object center]; + _glfw.ns.cascadePoint = + NSPointToCGPoint([window->ns.object cascadeTopLeftFromPoint: + NSPointFromCGPoint(_glfw.ns.cascadePoint)]); + } if (wndconfig->resizable) { @@ -839,6 +851,12 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, NSWindowCollectionBehaviorManaged; [window->ns.object setCollectionBehavior:behavior]; } + else + { + const NSWindowCollectionBehavior behavior = + NSWindowCollectionBehaviorFullScreenNone; + [window->ns.object setCollectionBehavior:behavior]; + } if (wndconfig->floating) [window->ns.object setLevel:NSFloatingWindowLevel]; @@ -872,8 +890,8 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, [window->ns.object setTabbingMode:NSWindowTabbingModeDisallowed]; #endif - _glfwPlatformGetWindowSize(window, &window->ns.width, &window->ns.height); - _glfwPlatformGetFramebufferSize(window, &window->ns.fbWidth, &window->ns.fbHeight); + _glfwGetWindowSizeCocoa(window, &window->ns.width, &window->ns.height); + _glfwGetFramebufferSizeCocoa(window, &window->ns.fbWidth, &window->ns.fbHeight); return GLFW_TRUE; } @@ -885,7 +903,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, // Transforms a y-coordinate between the CG display and NS screen spaces // -float _glfwTransformYNS(float y) +float _glfwTransformYCocoa(float y) { return CGDisplayBounds(CGMainDisplayID()).size.height - y - 1; } @@ -895,10 +913,10 @@ float _glfwTransformYNS(float y) ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -int _glfwPlatformCreateWindow(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig) +GLFWbool _glfwCreateWindowCocoa(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig) { @autoreleasepool { @@ -933,13 +951,31 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig)) return GLFW_FALSE; } + + if (!_glfwRefreshContextAttribs(window, ctxconfig)) + return GLFW_FALSE; } + if (wndconfig->mousePassthrough) + _glfwSetWindowMousePassthroughCocoa(window, GLFW_TRUE); + if (window->monitor) { - _glfwPlatformShowWindow(window); - _glfwPlatformFocusWindow(window); + _glfwShowWindowCocoa(window); + _glfwFocusWindowCocoa(window); acquireMonitor(window); + + if (wndconfig->centerCursor) + _glfwCenterCursorInContentArea(window); + } + else + { + if (wndconfig->visible) + { + _glfwShowWindowCocoa(window); + if (wndconfig->focused) + _glfwFocusWindowCocoa(window); + } } return GLFW_TRUE; @@ -947,7 +983,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, } // autoreleasepool } -void _glfwPlatformDestroyWindow(_GLFWwindow* window) +void _glfwDestroyWindowCocoa(_GLFWwindow* window) { @autoreleasepool { @@ -973,12 +1009,12 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) window->ns.object = nil; // HACK: Allow Cocoa to catch up before returning - _glfwPlatformPollEvents(); + _glfwPollEventsCocoa(); } // autoreleasepool } -void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) +void _glfwSetWindowTitleCocoa(_GLFWwindow* window, const char* title) { @autoreleasepool { NSString* string = @(title); @@ -989,14 +1025,14 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) } // autoreleasepool } -void _glfwPlatformSetWindowIcon(_GLFWwindow* window, - int count, const GLFWimage* images) +void _glfwSetWindowIconCocoa(_GLFWwindow* window, + int count, const GLFWimage* images) { _glfwInputError(GLFW_FEATURE_UNAVAILABLE, "Cocoa: Regular windows do not have icons on macOS"); } -void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) +void _glfwGetWindowPosCocoa(_GLFWwindow* window, int* xpos, int* ypos) { @autoreleasepool { @@ -1006,24 +1042,24 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) if (xpos) *xpos = contentRect.origin.x; if (ypos) - *ypos = _glfwTransformYNS(contentRect.origin.y + contentRect.size.height - 1); + *ypos = _glfwTransformYCocoa(contentRect.origin.y + contentRect.size.height - 1); } // autoreleasepool } -void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y) +void _glfwSetWindowPosCocoa(_GLFWwindow* window, int x, int y) { @autoreleasepool { const NSRect contentRect = [window->ns.view frame]; - const NSRect dummyRect = NSMakeRect(x, _glfwTransformYNS(y + contentRect.size.height - 1), 0, 0); + const NSRect dummyRect = NSMakeRect(x, _glfwTransformYCocoa(y + contentRect.size.height - 1), 0, 0); const NSRect frameRect = [window->ns.object frameRectForContentRect:dummyRect]; [window->ns.object setFrameOrigin:frameRect.origin]; } // autoreleasepool } -void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) +void _glfwGetWindowSizeCocoa(_GLFWwindow* window, int* width, int* height) { @autoreleasepool { @@ -1037,7 +1073,7 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) } // autoreleasepool } -void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) +void _glfwSetWindowSizeCocoa(_GLFWwindow* window, int width, int height) { @autoreleasepool { @@ -1059,9 +1095,9 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) } // autoreleasepool } -void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, - int minwidth, int minheight, - int maxwidth, int maxheight) +void _glfwSetWindowSizeLimitsCocoa(_GLFWwindow* window, + int minwidth, int minheight, + int maxwidth, int maxheight) { @autoreleasepool { @@ -1078,7 +1114,7 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, } // autoreleasepool } -void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom) +void _glfwSetWindowAspectRatioCocoa(_GLFWwindow* window, int numer, int denom) { @autoreleasepool { if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE) @@ -1088,7 +1124,7 @@ void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom } // autoreleasepool } -void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) +void _glfwGetFramebufferSizeCocoa(_GLFWwindow* window, int* width, int* height) { @autoreleasepool { @@ -1103,9 +1139,9 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* heigh } // autoreleasepool } -void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, - int* left, int* top, - int* right, int* bottom) +void _glfwGetWindowFrameSizeCocoa(_GLFWwindow* window, + int* left, int* top, + int* right, int* bottom) { @autoreleasepool { @@ -1126,8 +1162,8 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, } // autoreleasepool } -void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, - float* xscale, float* yscale) +void _glfwGetWindowContentScaleCocoa(_GLFWwindow* window, + float* xscale, float* yscale) { @autoreleasepool { @@ -1142,14 +1178,14 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, } // autoreleasepool } -void _glfwPlatformIconifyWindow(_GLFWwindow* window) +void _glfwIconifyWindowCocoa(_GLFWwindow* window) { @autoreleasepool { [window->ns.object miniaturize:nil]; } // autoreleasepool } -void _glfwPlatformRestoreWindow(_GLFWwindow* window) +void _glfwRestoreWindowCocoa(_GLFWwindow* window) { @autoreleasepool { if ([window->ns.object isMiniaturized]) @@ -1159,7 +1195,7 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) } // autoreleasepool } -void _glfwPlatformMaximizeWindow(_GLFWwindow* window) +void _glfwMaximizeWindowCocoa(_GLFWwindow* window) { @autoreleasepool { if (![window->ns.object isZoomed]) @@ -1167,28 +1203,28 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window) } // autoreleasepool } -void _glfwPlatformShowWindow(_GLFWwindow* window) +void _glfwShowWindowCocoa(_GLFWwindow* window) { @autoreleasepool { [window->ns.object orderFront:nil]; } // autoreleasepool } -void _glfwPlatformHideWindow(_GLFWwindow* window) +void _glfwHideWindowCocoa(_GLFWwindow* window) { @autoreleasepool { [window->ns.object orderOut:nil]; } // autoreleasepool } -void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) +void _glfwRequestWindowAttentionCocoa(_GLFWwindow* window) { @autoreleasepool { [NSApp requestUserAttention:NSInformationalRequest]; } // autoreleasepool } -void _glfwPlatformFocusWindow(_GLFWwindow* window) +void _glfwFocusWindowCocoa(_GLFWwindow* window) { @autoreleasepool { // Make us the active application @@ -1200,11 +1236,11 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) } // autoreleasepool } -void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, - _GLFWmonitor* monitor, - int xpos, int ypos, - int width, int height, - int refreshRate) +void _glfwSetWindowMonitorCocoa(_GLFWwindow* window, + _GLFWmonitor* monitor, + int xpos, int ypos, + int width, int height, + int refreshRate) { @autoreleasepool { @@ -1218,10 +1254,11 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, else { const NSRect contentRect = - NSMakeRect(xpos, _glfwTransformYNS(ypos + height - 1), width, height); + NSMakeRect(xpos, _glfwTransformYCocoa(ypos + height - 1), width, height); + const NSUInteger styleMask = [window->ns.object styleMask]; const NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect - styleMask:getStyleMask(window)]; + styleMask:styleMask]; [window->ns.object setFrame:frameRect display:YES]; } @@ -1236,9 +1273,29 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, // HACK: Allow the state cached in Cocoa to catch up to reality // TODO: Solve this in a less terrible way - _glfwPlatformPollEvents(); + _glfwPollEventsCocoa(); + + NSUInteger styleMask = [window->ns.object styleMask]; + + if (window->monitor) + { + styleMask &= ~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable); + styleMask |= NSWindowStyleMaskBorderless; + } + else + { + if (window->decorated) + { + styleMask &= ~NSWindowStyleMaskBorderless; + styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable); + } + + if (window->resizable) + styleMask |= NSWindowStyleMaskResizable; + else + styleMask &= ~NSWindowStyleMaskResizable; + } - const NSUInteger styleMask = getStyleMask(window); [window->ns.object setStyleMask:styleMask]; // HACK: Changing the style mask can cause the first responder to be cleared [window->ns.object makeFirstResponder:window->ns.view]; @@ -1252,7 +1309,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, } else { - NSRect contentRect = NSMakeRect(xpos, _glfwTransformYNS(ypos + height - 1), + NSRect contentRect = NSMakeRect(xpos, _glfwTransformYCocoa(ypos + height - 1), width, height); NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect styleMask:styleMask]; @@ -1284,6 +1341,20 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, else [window->ns.object setLevel:NSNormalWindowLevel]; + if (window->resizable) + { + const NSWindowCollectionBehavior behavior = + NSWindowCollectionBehaviorFullScreenPrimary | + NSWindowCollectionBehaviorManaged; + [window->ns.object setCollectionBehavior:behavior]; + } + else + { + const NSWindowCollectionBehavior behavior = + NSWindowCollectionBehaviorFullScreenNone; + [window->ns.object setCollectionBehavior:behavior]; + } + [window->ns.object setHasShadow:YES]; // HACK: Clearing NSWindowStyleMaskTitled resets and disables the window // title property but the miniwindow title property is unaffected @@ -1293,35 +1364,40 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, } // autoreleasepool } -int _glfwPlatformWindowFocused(_GLFWwindow* window) +GLFWbool _glfwWindowFocusedCocoa(_GLFWwindow* window) { @autoreleasepool { return [window->ns.object isKeyWindow]; } // autoreleasepool } -int _glfwPlatformWindowIconified(_GLFWwindow* window) +GLFWbool _glfwWindowIconifiedCocoa(_GLFWwindow* window) { @autoreleasepool { return [window->ns.object isMiniaturized]; } // autoreleasepool } -int _glfwPlatformWindowVisible(_GLFWwindow* window) +GLFWbool _glfwWindowVisibleCocoa(_GLFWwindow* window) { @autoreleasepool { return [window->ns.object isVisible]; } // autoreleasepool } -int _glfwPlatformWindowMaximized(_GLFWwindow* window) +GLFWbool _glfwWindowMaximizedCocoa(_GLFWwindow* window) { @autoreleasepool { - return [window->ns.object isZoomed]; + + if (window->resizable) + return [window->ns.object isZoomed]; + else + return GLFW_FALSE; + } // autoreleasepool } -int _glfwPlatformWindowHovered(_GLFWwindow* window) +GLFWbool _glfwWindowHoveredCocoa(_GLFWwindow* window) { @autoreleasepool { @@ -1339,29 +1415,60 @@ int _glfwPlatformWindowHovered(_GLFWwindow* window) } // autoreleasepool } -int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) +GLFWbool _glfwFramebufferTransparentCocoa(_GLFWwindow* window) { @autoreleasepool { return ![window->ns.object isOpaque] && ![window->ns.view isOpaque]; } // autoreleasepool } -void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowResizableCocoa(_GLFWwindow* window, GLFWbool enabled) { @autoreleasepool { - [window->ns.object setStyleMask:getStyleMask(window)]; + + const NSUInteger styleMask = [window->ns.object styleMask]; + if (enabled) + { + [window->ns.object setStyleMask:(styleMask | NSWindowStyleMaskResizable)]; + const NSWindowCollectionBehavior behavior = + NSWindowCollectionBehaviorFullScreenPrimary | + NSWindowCollectionBehaviorManaged; + [window->ns.object setCollectionBehavior:behavior]; + } + else + { + [window->ns.object setStyleMask:(styleMask & ~NSWindowStyleMaskResizable)]; + const NSWindowCollectionBehavior behavior = + NSWindowCollectionBehaviorFullScreenNone; + [window->ns.object setCollectionBehavior:behavior]; + } + } // autoreleasepool } -void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowDecoratedCocoa(_GLFWwindow* window, GLFWbool enabled) { @autoreleasepool { - [window->ns.object setStyleMask:getStyleMask(window)]; + + NSUInteger styleMask = [window->ns.object styleMask]; + if (enabled) + { + styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable); + styleMask &= ~NSWindowStyleMaskBorderless; + } + else + { + styleMask |= NSWindowStyleMaskBorderless; + styleMask &= ~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable); + } + + [window->ns.object setStyleMask:styleMask]; [window->ns.object makeFirstResponder:window->ns.view]; + } // autoreleasepool } -void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowFloatingCocoa(_GLFWwindow* window, GLFWbool enabled) { @autoreleasepool { if (enabled) @@ -1371,39 +1478,39 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) } // autoreleasepool } -void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowMousePassthroughCocoa(_GLFWwindow* window, GLFWbool enabled) { @autoreleasepool { [window->ns.object setIgnoresMouseEvents:enabled]; } } -float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) +float _glfwGetWindowOpacityCocoa(_GLFWwindow* window) { @autoreleasepool { return (float) [window->ns.object alphaValue]; } // autoreleasepool } -void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) +void _glfwSetWindowOpacityCocoa(_GLFWwindow* window, float opacity) { @autoreleasepool { [window->ns.object setAlphaValue:opacity]; } // autoreleasepool } -void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled) +void _glfwSetRawMouseMotionCocoa(_GLFWwindow *window, GLFWbool enabled) { _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, "Cocoa: Raw mouse motion not yet implemented"); } -GLFWbool _glfwPlatformRawMouseMotionSupported(void) +GLFWbool _glfwRawMouseMotionSupportedCocoa(void) { return GLFW_FALSE; } -void _glfwPlatformPollEvents(void) +void _glfwPollEventsCocoa(void) { @autoreleasepool { @@ -1422,7 +1529,7 @@ void _glfwPlatformPollEvents(void) } // autoreleasepool } -void _glfwPlatformWaitEvents(void) +void _glfwWaitEventsCocoa(void) { @autoreleasepool { @@ -1435,12 +1542,12 @@ void _glfwPlatformWaitEvents(void) dequeue:YES]; [NSApp sendEvent:event]; - _glfwPlatformPollEvents(); + _glfwPollEventsCocoa(); } // autoreleasepool } -void _glfwPlatformWaitEventsTimeout(double timeout) +void _glfwWaitEventsTimeoutCocoa(double timeout) { @autoreleasepool { @@ -1452,12 +1559,12 @@ void _glfwPlatformWaitEventsTimeout(double timeout) if (event) [NSApp sendEvent:event]; - _glfwPlatformPollEvents(); + _glfwPollEventsCocoa(); } // autoreleasepool } -void _glfwPlatformPostEmptyEvent(void) +void _glfwPostEmptyEventCocoa(void) { @autoreleasepool { @@ -1475,7 +1582,7 @@ void _glfwPlatformPostEmptyEvent(void) } // autoreleasepool } -void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) +void _glfwGetCursorPosCocoa(_GLFWwindow* window, double* xpos, double* ypos) { @autoreleasepool { @@ -1491,7 +1598,7 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) } // autoreleasepool } -void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) +void _glfwSetCursorPosCocoa(_GLFWwindow* window, double x, double y) { @autoreleasepool { @@ -1516,7 +1623,7 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) const NSPoint globalPoint = globalRect.origin; CGWarpMouseCursorPosition(CGPointMake(globalPoint.x, - _glfwTransformYNS(globalPoint.y))); + _glfwTransformYCocoa(globalPoint.y))); } // HACK: Calling this right after setting the cursor position prevents macOS @@ -1527,15 +1634,23 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) } // autoreleasepool } -void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) +void _glfwSetCursorModeCocoa(_GLFWwindow* window, int mode) { @autoreleasepool { - if (_glfwPlatformWindowFocused(window)) + + if (mode == GLFW_CURSOR_CAPTURED) + { + _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, + "Cocoa: Captured cursor mode not yet implemented"); + } + + if (_glfwWindowFocusedCocoa(window)) updateCursorMode(window); + } // autoreleasepool } -const char* _glfwPlatformGetScancodeName(int scancode) +const char* _glfwGetScancodeNameCocoa(int scancode) { @autoreleasepool { @@ -1584,14 +1699,14 @@ const char* _glfwPlatformGetScancodeName(int scancode) } // autoreleasepool } -int _glfwPlatformGetKeyScancode(int key) +int _glfwGetKeyScancodeCocoa(int key) { return _glfw.ns.scancodes[key]; } -int _glfwPlatformCreateCursor(_GLFWcursor* cursor, - const GLFWimage* image, - int xhot, int yhot) +GLFWbool _glfwCreateCursorCocoa(_GLFWcursor* cursor, + const GLFWimage* image, + int xhot, int yhot) { @autoreleasepool { @@ -1633,7 +1748,7 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor, } // autoreleasepool } -int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) +GLFWbool _glfwCreateStandardCursorCocoa(_GLFWcursor* cursor, int shape) { @autoreleasepool { @@ -1707,7 +1822,7 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) } // autoreleasepool } -void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) +void _glfwDestroyCursorCocoa(_GLFWcursor* cursor) { @autoreleasepool { if (cursor->ns.object) @@ -1715,7 +1830,7 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) } // autoreleasepool } -void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) +void _glfwSetCursorCocoa(_GLFWwindow* window, _GLFWcursor* cursor) { @autoreleasepool { if (cursorInContentArea(window)) @@ -1723,7 +1838,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) } // autoreleasepool } -void _glfwPlatformSetClipboardString(const char* string) +void _glfwSetClipboardStringCocoa(const char* string) { @autoreleasepool { NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; @@ -1732,7 +1847,7 @@ void _glfwPlatformSetClipboardString(const char* string) } // autoreleasepool } -const char* _glfwPlatformGetClipboardString(void) +const char* _glfwGetClipboardStringCocoa(void) { @autoreleasepool { @@ -1761,7 +1876,7 @@ const char* _glfwPlatformGetClipboardString(void) } // autoreleasepool } -EGLenum _glfwPlatformGetEGLPlatform(EGLint** attribs) +EGLenum _glfwGetEGLPlatformCocoa(EGLint** attribs) { if (_glfw.egl.ANGLE_platform_angle) { @@ -1792,17 +1907,17 @@ EGLenum _glfwPlatformGetEGLPlatform(EGLint** attribs) return 0; } -EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void) +EGLNativeDisplayType _glfwGetEGLNativeDisplayCocoa(void) { return EGL_DEFAULT_DISPLAY; } -EGLNativeWindowType _glfwPlatformGetEGLNativeWindow(_GLFWwindow* window) +EGLNativeWindowType _glfwGetEGLNativeWindowCocoa(_GLFWwindow* window) { return window->ns.layer; } -void _glfwPlatformGetRequiredInstanceExtensions(char** extensions) +void _glfwGetRequiredInstanceExtensionsCocoa(char** extensions) { if (_glfw.vk.KHR_surface && _glfw.vk.EXT_metal_surface) { @@ -1816,17 +1931,17 @@ void _glfwPlatformGetRequiredInstanceExtensions(char** extensions) } } -int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, - VkPhysicalDevice device, - uint32_t queuefamily) +GLFWbool _glfwGetPhysicalDevicePresentationSupportCocoa(VkInstance instance, + VkPhysicalDevice device, + uint32_t queuefamily) { return GLFW_TRUE; } -VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, - _GLFWwindow* window, - const VkAllocationCallbacks* allocator, - VkSurfaceKHR* surface) +VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance, + _GLFWwindow* window, + const VkAllocationCallbacks* allocator, + VkSurfaceKHR* surface) { @autoreleasepool { @@ -1923,6 +2038,16 @@ GLFWAPI id glfwGetCocoaWindow(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(nil); + + if (_glfw.platform.platformID != GLFW_PLATFORM_COCOA) + { + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, + "Cocoa: Platform not initialized"); + return NULL; + } + return window->ns.object; } +#endif // _GLFW_COCOA + diff --git a/src/context.c b/src/context.c index f6629f55..33b399c9 100644 --- a/src/context.c +++ b/src/context.c @@ -48,16 +48,6 @@ // GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) { - if (ctxconfig->share) - { - if (ctxconfig->client == GLFW_NO_API || - ctxconfig->share->context.client == GLFW_NO_API) - { - _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); - return GLFW_FALSE; - } - } - if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API && ctxconfig->source != GLFW_EGL_CONTEXT_API && ctxconfig->source != GLFW_OSMESA_CONTEXT_API) @@ -78,6 +68,23 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) return GLFW_FALSE; } + if (ctxconfig->share) + { + if (ctxconfig->client == GLFW_NO_API || + ctxconfig->share->context.client == GLFW_NO_API) + { + _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); + return GLFW_FALSE; + } + + if (ctxconfig->source != ctxconfig->share->context.source) + { + _glfwInputError(GLFW_INVALID_ENUM, + "Context creation APIs do not match between contexts"); + return GLFW_FALSE; + } + } + if (ctxconfig->client == GLFW_OPENGL_API) { if ((ctxconfig->major < 1 || ctxconfig->minor < 0) || @@ -609,10 +616,12 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; - _GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.contextSlot); + _GLFWwindow* previous; _GLFW_REQUIRE_INIT(); + previous = _glfwPlatformGetTls(&_glfw.contextSlot); + if (window && window->context.client == GLFW_NO_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, diff --git a/src/egl_context.c b/src/egl_context.c index 264b233a..64dcdd6f 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -88,13 +88,30 @@ static int getEGLConfigAttrib(EGLConfig config, int attrib) // Return the EGLConfig most closely matching the specified hints // static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* desired, + const _GLFWfbconfig* fbconfig, EGLConfig* result) { EGLConfig* nativeConfigs; _GLFWfbconfig* usableConfigs; const _GLFWfbconfig* closest; - int i, nativeCount, usableCount; + int i, nativeCount, usableCount, apiBit; + GLFWbool wrongApiAvailable = GLFW_FALSE; + + if (ctxconfig->client == GLFW_OPENGL_ES_API) + { + if (ctxconfig->major == 1) + apiBit = EGL_OPENGL_ES_BIT; + else + apiBit = EGL_OPENGL_ES2_BIT; + } + else + apiBit = EGL_OPENGL_BIT; + + if (fbconfig->stereo) + { + _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "EGL: Stereo rendering not supported"); + return GLFW_FALSE; + } eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount); if (!nativeCount) @@ -123,6 +140,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, continue; #if defined(_GLFW_X11) + if (_glfw.platform.platformID == GLFW_PLATFORM_X11) { XVisualInfo vi = {0}; @@ -131,7 +149,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, if (!vi.visualid) continue; - if (desired->transparent) + if (fbconfig->transparent) { int count; XVisualInfo* vis = @@ -145,23 +163,10 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, } #endif // _GLFW_X11 - if (ctxconfig->client == GLFW_OPENGL_ES_API) + if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & apiBit)) { - if (ctxconfig->major == 1) - { - if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT)) - continue; - } - else - { - if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT)) - continue; - } - } - else if (ctxconfig->client == GLFW_OPENGL_API) - { - if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT)) - continue; + wrongApiAvailable = GLFW_TRUE; + continue; } u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE); @@ -172,16 +177,60 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE); u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE); +#if defined(_GLFW_WAYLAND) + if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND) + { + // NOTE: The wl_surface opaque region is no guarantee that its buffer + // is presented as opaque, if it also has an alpha channel + // HACK: If EGL_EXT_present_opaque is unavailable, ignore any config + // with an alpha channel to ensure the buffer is opaque + if (!_glfw.egl.EXT_present_opaque) + { + if (!fbconfig->transparent && u->alphaBits > 0) + continue; + } + } +#endif // _GLFW_WAYLAND + u->samples = getEGLConfigAttrib(n, EGL_SAMPLES); - u->doublebuffer = desired->doublebuffer; + u->doublebuffer = fbconfig->doublebuffer; u->handle = (uintptr_t) n; usableCount++; } - closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); + closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount); if (closest) *result = (EGLConfig) closest->handle; + else + { + if (wrongApiAvailable) + { + if (ctxconfig->client == GLFW_OPENGL_ES_API) + { + if (ctxconfig->major == 1) + { + _glfwInputError(GLFW_API_UNAVAILABLE, + "EGL: Failed to find support for OpenGL ES 1.x"); + } + else + { + _glfwInputError(GLFW_API_UNAVAILABLE, + "EGL: Failed to find support for OpenGL ES 2 or later"); + } + } + else + { + _glfwInputError(GLFW_API_UNAVAILABLE, + "EGL: Failed to find support for OpenGL"); + } + } + else + { + _glfwInputError(GLFW_FORMAT_UNAVAILABLE, + "EGL: Failed to find a suitable EGLConfig"); + } + } _glfw_free(nativeConfigs); _glfw_free(usableConfigs); @@ -230,6 +279,15 @@ static void swapBuffersEGL(_GLFWwindow* window) return; } +#if defined(_GLFW_WAYLAND) + if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND) + { + // NOTE: Swapping buffers on a hidden window on Wayland makes it visible + if (!window->wl.visible) + return; + } +#endif + eglSwapBuffers(_glfw.egl.display, window->context.egl.surface); } @@ -256,8 +314,8 @@ static GLFWglproc getProcAddressEGL(const char* procname) if (window->context.egl.client) { - GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->context.egl.client, - procname); + GLFWglproc proc = (GLFWglproc) + _glfwPlatformGetModuleSymbol(window->context.egl.client, procname); if (proc) return proc; } @@ -267,15 +325,14 @@ static GLFWglproc getProcAddressEGL(const char* procname) static void destroyContextEGL(_GLFWwindow* window) { -#if defined(_GLFW_X11) // NOTE: Do not unload libGL.so.1 while the X11 display is still open, // as it will make XCloseDisplay segfault - if (window->context.client != GLFW_OPENGL_API) -#endif // _GLFW_X11 + if (_glfw.platform.platformID != GLFW_PLATFORM_X11 || + window->context.client != GLFW_OPENGL_API) { if (window->context.egl.client) { - _glfw_dlclose(window->context.egl.client); + _glfwPlatformFreeModule(window->context.egl.client); window->context.egl.client = NULL; } } @@ -316,6 +373,8 @@ GLFWbool _glfwInitEGL(void) "libEGL.dylib", #elif defined(__CYGWIN__) "libEGL-1.so", +#elif defined(__OpenBSD__) || defined(__NetBSD__) + "libEGL.so", #else "libEGL.so.1", #endif @@ -327,7 +386,7 @@ GLFWbool _glfwInitEGL(void) for (i = 0; sonames[i]; i++) { - _glfw.egl.handle = _glfw_dlopen(sonames[i]); + _glfw.egl.handle = _glfwPlatformLoadModule(sonames[i]); if (_glfw.egl.handle) break; } @@ -341,37 +400,37 @@ GLFWbool _glfwInitEGL(void) _glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0); _glfw.egl.GetConfigAttrib = (PFN_eglGetConfigAttrib) - _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib"); + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglGetConfigAttrib"); _glfw.egl.GetConfigs = (PFN_eglGetConfigs) - _glfw_dlsym(_glfw.egl.handle, "eglGetConfigs"); + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglGetConfigs"); _glfw.egl.GetDisplay = (PFN_eglGetDisplay) - _glfw_dlsym(_glfw.egl.handle, "eglGetDisplay"); + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglGetDisplay"); _glfw.egl.GetError = (PFN_eglGetError) - _glfw_dlsym(_glfw.egl.handle, "eglGetError"); + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglGetError"); _glfw.egl.Initialize = (PFN_eglInitialize) - _glfw_dlsym(_glfw.egl.handle, "eglInitialize"); + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglInitialize"); _glfw.egl.Terminate = (PFN_eglTerminate) - _glfw_dlsym(_glfw.egl.handle, "eglTerminate"); + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglTerminate"); _glfw.egl.BindAPI = (PFN_eglBindAPI) - _glfw_dlsym(_glfw.egl.handle, "eglBindAPI"); + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglBindAPI"); _glfw.egl.CreateContext = (PFN_eglCreateContext) - _glfw_dlsym(_glfw.egl.handle, "eglCreateContext"); + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglCreateContext"); _glfw.egl.DestroySurface = (PFN_eglDestroySurface) - _glfw_dlsym(_glfw.egl.handle, "eglDestroySurface"); + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglDestroySurface"); _glfw.egl.DestroyContext = (PFN_eglDestroyContext) - _glfw_dlsym(_glfw.egl.handle, "eglDestroyContext"); + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglDestroyContext"); _glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface) - _glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface"); + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglCreateWindowSurface"); _glfw.egl.MakeCurrent = (PFN_eglMakeCurrent) - _glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent"); + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglMakeCurrent"); _glfw.egl.SwapBuffers = (PFN_eglSwapBuffers) - _glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers"); + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglSwapBuffers"); _glfw.egl.SwapInterval = (PFN_eglSwapInterval) - _glfw_dlsym(_glfw.egl.handle, "eglSwapInterval"); + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglSwapInterval"); _glfw.egl.QueryString = (PFN_eglQueryString) - _glfw_dlsym(_glfw.egl.handle, "eglQueryString"); + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglQueryString"); _glfw.egl.GetProcAddress = (PFN_eglGetProcAddress) - _glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress"); + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglGetProcAddress"); if (!_glfw.egl.GetConfigAttrib || !_glfw.egl.GetConfigs || @@ -429,16 +488,16 @@ GLFWbool _glfwInitEGL(void) eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"); } - _glfw.egl.platform = _glfwPlatformGetEGLPlatform(&attribs); + _glfw.egl.platform = _glfw.platform.getEGLPlatform(&attribs); if (_glfw.egl.platform) { _glfw.egl.display = eglGetPlatformDisplayEXT(_glfw.egl.platform, - _glfwPlatformGetEGLNativeDisplay(), + _glfw.platform.getEGLNativeDisplay(), attribs); } else - _glfw.egl.display = eglGetDisplay(_glfwPlatformGetEGLNativeDisplay()); + _glfw.egl.display = eglGetDisplay(_glfw.platform.getEGLNativeDisplay()); _glfw_free(attribs); @@ -472,6 +531,8 @@ GLFWbool _glfwInitEGL(void) extensionSupportedEGL("EGL_KHR_get_all_proc_addresses"); _glfw.egl.KHR_context_flush_control = extensionSupportedEGL("EGL_KHR_context_flush_control"); + _glfw.egl.EXT_present_opaque = + extensionSupportedEGL("EGL_EXT_present_opaque"); return GLFW_TRUE; } @@ -488,12 +549,12 @@ void _glfwTerminateEGL(void) if (_glfw.egl.handle) { - _glfw_dlclose(_glfw.egl.handle); + _glfwPlatformFreeModule(_glfw.egl.handle); _glfw.egl.handle = NULL; } } -#define setAttrib(a, v) \ +#define SET_ATTRIB(a, v) \ { \ assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ attribs[index++] = a; \ @@ -522,11 +583,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, share = ctxconfig->share->context.egl.handle; if (!chooseEGLConfig(ctxconfig, fbconfig, &config)) - { - _glfwInputError(GLFW_FORMAT_UNAVAILABLE, - "EGL: Failed to find a suitable EGLConfig"); return GLFW_FALSE; - } if (ctxconfig->client == GLFW_OPENGL_ES_API) { @@ -571,13 +628,13 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, { if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION) { - setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, - EGL_NO_RESET_NOTIFICATION_KHR); + SET_ATTRIB(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, + EGL_NO_RESET_NOTIFICATION_KHR); } else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET) { - setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, - EGL_LOSE_CONTEXT_ON_RESET_KHR); + SET_ATTRIB(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, + EGL_LOSE_CONTEXT_ON_RESET_KHR); } flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; @@ -586,42 +643,42 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, if (ctxconfig->noerror) { if (_glfw.egl.KHR_create_context_no_error) - setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE); + SET_ATTRIB(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE); } if (ctxconfig->major != 1 || ctxconfig->minor != 0) { - setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major); - setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor); + SET_ATTRIB(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major); + SET_ATTRIB(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor); } if (mask) - setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask); + SET_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask); if (flags) - setAttrib(EGL_CONTEXT_FLAGS_KHR, flags); + SET_ATTRIB(EGL_CONTEXT_FLAGS_KHR, flags); } else { if (ctxconfig->client == GLFW_OPENGL_ES_API) - setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major); + SET_ATTRIB(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major); } if (_glfw.egl.KHR_context_flush_control) { if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE) { - setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, - EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR); + SET_ATTRIB(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, + EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR); } else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH) { - setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, - EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR); + SET_ATTRIB(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, + EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR); } } - setAttrib(EGL_NONE, EGL_NONE); + SET_ATTRIB(EGL_NONE, EGL_NONE); window->context.egl.handle = eglCreateContext(_glfw.egl.display, config, share, attribs); @@ -640,15 +697,18 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, if (fbconfig->sRGB) { if (_glfw.egl.KHR_gl_colorspace) - setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR); + SET_ATTRIB(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR); } if (!fbconfig->doublebuffer) - setAttrib(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER); + SET_ATTRIB(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER); - setAttrib(EGL_NONE, EGL_NONE); + if (_glfw.egl.EXT_present_opaque) + SET_ATTRIB(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent); - native = _glfwPlatformGetEGLNativeWindow(window); + SET_ATTRIB(EGL_NONE, EGL_NONE); + + native = _glfw.platform.getEGLNativeWindow(window); // HACK: ANGLE does not implement eglCreatePlatformWindowSurfaceEXT // despite reporting EGL_EXT_platform_base if (_glfw.egl.platform && _glfw.egl.platform != EGL_PLATFORM_ANGLE_ANGLE) @@ -686,6 +746,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, "libGLES_CM.dll", #elif defined(_GLFW_COCOA) "libGLESv1_CM.dylib", +#elif defined(__OpenBSD__) || defined(__NetBSD__) + "libGLESv1_CM.so", #else "libGLESv1_CM.so.1", "libGLES_CM.so.1", @@ -703,6 +765,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, "libGLESv2.dylib", #elif defined(__CYGWIN__) "libGLESv2-2.so", +#elif defined(__OpenBSD__) || defined(__NetBSD__) + "libGLESv2.so", #else "libGLESv2.so.2", #endif @@ -714,7 +778,10 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, _GLFW_OPENGL_LIBRARY, #elif defined(_GLFW_WIN32) #elif defined(_GLFW_COCOA) +#elif defined(__OpenBSD__) || defined(__NetBSD__) + "libGL.so", #else + "libOpenGL.so.0", "libGL.so.1", #endif NULL @@ -737,7 +804,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, if (_glfw.egl.prefix != (strncmp(sonames[i], "lib", 3) == 0)) continue; - window->context.egl.client = _glfw_dlopen(sonames[i]); + window->context.egl.client = _glfwPlatformLoadModule(sonames[i]); if (window->context.egl.client) break; } @@ -760,7 +827,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, return GLFW_TRUE; } -#undef setAttrib +#undef SET_ATTRIB // Returns the Visual and depth of the chosen EGLConfig // @@ -777,11 +844,7 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig, const long vimask = VisualScreenMask | VisualIDMask; if (!chooseEGLConfig(ctxconfig, fbconfig, &native)) - { - _glfwInputError(GLFW_FORMAT_UNAVAILABLE, - "EGL: Failed to find a suitable EGLConfig"); return GLFW_FALSE; - } eglGetConfigAttrib(_glfw.egl.display, native, EGL_NATIVE_VISUAL_ID, &visualID); @@ -821,7 +884,7 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle) _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT); - if (window->context.client == GLFW_NO_API) + if (window->context.source != GLFW_EGL_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return EGL_NO_CONTEXT; @@ -835,7 +898,7 @@ GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle) _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE); - if (window->context.client == GLFW_NO_API) + if (window->context.source != GLFW_EGL_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return EGL_NO_SURFACE; diff --git a/src/egl_context.h b/src/egl_context.h deleted file mode 100644 index 4c84072e..00000000 --- a/src/egl_context.h +++ /dev/null @@ -1,229 +0,0 @@ -//======================================================================== -// GLFW 3.4 EGL - www.glfw.org -//------------------------------------------------------------------------ -// Copyright (c) 2002-2006 Marcus Geelnard -// Copyright (c) 2006-2017 Camilla Löwy -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would -// be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -// -//======================================================================== - -#if defined(_GLFW_WIN32) - #define EGLAPIENTRY __stdcall -#else - #define EGLAPIENTRY -#endif - -#define EGL_SUCCESS 0x3000 -#define EGL_NOT_INITIALIZED 0x3001 -#define EGL_BAD_ACCESS 0x3002 -#define EGL_BAD_ALLOC 0x3003 -#define EGL_BAD_ATTRIBUTE 0x3004 -#define EGL_BAD_CONFIG 0x3005 -#define EGL_BAD_CONTEXT 0x3006 -#define EGL_BAD_CURRENT_SURFACE 0x3007 -#define EGL_BAD_DISPLAY 0x3008 -#define EGL_BAD_MATCH 0x3009 -#define EGL_BAD_NATIVE_PIXMAP 0x300a -#define EGL_BAD_NATIVE_WINDOW 0x300b -#define EGL_BAD_PARAMETER 0x300c -#define EGL_BAD_SURFACE 0x300d -#define EGL_CONTEXT_LOST 0x300e -#define EGL_COLOR_BUFFER_TYPE 0x303f -#define EGL_RGB_BUFFER 0x308e -#define EGL_SURFACE_TYPE 0x3033 -#define EGL_WINDOW_BIT 0x0004 -#define EGL_RENDERABLE_TYPE 0x3040 -#define EGL_OPENGL_ES_BIT 0x0001 -#define EGL_OPENGL_ES2_BIT 0x0004 -#define EGL_OPENGL_BIT 0x0008 -#define EGL_ALPHA_SIZE 0x3021 -#define EGL_BLUE_SIZE 0x3022 -#define EGL_GREEN_SIZE 0x3023 -#define EGL_RED_SIZE 0x3024 -#define EGL_DEPTH_SIZE 0x3025 -#define EGL_STENCIL_SIZE 0x3026 -#define EGL_SAMPLES 0x3031 -#define EGL_OPENGL_ES_API 0x30a0 -#define EGL_OPENGL_API 0x30a2 -#define EGL_NONE 0x3038 -#define EGL_RENDER_BUFFER 0x3086 -#define EGL_SINGLE_BUFFER 0x3085 -#define EGL_EXTENSIONS 0x3055 -#define EGL_CONTEXT_CLIENT_VERSION 0x3098 -#define EGL_NATIVE_VISUAL_ID 0x302e -#define EGL_NO_SURFACE ((EGLSurface) 0) -#define EGL_NO_DISPLAY ((EGLDisplay) 0) -#define EGL_NO_CONTEXT ((EGLContext) 0) -#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType) 0) - -#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 -#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 -#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002 -#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001 -#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31bd -#define EGL_NO_RESET_NOTIFICATION_KHR 0x31be -#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31bf -#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004 -#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098 -#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30fb -#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30fd -#define EGL_CONTEXT_FLAGS_KHR 0x30fc -#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3 -#define EGL_GL_COLORSPACE_KHR 0x309d -#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089 -#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097 -#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0 -#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098 -#define EGL_PLATFORM_X11_EXT 0x31d5 -#define EGL_PLATFORM_WAYLAND_EXT 0x31d8 -#define EGL_PLATFORM_ANGLE_ANGLE 0x3202 -#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203 -#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320d -#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320e -#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207 -#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208 -#define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450 -#define EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE 0x3489 -#define EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE 0x348f - -typedef int EGLint; -typedef unsigned int EGLBoolean; -typedef unsigned int EGLenum; -typedef void* EGLConfig; -typedef void* EGLContext; -typedef void* EGLDisplay; -typedef void* EGLSurface; - -typedef void* EGLNativeDisplayType; -typedef void* EGLNativeWindowType; - -// EGL function pointer typedefs -typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*); -typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigs)(EGLDisplay,EGLConfig*,EGLint,EGLint*); -typedef EGLDisplay (EGLAPIENTRY * PFN_eglGetDisplay)(EGLNativeDisplayType); -typedef EGLint (EGLAPIENTRY * PFN_eglGetError)(void); -typedef EGLBoolean (EGLAPIENTRY * PFN_eglInitialize)(EGLDisplay,EGLint*,EGLint*); -typedef EGLBoolean (EGLAPIENTRY * PFN_eglTerminate)(EGLDisplay); -typedef EGLBoolean (EGLAPIENTRY * PFN_eglBindAPI)(EGLenum); -typedef EGLContext (EGLAPIENTRY * PFN_eglCreateContext)(EGLDisplay,EGLConfig,EGLContext,const EGLint*); -typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroySurface)(EGLDisplay,EGLSurface); -typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext); -typedef EGLSurface (EGLAPIENTRY * PFN_eglCreateWindowSurface)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*); -typedef EGLBoolean (EGLAPIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLSurface,EGLContext); -typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface); -typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint); -typedef const char* (EGLAPIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint); -typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*); -#define eglGetConfigAttrib _glfw.egl.GetConfigAttrib -#define eglGetConfigs _glfw.egl.GetConfigs -#define eglGetDisplay _glfw.egl.GetDisplay -#define eglGetError _glfw.egl.GetError -#define eglInitialize _glfw.egl.Initialize -#define eglTerminate _glfw.egl.Terminate -#define eglBindAPI _glfw.egl.BindAPI -#define eglCreateContext _glfw.egl.CreateContext -#define eglDestroySurface _glfw.egl.DestroySurface -#define eglDestroyContext _glfw.egl.DestroyContext -#define eglCreateWindowSurface _glfw.egl.CreateWindowSurface -#define eglMakeCurrent _glfw.egl.MakeCurrent -#define eglSwapBuffers _glfw.egl.SwapBuffers -#define eglSwapInterval _glfw.egl.SwapInterval -#define eglQueryString _glfw.egl.QueryString -#define eglGetProcAddress _glfw.egl.GetProcAddress - -typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum,void*,const EGLint*); -typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)(EGLDisplay,EGLConfig,void*,const EGLint*); -#define eglGetPlatformDisplayEXT _glfw.egl.GetPlatformDisplayEXT -#define eglCreatePlatformWindowSurfaceEXT _glfw.egl.CreatePlatformWindowSurfaceEXT - -// EGL-specific per-context data -// -typedef struct _GLFWcontextEGL -{ - EGLConfig config; - EGLContext handle; - EGLSurface surface; - - void* client; - -} _GLFWcontextEGL; - -// EGL-specific global data -// -typedef struct _GLFWlibraryEGL -{ - EGLenum platform; - EGLDisplay display; - EGLint major, minor; - GLFWbool prefix; - - GLFWbool KHR_create_context; - GLFWbool KHR_create_context_no_error; - GLFWbool KHR_gl_colorspace; - GLFWbool KHR_get_all_proc_addresses; - GLFWbool KHR_context_flush_control; - GLFWbool EXT_client_extensions; - GLFWbool EXT_platform_base; - GLFWbool EXT_platform_x11; - GLFWbool EXT_platform_wayland; - GLFWbool ANGLE_platform_angle; - GLFWbool ANGLE_platform_angle_opengl; - GLFWbool ANGLE_platform_angle_d3d; - GLFWbool ANGLE_platform_angle_vulkan; - GLFWbool ANGLE_platform_angle_metal; - - void* handle; - - PFN_eglGetConfigAttrib GetConfigAttrib; - PFN_eglGetConfigs GetConfigs; - PFN_eglGetDisplay GetDisplay; - PFN_eglGetError GetError; - PFN_eglInitialize Initialize; - PFN_eglTerminate Terminate; - PFN_eglBindAPI BindAPI; - PFN_eglCreateContext CreateContext; - PFN_eglDestroySurface DestroySurface; - PFN_eglDestroyContext DestroyContext; - PFN_eglCreateWindowSurface CreateWindowSurface; - PFN_eglMakeCurrent MakeCurrent; - PFN_eglSwapBuffers SwapBuffers; - PFN_eglSwapInterval SwapInterval; - PFN_eglQueryString QueryString; - PFN_eglGetProcAddress GetProcAddress; - - PFNEGLGETPLATFORMDISPLAYEXTPROC GetPlatformDisplayEXT; - PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC CreatePlatformWindowSurfaceEXT; - -} _GLFWlibraryEGL; - - -GLFWbool _glfwInitEGL(void); -void _glfwTerminateEGL(void); -GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig); -#if defined(_GLFW_X11) -GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig, - Visual** visual, int* depth); -#endif /*_GLFW_X11*/ - diff --git a/src/glfw_config.h.in b/src/glfw_config.h.in deleted file mode 100644 index f4876da2..00000000 --- a/src/glfw_config.h.in +++ /dev/null @@ -1,58 +0,0 @@ -//======================================================================== -// GLFW 3.4 - www.glfw.org -//------------------------------------------------------------------------ -// Copyright (c) 2010-2016 Camilla Löwy -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would -// be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -// -//======================================================================== -// As glfw_config.h.in, this file is used by CMake to produce the -// glfw_config.h configuration header file. If you are adding a feature -// requiring conditional compilation, this is where to add the macro. -//======================================================================== -// As glfw_config.h, this file defines compile-time option macros for a -// specific platform and development environment. If you are using the -// GLFW CMake files, modify glfw_config.h.in instead of this file. If you -// are using your own build system, make this file define the appropriate -// macros in whatever way is suitable. -//======================================================================== - -// Define this to 1 if building GLFW for X11 -#cmakedefine _GLFW_X11 -// Define this to 1 if building GLFW for Win32 -#cmakedefine _GLFW_WIN32 -// Define this to 1 if building GLFW for Cocoa -#cmakedefine _GLFW_COCOA -// Define this to 1 if building GLFW for Wayland -#cmakedefine _GLFW_WAYLAND -// Define this to 1 if building GLFW for OSMesa -#cmakedefine _GLFW_OSMESA - -// Define this to 1 to use Vulkan loader linked statically into application -#cmakedefine _GLFW_VULKAN_STATIC - -// Define this to 1 to force use of high-performance GPU on hybrid systems -#cmakedefine _GLFW_USE_HYBRID_HPG - -// Define this to 1 if xkbcommon supports the compose key -#cmakedefine HAVE_XKBCOMMON_COMPOSE_H -// Define this to 1 if the libc supports memfd_create() -#cmakedefine HAVE_MEMFD_CREATE - diff --git a/src/glx_context.c b/src/glx_context.c index 7207cd55..4406dfd3 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -29,6 +29,8 @@ #include "internal.h" +#if defined(_GLFW_X11) + #include #include #include @@ -55,7 +57,7 @@ static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* nativeConfigs; _GLFWfbconfig* usableConfigs; const _GLFWfbconfig* closest; - int i, nativeCount, usableCount; + int nativeCount, usableCount; const char* vendor; GLFWbool trustWindowBit = GLFW_TRUE; @@ -76,7 +78,7 @@ static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired, usableConfigs = _glfw_calloc(nativeCount, sizeof(_GLFWfbconfig)); usableCount = 0; - for (i = 0; i < nativeCount; i++) + for (int i = 0; i < nativeCount; i++) { const GLXFBConfig n = nativeConfigs[i]; _GLFWfbconfig* u = usableConfigs + usableCount; @@ -226,7 +228,10 @@ static GLFWglproc getProcAddressGLX(const char* procname) else if (_glfw.glx.GetProcAddressARB) return _glfw.glx.GetProcAddressARB((const GLubyte*) procname); else - return _glfw_dlsym(_glfw.glx.handle, procname); + { + // NOTE: glvnd provides GLX 1.4, so this can only happen with libGL + return _glfwPlatformGetModuleSymbol(_glfw.glx.handle, procname); + } } static void destroyContextGLX(_GLFWwindow* window) @@ -253,14 +258,16 @@ static void destroyContextGLX(_GLFWwindow* window) // GLFWbool _glfwInitGLX(void) { - int i; const char* sonames[] = { #if defined(_GLFW_GLX_LIBRARY) _GLFW_GLX_LIBRARY, #elif defined(__CYGWIN__) "libGL-1.so", +#elif defined(__OpenBSD__) || defined(__NetBSD__) + "libGL.so", #else + "libGLX.so.0", "libGL.so.1", "libGL.so", #endif @@ -270,9 +277,9 @@ GLFWbool _glfwInitGLX(void) if (_glfw.glx.handle) return GLFW_TRUE; - for (i = 0; sonames[i]; i++) + for (int i = 0; sonames[i]; i++) { - _glfw.glx.handle = _glfw_dlopen(sonames[i]); + _glfw.glx.handle = _glfwPlatformLoadModule(sonames[i]); if (_glfw.glx.handle) break; } @@ -283,36 +290,32 @@ GLFWbool _glfwInitGLX(void) return GLFW_FALSE; } - _glfw.glx.GetFBConfigs = - _glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigs"); - _glfw.glx.GetFBConfigAttrib = - _glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib"); - _glfw.glx.GetClientString = - _glfw_dlsym(_glfw.glx.handle, "glXGetClientString"); - _glfw.glx.QueryExtension = - _glfw_dlsym(_glfw.glx.handle, "glXQueryExtension"); - _glfw.glx.QueryVersion = - _glfw_dlsym(_glfw.glx.handle, "glXQueryVersion"); - _glfw.glx.DestroyContext = - _glfw_dlsym(_glfw.glx.handle, "glXDestroyContext"); - _glfw.glx.MakeCurrent = - _glfw_dlsym(_glfw.glx.handle, "glXMakeCurrent"); - _glfw.glx.SwapBuffers = - _glfw_dlsym(_glfw.glx.handle, "glXSwapBuffers"); - _glfw.glx.QueryExtensionsString = - _glfw_dlsym(_glfw.glx.handle, "glXQueryExtensionsString"); - _glfw.glx.CreateNewContext = - _glfw_dlsym(_glfw.glx.handle, "glXCreateNewContext"); - _glfw.glx.CreateWindow = - _glfw_dlsym(_glfw.glx.handle, "glXCreateWindow"); - _glfw.glx.DestroyWindow = - _glfw_dlsym(_glfw.glx.handle, "glXDestroyWindow"); - _glfw.glx.GetProcAddress = - _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress"); - _glfw.glx.GetProcAddressARB = - _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB"); - _glfw.glx.GetVisualFromFBConfig = - _glfw_dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig"); + _glfw.glx.GetFBConfigs = (PFNGLXGETFBCONFIGSPROC) + _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetFBConfigs"); + _glfw.glx.GetFBConfigAttrib = (PFNGLXGETFBCONFIGATTRIBPROC) + _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetFBConfigAttrib"); + _glfw.glx.GetClientString = (PFNGLXGETCLIENTSTRINGPROC) + _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetClientString"); + _glfw.glx.QueryExtension = (PFNGLXQUERYEXTENSIONPROC) + _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXQueryExtension"); + _glfw.glx.QueryVersion = (PFNGLXQUERYVERSIONPROC) + _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXQueryVersion"); + _glfw.glx.DestroyContext = (PFNGLXDESTROYCONTEXTPROC) + _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXDestroyContext"); + _glfw.glx.MakeCurrent = (PFNGLXMAKECURRENTPROC) + _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXMakeCurrent"); + _glfw.glx.SwapBuffers = (PFNGLXSWAPBUFFERSPROC) + _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXSwapBuffers"); + _glfw.glx.QueryExtensionsString = (PFNGLXQUERYEXTENSIONSSTRINGPROC) + _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXQueryExtensionsString"); + _glfw.glx.CreateNewContext = (PFNGLXCREATENEWCONTEXTPROC) + _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXCreateNewContext"); + _glfw.glx.CreateWindow = (PFNGLXCREATEWINDOWPROC) + _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXCreateWindow"); + _glfw.glx.DestroyWindow = (PFNGLXDESTROYWINDOWPROC) + _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXDestroyWindow"); + _glfw.glx.GetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC) + _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetVisualFromFBConfig"); if (!_glfw.glx.GetFBConfigs || !_glfw.glx.GetFBConfigAttrib || @@ -326,8 +329,6 @@ GLFWbool _glfwInitGLX(void) !_glfw.glx.CreateNewContext || !_glfw.glx.CreateWindow || !_glfw.glx.DestroyWindow || - !_glfw.glx.GetProcAddress || - !_glfw.glx.GetProcAddressARB || !_glfw.glx.GetVisualFromFBConfig) { _glfwInputError(GLFW_PLATFORM_ERROR, @@ -335,6 +336,12 @@ GLFWbool _glfwInitGLX(void) return GLFW_FALSE; } + // NOTE: Unlike GLX 1.3 entry points these are not required to be present + _glfw.glx.GetProcAddress = (PFNGLXGETPROCADDRESSPROC) + _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetProcAddress"); + _glfw.glx.GetProcAddressARB = (PFNGLXGETPROCADDRESSPROC) + _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetProcAddressARB"); + if (!glXQueryExtension(_glfw.x11.display, &_glfw.glx.errorBase, &_glfw.glx.eventBase)) @@ -425,16 +432,16 @@ GLFWbool _glfwInitGLX(void) void _glfwTerminateGLX(void) { // NOTE: This function must not call any X11 functions, as it is called - // after XCloseDisplay (see _glfwPlatformTerminate for details) + // after XCloseDisplay (see _glfwTerminateX11 for details) if (_glfw.glx.handle) { - _glfw_dlclose(_glfw.glx.handle); + _glfwPlatformFreeModule(_glfw.glx.handle); _glfw.glx.handle = NULL; } } -#define setAttrib(a, v) \ +#define SET_ATTRIB(a, v) \ { \ assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ attribs[index++] = a; \ @@ -522,13 +529,13 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window, { if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION) { - setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, - GLX_NO_RESET_NOTIFICATION_ARB); + SET_ATTRIB(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, + GLX_NO_RESET_NOTIFICATION_ARB); } else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET) { - setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, - GLX_LOSE_CONTEXT_ON_RESET_ARB); + SET_ATTRIB(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, + GLX_LOSE_CONTEXT_ON_RESET_ARB); } flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; @@ -541,13 +548,13 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window, { if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE) { - setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB, - GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB); + SET_ATTRIB(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB, + GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB); } else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH) { - setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB, - GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB); + SET_ATTRIB(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB, + GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB); } } } @@ -555,7 +562,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window, if (ctxconfig->noerror) { if (_glfw.glx.ARB_create_context_no_error) - setAttrib(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE); + SET_ATTRIB(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE); } // NOTE: Only request an explicitly versioned context when necessary, as @@ -563,17 +570,17 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window, // highest version supported by the driver if (ctxconfig->major != 1 || ctxconfig->minor != 0) { - setAttrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major); - setAttrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor); + SET_ATTRIB(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major); + SET_ATTRIB(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor); } if (mask) - setAttrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask); + SET_ATTRIB(GLX_CONTEXT_PROFILE_MASK_ARB, mask); if (flags) - setAttrib(GLX_CONTEXT_FLAGS_ARB, flags); + SET_ATTRIB(GLX_CONTEXT_FLAGS_ARB, flags); - setAttrib(None, None); + SET_ATTRIB(None, None); window->context.glx.handle = _glfw.glx.CreateContextAttribsARB(_glfw.x11.display, @@ -630,7 +637,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window, return GLFW_TRUE; } -#undef setAttrib +#undef SET_ATTRIB // Returns the Visual and depth of the chosen GLXFBConfig // @@ -674,7 +681,13 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle) _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - if (window->context.client == GLFW_NO_API) + if (_glfw.platform.platformID != GLFW_PLATFORM_X11) + { + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "GLX: Platform not initialized"); + return NULL; + } + + if (window->context.source != GLFW_NATIVE_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return NULL; @@ -688,7 +701,13 @@ GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle) _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(None); - if (window->context.client == GLFW_NO_API) + if (_glfw.platform.platformID != GLFW_PLATFORM_X11) + { + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "GLX: Platform not initialized"); + return None; + } + + if (window->context.source != GLFW_NATIVE_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return None; @@ -697,3 +716,5 @@ GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle) return window->context.glx.window; } +#endif // _GLFW_X11 + diff --git a/src/glx_context.h b/src/glx_context.h deleted file mode 100644 index 94f07e2e..00000000 --- a/src/glx_context.h +++ /dev/null @@ -1,181 +0,0 @@ -//======================================================================== -// GLFW 3.4 GLX - www.glfw.org -//------------------------------------------------------------------------ -// Copyright (c) 2002-2006 Marcus Geelnard -// Copyright (c) 2006-2017 Camilla Löwy -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would -// be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -// -//======================================================================== - -#define GLX_VENDOR 1 -#define GLX_RGBA_BIT 0x00000001 -#define GLX_WINDOW_BIT 0x00000001 -#define GLX_DRAWABLE_TYPE 0x8010 -#define GLX_RENDER_TYPE 0x8011 -#define GLX_RGBA_TYPE 0x8014 -#define GLX_DOUBLEBUFFER 5 -#define GLX_STEREO 6 -#define GLX_AUX_BUFFERS 7 -#define GLX_RED_SIZE 8 -#define GLX_GREEN_SIZE 9 -#define GLX_BLUE_SIZE 10 -#define GLX_ALPHA_SIZE 11 -#define GLX_DEPTH_SIZE 12 -#define GLX_STENCIL_SIZE 13 -#define GLX_ACCUM_RED_SIZE 14 -#define GLX_ACCUM_GREEN_SIZE 15 -#define GLX_ACCUM_BLUE_SIZE 16 -#define GLX_ACCUM_ALPHA_SIZE 17 -#define GLX_SAMPLES 0x186a1 -#define GLX_VISUAL_ID 0x800b - -#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20b2 -#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001 -#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 -#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 -#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 -#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 -#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define GLX_CONTEXT_FLAGS_ARB 0x2094 -#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 -#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 -#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252 -#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 -#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261 -#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097 -#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0 -#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 -#define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3 - -typedef XID GLXWindow; -typedef XID GLXDrawable; -typedef struct __GLXFBConfig* GLXFBConfig; -typedef struct __GLXcontext* GLXContext; -typedef void (*__GLXextproc)(void); - -typedef int (*PFNGLXGETFBCONFIGATTRIBPROC)(Display*,GLXFBConfig,int,int*); -typedef const char* (*PFNGLXGETCLIENTSTRINGPROC)(Display*,int); -typedef Bool (*PFNGLXQUERYEXTENSIONPROC)(Display*,int*,int*); -typedef Bool (*PFNGLXQUERYVERSIONPROC)(Display*,int*,int*); -typedef void (*PFNGLXDESTROYCONTEXTPROC)(Display*,GLXContext); -typedef Bool (*PFNGLXMAKECURRENTPROC)(Display*,GLXDrawable,GLXContext); -typedef void (*PFNGLXSWAPBUFFERSPROC)(Display*,GLXDrawable); -typedef const char* (*PFNGLXQUERYEXTENSIONSSTRINGPROC)(Display*,int); -typedef GLXFBConfig* (*PFNGLXGETFBCONFIGSPROC)(Display*,int,int*); -typedef GLXContext (*PFNGLXCREATENEWCONTEXTPROC)(Display*,GLXFBConfig,int,GLXContext,Bool); -typedef __GLXextproc (* PFNGLXGETPROCADDRESSPROC)(const GLubyte *procName); -typedef void (*PFNGLXSWAPINTERVALEXTPROC)(Display*,GLXDrawable,int); -typedef XVisualInfo* (*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display*,GLXFBConfig); -typedef GLXWindow (*PFNGLXCREATEWINDOWPROC)(Display*,GLXFBConfig,Window,const int*); -typedef void (*PFNGLXDESTROYWINDOWPROC)(Display*,GLXWindow); - -typedef int (*PFNGLXSWAPINTERVALMESAPROC)(int); -typedef int (*PFNGLXSWAPINTERVALSGIPROC)(int); -typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLXContext,Bool,const int*); - -// libGL.so function pointer typedefs -#define glXGetFBConfigs _glfw.glx.GetFBConfigs -#define glXGetFBConfigAttrib _glfw.glx.GetFBConfigAttrib -#define glXGetClientString _glfw.glx.GetClientString -#define glXQueryExtension _glfw.glx.QueryExtension -#define glXQueryVersion _glfw.glx.QueryVersion -#define glXDestroyContext _glfw.glx.DestroyContext -#define glXMakeCurrent _glfw.glx.MakeCurrent -#define glXSwapBuffers _glfw.glx.SwapBuffers -#define glXQueryExtensionsString _glfw.glx.QueryExtensionsString -#define glXCreateNewContext _glfw.glx.CreateNewContext -#define glXGetVisualFromFBConfig _glfw.glx.GetVisualFromFBConfig -#define glXCreateWindow _glfw.glx.CreateWindow -#define glXDestroyWindow _glfw.glx.DestroyWindow - -#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX glx -#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx - - -// GLX-specific per-context data -// -typedef struct _GLFWcontextGLX -{ - GLXContext handle; - GLXWindow window; - -} _GLFWcontextGLX; - -// GLX-specific global data -// -typedef struct _GLFWlibraryGLX -{ - int major, minor; - int eventBase; - int errorBase; - - // dlopen handle for libGL.so.1 - void* handle; - - // GLX 1.3 functions - PFNGLXGETFBCONFIGSPROC GetFBConfigs; - PFNGLXGETFBCONFIGATTRIBPROC GetFBConfigAttrib; - PFNGLXGETCLIENTSTRINGPROC GetClientString; - PFNGLXQUERYEXTENSIONPROC QueryExtension; - PFNGLXQUERYVERSIONPROC QueryVersion; - PFNGLXDESTROYCONTEXTPROC DestroyContext; - PFNGLXMAKECURRENTPROC MakeCurrent; - PFNGLXSWAPBUFFERSPROC SwapBuffers; - PFNGLXQUERYEXTENSIONSSTRINGPROC QueryExtensionsString; - PFNGLXCREATENEWCONTEXTPROC CreateNewContext; - PFNGLXGETVISUALFROMFBCONFIGPROC GetVisualFromFBConfig; - PFNGLXCREATEWINDOWPROC CreateWindow; - PFNGLXDESTROYWINDOWPROC DestroyWindow; - - // GLX 1.4 and extension functions - PFNGLXGETPROCADDRESSPROC GetProcAddress; - PFNGLXGETPROCADDRESSPROC GetProcAddressARB; - PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI; - PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT; - PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA; - PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; - GLFWbool SGI_swap_control; - GLFWbool EXT_swap_control; - GLFWbool MESA_swap_control; - GLFWbool ARB_multisample; - GLFWbool ARB_framebuffer_sRGB; - GLFWbool EXT_framebuffer_sRGB; - GLFWbool ARB_create_context; - GLFWbool ARB_create_context_profile; - GLFWbool ARB_create_context_robustness; - GLFWbool EXT_create_context_es2_profile; - GLFWbool ARB_create_context_no_error; - GLFWbool ARB_context_flush_control; - -} _GLFWlibraryGLX; - -GLFWbool _glfwInitGLX(void); -void _glfwTerminateGLX(void); -GLFWbool _glfwCreateContextGLX(_GLFWwindow* window, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig); -void _glfwDestroyContextGLX(_GLFWwindow* window); -GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig, - Visual** visual, int* depth); - diff --git a/src/init.c b/src/init.c index a9f9a54d..d07a492e 100644 --- a/src/init.c +++ b/src/init.c @@ -36,16 +36,15 @@ #include -// The global variables below comprise all mutable global data in GLFW -// -// Any other global variable is a bug +// NOTE: The global variables below comprise all mutable global data in GLFW +// Any other mutable global variable is a bug -// Global state shared between compilation units of GLFW +// This contains all mutable state shared between compilation units of GLFW // _GLFWlibrary _glfw = { GLFW_FALSE }; // These are outside of _glfw so they can be used before initialization and -// after termination +// after termination without special handling when _glfw is cleared to zero // static _GLFWerror _glfwMainThreadError; static GLFWerrorfun _glfwErrorCallback; @@ -54,6 +53,8 @@ static _GLFWinitconfig _glfwInitHints = { GLFW_TRUE, // hat buttons GLFW_ANGLE_PLATFORM_TYPE_NONE, // ANGLE backend + GLFW_ANY_PLATFORM, // preferred platform + NULL, // vkGetInstanceProcAddr function { GLFW_TRUE, // macOS menu bar GLFW_TRUE // macOS bundle chdir @@ -102,7 +103,7 @@ static void terminate(void) { _GLFWmonitor* monitor = _glfw.monitors[i]; if (monitor->originalRamp.size) - _glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp); + _glfw.platform.setGammaRamp(monitor, &monitor->originalRamp); _glfwFreeMonitor(monitor); } @@ -115,8 +116,8 @@ static void terminate(void) _glfw.mappingCount = 0; _glfwTerminateVulkan(); - _glfwPlatformTerminateJoysticks(); - _glfwPlatformTerminate(); + _glfw.platform.terminateJoysticks(); + _glfw.platform.terminate(); _glfw.initialized = GLFW_FALSE; @@ -139,6 +140,90 @@ static void terminate(void) ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// +// Encode a Unicode code point to a UTF-8 stream +// Based on cutef8 by Jeff Bezanson (Public Domain) +// +size_t _glfwEncodeUTF8(char* s, uint32_t codepoint) +{ + size_t count = 0; + + if (codepoint < 0x80) + s[count++] = (char) codepoint; + else if (codepoint < 0x800) + { + s[count++] = (codepoint >> 6) | 0xc0; + s[count++] = (codepoint & 0x3f) | 0x80; + } + else if (codepoint < 0x10000) + { + s[count++] = (codepoint >> 12) | 0xe0; + s[count++] = ((codepoint >> 6) & 0x3f) | 0x80; + s[count++] = (codepoint & 0x3f) | 0x80; + } + else if (codepoint < 0x110000) + { + s[count++] = (codepoint >> 18) | 0xf0; + s[count++] = ((codepoint >> 12) & 0x3f) | 0x80; + s[count++] = ((codepoint >> 6) & 0x3f) | 0x80; + s[count++] = (codepoint & 0x3f) | 0x80; + } + + return count; +} + +// Splits and translates a text/uri-list into separate file paths +// NOTE: This function destroys the provided string +// +char** _glfwParseUriList(char* text, int* count) +{ + const char* prefix = "file://"; + char** paths = NULL; + char* line; + + *count = 0; + + while ((line = strtok(text, "\r\n"))) + { + char* path; + + text = NULL; + + if (line[0] == '#') + continue; + + if (strncmp(line, prefix, strlen(prefix)) == 0) + { + line += strlen(prefix); + // TODO: Validate hostname + while (*line != '/') + line++; + } + + (*count)++; + + path = _glfw_calloc(strlen(line) + 1, 1); + paths = _glfw_realloc(paths, *count * sizeof(char*)); + paths[*count - 1] = path; + + while (*line) + { + if (line[0] == '%' && line[1] && line[2]) + { + const char digits[3] = { line[1], line[2], '\0' }; + *path = (char) strtol(digits, NULL, 16); + line += 2; + } + else + *path = *line; + + path++; + line++; + } + } + + return paths; +} + char* _glfw_strdup(const char* source) { const size_t length = strlen(source); @@ -147,6 +232,16 @@ char* _glfw_strdup(const char* source) return result; } +int _glfw_min(int a, int b) +{ + return a < b ? a : b; +} + +int _glfw_max(int a, int b) +{ + return a > b ? a : b; +} + float _glfw_fminf(float a, float b) { if (a != a) @@ -274,6 +369,8 @@ void _glfwInputError(int code, const char* format, ...) strcpy(description, "The requested feature cannot be implemented for this platform"); else if (code == GLFW_FEATURE_UNIMPLEMENTED) strcpy(description, "The requested feature has not yet been implemented for this platform"); + else if (code == GLFW_PLATFORM_UNAVAILABLE) + strcpy(description, "The requested platform is unavailable"); else strcpy(description, "ERROR: UNKNOWN GLFW ERROR"); } @@ -322,7 +419,10 @@ GLFWAPI int glfwInit(void) _glfw.allocator.deallocate = defaultDeallocate; } - if (!_glfwPlatformInit()) + if (!_glfwSelectPlatform(_glfw.hints.init.platformID, &_glfw.platform)) + return GLFW_FALSE; + + if (!_glfw.platform.init()) { terminate(); return GLFW_FALSE; @@ -340,9 +440,11 @@ GLFWAPI int glfwInit(void) _glfwInitGamepadMappings(); - _glfw.initialized = GLFW_TRUE; + _glfwPlatformInitTimer(); _glfw.timer.offset = _glfwPlatformGetTimerValue(); + _glfw.initialized = GLFW_TRUE; + glfwDefaultWindowHints(); return GLFW_TRUE; } @@ -365,6 +467,9 @@ GLFWAPI void glfwInitHint(int hint, int value) case GLFW_ANGLE_PLATFORM_TYPE: _glfwInitHints.angleType = value; return; + case GLFW_PLATFORM: + _glfwInitHints.platformID = value; + return; case GLFW_COCOA_CHDIR_RESOURCES: _glfwInitHints.ns.chdir = value; return; @@ -393,6 +498,11 @@ GLFWAPI void glfwInitAllocator(const GLFWallocator* allocator) memset(&_glfwInitAllocator, 0, sizeof(GLFWallocator)); } +GLFWAPI void glfwInitVulkanLoader(PFN_vkGetInstanceProcAddr loader) +{ + _glfwInitHints.vulkanLoader = loader; +} + GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev) { if (major != NULL) @@ -403,11 +513,6 @@ GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev) *rev = GLFW_VERSION_REVISION; } -GLFWAPI const char* glfwGetVersionString(void) -{ - return _glfwPlatformGetVersionString(); -} - GLFWAPI int glfwGetError(const char** description) { _GLFWerror* error; @@ -434,7 +539,7 @@ GLFWAPI int glfwGetError(const char** description) GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun) { - _GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun); + _GLFW_SWAP(GLFWerrorfun, _glfwErrorCallback, cbfun); return cbfun; } diff --git a/src/input.c b/src/input.c index 863cacd7..218b4578 100644 --- a/src/input.c +++ b/src/input.c @@ -40,9 +40,16 @@ #define _GLFW_STICK 3 // Internal constants for gamepad mapping source types -#define _GLFW_JOYSTICK_AXIS 1 -#define _GLFW_JOYSTICK_BUTTON 2 -#define _GLFW_JOYSTICK_HATBIT 3 +#define _GLFW_JOYSTICK_AXIS 1 +#define _GLFW_JOYSTICK_BUTTON 2 +#define _GLFW_JOYSTICK_HATBIT 3 + +#define GLFW_MOD_MASK (GLFW_MOD_SHIFT | \ + GLFW_MOD_CONTROL | \ + GLFW_MOD_ALT | \ + GLFW_MOD_SUPER | \ + GLFW_MOD_CAPS_LOCK | \ + GLFW_MOD_NUM_LOCK) // Initializes the platform joystick API if it has not been already // @@ -50,9 +57,9 @@ static GLFWbool initJoysticks(void) { if (!_glfw.joysticksInitialized) { - if (!_glfwPlatformInitJoysticks()) + if (!_glfw.platform.initJoysticks()) { - _glfwPlatformTerminateJoysticks(); + _glfw.platform.terminateJoysticks(); return GLFW_FALSE; } } @@ -62,11 +69,11 @@ static GLFWbool initJoysticks(void) // Finds a mapping based on joystick GUID // -static _GLFWmapping* findMapping(const char* guid) +static _GLFWmapping *findMapping(const char *guid) { int i; - for (i = 0; i < _glfw.mappingCount; i++) + for (i = 0; i < _glfw.mappingCount; i++) { if (strcmp(_glfw.mappings[i].guid, guid) == 0) return _glfw.mappings + i; @@ -77,8 +84,8 @@ static _GLFWmapping* findMapping(const char* guid) // Checks whether a gamepad mapping element is present in the hardware // -static GLFWbool isValidElementForJoystick(const _GLFWmapelement* e, - const _GLFWjoystick* js) +static GLFWbool isValidElementForJoystick(const _GLFWmapelement *e, + const _GLFWjoystick *js) { if (e->type == _GLFW_JOYSTICK_HATBIT && (e->index >> 4) >= js->hatCount) return GLFW_FALSE; @@ -92,20 +99,20 @@ static GLFWbool isValidElementForJoystick(const _GLFWmapelement* e, // Finds a mapping based on joystick GUID and verifies element indices // -static _GLFWmapping* findValidMapping(const _GLFWjoystick* js) +static _GLFWmapping *findValidMapping(const _GLFWjoystick *js) { - _GLFWmapping* mapping = findMapping(js->guid); + _GLFWmapping *mapping = findMapping(js->guid); if (mapping) { int i; - for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++) + for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++) { if (!isValidElementForJoystick(mapping->buttons + i, js)) return NULL; } - for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++) + for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++) { if (!isValidElementForJoystick(mapping->axes + i, js)) return NULL; @@ -117,39 +124,38 @@ static _GLFWmapping* findValidMapping(const _GLFWjoystick* js) // Parses an SDL_GameControllerDB line and adds it to the mapping list // -static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string) +static GLFWbool parseMapping(_GLFWmapping *mapping, const char *string) { - const char* c = string; + const char *c = string; size_t i, length; struct { - const char* name; - _GLFWmapelement* element; + const char *name; + _GLFWmapelement *element; } fields[] = - { - { "platform", NULL }, - { "a", mapping->buttons + GLFW_GAMEPAD_BUTTON_A }, - { "b", mapping->buttons + GLFW_GAMEPAD_BUTTON_B }, - { "x", mapping->buttons + GLFW_GAMEPAD_BUTTON_X }, - { "y", mapping->buttons + GLFW_GAMEPAD_BUTTON_Y }, - { "back", mapping->buttons + GLFW_GAMEPAD_BUTTON_BACK }, - { "start", mapping->buttons + GLFW_GAMEPAD_BUTTON_START }, - { "guide", mapping->buttons + GLFW_GAMEPAD_BUTTON_GUIDE }, - { "leftshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_BUMPER }, - { "rightshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER }, - { "leftstick", mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_THUMB }, - { "rightstick", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_THUMB }, - { "dpup", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_UP }, - { "dpright", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_RIGHT }, - { "dpdown", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_DOWN }, - { "dpleft", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_LEFT }, - { "lefttrigger", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_TRIGGER }, - { "righttrigger", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER }, - { "leftx", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_X }, - { "lefty", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_Y }, - { "rightx", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_X }, - { "righty", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_Y } - }; + { + {"platform", NULL}, + {"a", mapping->buttons + GLFW_GAMEPAD_BUTTON_A}, + {"b", mapping->buttons + GLFW_GAMEPAD_BUTTON_B}, + {"x", mapping->buttons + GLFW_GAMEPAD_BUTTON_X}, + {"y", mapping->buttons + GLFW_GAMEPAD_BUTTON_Y}, + {"back", mapping->buttons + GLFW_GAMEPAD_BUTTON_BACK}, + {"start", mapping->buttons + GLFW_GAMEPAD_BUTTON_START}, + {"guide", mapping->buttons + GLFW_GAMEPAD_BUTTON_GUIDE}, + {"leftshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_BUMPER}, + {"rightshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER}, + {"leftstick", mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_THUMB}, + {"rightstick", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_THUMB}, + {"dpup", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_UP}, + {"dpright", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_RIGHT}, + {"dpdown", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_DOWN}, + {"dpleft", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_LEFT}, + {"lefttrigger", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_TRIGGER}, + {"righttrigger", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER}, + {"leftx", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_X}, + {"lefty", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_Y}, + {"rightx", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_X}, + {"righty", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_Y}}; length = strcspn(c, ","); if (length != 32 || c[length] != ',') @@ -177,7 +183,7 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string) if (*c == '+' || *c == '-') return GLFW_FALSE; - for (i = 0; i < sizeof(fields) / sizeof(fields[0]); i++) + for (i = 0; i < sizeof(fields) / sizeof(fields[0]); i++) { length = strlen(fields[i].name); if (strncmp(c, fields[i].name, length) != 0 || c[length] != ':') @@ -187,7 +193,7 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string) if (fields[i].element) { - _GLFWmapelement* e = fields[i].element; + _GLFWmapelement *e = fields[i].element; int8_t minimum = -1; int8_t maximum = 1; @@ -213,12 +219,12 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string) if (e->type == _GLFW_JOYSTICK_HATBIT) { - const unsigned long hat = strtoul(c + 1, (char**) &c, 10); - const unsigned long bit = strtoul(c + 1, (char**) &c, 10); - e->index = (uint8_t) ((hat << 4) | bit); + const unsigned long hat = strtoul(c + 1, (char **)&c, 10); + const unsigned long bit = strtoul(c + 1, (char **)&c, 10); + e->index = (uint8_t)((hat << 4) | bit); } else - e->index = (uint8_t) strtoul(c + 1, (char**) &c, 10); + e->index = (uint8_t)strtoul(c + 1, (char **)&c, 10); if (e->type == _GLFW_JOYSTICK_AXIS) { @@ -234,8 +240,9 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string) } else { - length = strlen(_GLFW_PLATFORM_MAPPING_NAME); - if (strncmp(c, _GLFW_PLATFORM_MAPPING_NAME, length) != 0) + const char *name = _glfw.platform.getMappingName(); + length = strlen(name); + if (strncmp(c, name, length) != 0) return GLFW_FALSE; } @@ -246,25 +253,30 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string) c += strspn(c, ","); } - for (i = 0; i < 32; i++) + for (i = 0; i < 32; i++) { if (mapping->guid[i] >= 'A' && mapping->guid[i] <= 'F') mapping->guid[i] += 'a' - 'A'; } - _glfwPlatformUpdateGamepadGUID(mapping->guid); + _glfw.platform.updateGamepadGUID(mapping->guid); return GLFW_TRUE; } - ////////////////////////////////////////////////////////////////////////// ////// GLFW event API ////// ////////////////////////////////////////////////////////////////////////// // Notifies shared code of a physical key event // -void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods) +void _glfwInputKey(_GLFWwindow *window, int key, int scancode, int action, int mods) { + assert(window != NULL); + assert(key >= 0 || key == GLFW_KEY_UNKNOWN); + assert(key <= GLFW_KEY_LAST); + assert(action == GLFW_PRESS || action == GLFW_RELEASE); + assert(mods == (mods & GLFW_MOD_MASK)); + if (key >= 0 && key <= GLFW_KEY_LAST) { GLFWbool repeated = GLFW_FALSE; @@ -278,7 +290,7 @@ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int m if (action == GLFW_RELEASE && window->stickyKeys) window->keys[key] = _GLFW_STICK; else - window->keys[key] = (char) action; + window->keys[key] = (char)action; if (repeated) action = GLFW_REPEAT; @@ -288,14 +300,18 @@ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int m mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK); if (window->callbacks.key) - window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods); + window->callbacks.key((GLFWwindow *)window, key, scancode, action, mods); } // Notifies shared code of a Unicode codepoint input event // The 'plain' parameter determines whether to emit a regular character event // -void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain) +void _glfwInputChar(_GLFWwindow *window, uint32_t codepoint, int mods, GLFWbool plain) { + assert(window != NULL); + assert(mods == (mods & GLFW_MOD_MASK)); + assert(plain == GLFW_TRUE || plain == GLFW_FALSE); + if (codepoint < 32 || (codepoint > 126 && codepoint < 160)) return; @@ -303,27 +319,39 @@ void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWb mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK); if (window->callbacks.charmods) - window->callbacks.charmods((GLFWwindow*) window, codepoint, mods); + window->callbacks.charmods((GLFWwindow *)window, codepoint, mods); if (plain) { if (window->callbacks.character) - window->callbacks.character((GLFWwindow*) window, codepoint); + window->callbacks.character((GLFWwindow *)window, codepoint); } } // Notifies shared code of a scroll event // -void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset) +void _glfwInputScroll(_GLFWwindow *window, double xoffset, double yoffset) { + assert(window != NULL); + assert(xoffset > -FLT_MAX); + assert(xoffset < FLT_MAX); + assert(yoffset > -FLT_MAX); + assert(yoffset < FLT_MAX); + if (window->callbacks.scroll) - window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset); + window->callbacks.scroll((GLFWwindow *)window, xoffset, yoffset); } // Notifies shared code of a mouse button click event // -void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods) +void _glfwInputMouseClick(_GLFWwindow *window, int button, int action, int mods) { + assert(window != NULL); + assert(button >= 0); + assert(button <= GLFW_MOUSE_BUTTON_LAST); + assert(action == GLFW_PRESS || action == GLFW_RELEASE); + assert(mods == (mods & GLFW_MOD_MASK)); + if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST) return; @@ -333,17 +361,23 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods) if (action == GLFW_RELEASE && window->stickyMouseButtons) window->mouseButtons[button] = _GLFW_STICK; else - window->mouseButtons[button] = (char) action; + window->mouseButtons[button] = (char)action; if (window->callbacks.mouseButton) - window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods); + window->callbacks.mouseButton((GLFWwindow *)window, button, action, mods); } // Notifies shared code of a cursor motion event // The position is specified in content area relative screen coordinates // -void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos) +void _glfwInputCursorPos(_GLFWwindow *window, double xpos, double ypos) { + assert(window != NULL); + assert(xpos > -FLT_MAX); + assert(xpos < FLT_MAX); + assert(ypos > -FLT_MAX); + assert(ypos < FLT_MAX); + if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos) return; @@ -351,104 +385,148 @@ void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos) window->virtualCursorPosY = ypos; if (window->callbacks.cursorPos) - window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos); + window->callbacks.cursorPos((GLFWwindow *)window, xpos, ypos); } // Notifies shared code of a cursor enter/leave event // -void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered) +void _glfwInputCursorEnter(_GLFWwindow *window, GLFWbool entered) { + assert(window != NULL); + assert(entered == GLFW_TRUE || entered == GLFW_FALSE); + if (window->callbacks.cursorEnter) - window->callbacks.cursorEnter((GLFWwindow*) window, entered); + window->callbacks.cursorEnter((GLFWwindow *)window, entered); } // Notifies shared code of files or directories dropped on a window // -void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths) +void _glfwInputDrop(_GLFWwindow *window, int count, const char **paths) { + assert(window != NULL); + assert(count > 0); + assert(paths != NULL); + if (window->callbacks.drop) - window->callbacks.drop((GLFWwindow*) window, count, paths); + window->callbacks.drop((GLFWwindow *)window, count, paths); } // Notifies shared code of a change in the gamepad state. // Automatically recalculates the state if the gamepad callback is installed. -void _glfwInputGamepad(_GLFWjoystick* js) +void _glfwInputGamepad(_GLFWjoystick *js) { - const int jid = (int) (js - _glfw.joysticks); + const int jid = (int)(js - _glfw.joysticks); - if (!_glfw.initialized) { + if (!_glfw.initialized) + { return; } - if ((js->mapping != NULL) && (_glfw.callbacks.gamepad_state)) { + if ((js->mapping != NULL) && (_glfw.callbacks.gamepad_state)) + { GLFWgamepadstate state; - if (glfwGetGamepadState(jid, &state)) { - _glfw.callbacks.gamepad_state(jid, state.buttons, state.axes); + if (glfwGetGamepadState(jid, &state)) + { + _glfw.callbacks.gamepad_state(jid, state.buttons, state.axes); } } } // Notifies shared code of a joystick connection or disconnection // -void _glfwInputJoystick(_GLFWjoystick* js, int event) +void _glfwInputJoystick(_GLFWjoystick *js, int event) { - if (_glfw.callbacks.joystick) { - const int jid = (int) (js - _glfw.joysticks); - _glfw.callbacks.joystick(jid, event); - } -} + assert(js != NULL); + assert(event == GLFW_CONNECTED || event == GLFW_DISCONNECTED); + if (event == GLFW_CONNECTED) + js->connected = GLFW_TRUE; + else if (event == GLFW_DISCONNECTED) + js->connected = GLFW_FALSE; + + if (_glfw.callbacks.joystick) + _glfw.callbacks.joystick((int)(js - _glfw.joysticks), event); +} // Notifies shared code of the new value of a joystick axis // -void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value) +void _glfwInputJoystickAxis(_GLFWjoystick *js, int axis, float value) { - if (js->axes[axis] != value) { - const int jid = (int) (js - _glfw.joysticks); + assert(js != NULL); + assert(axis >= 0); + assert(axis < js->axisCount); + + if (js->axes[axis] != value) + { + const int jid = (int)(js - _glfw.joysticks); js->axes[axis] = value; if (_glfw.callbacks.joystick_axis) _glfw.callbacks.joystick_axis(jid, axis, value); _glfwInputGamepad(js); } + else + { + js->axes[axis] = value; + } } // Notifies shared code of the new value of a joystick button // -void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value) +void _glfwInputJoystickButton(_GLFWjoystick *js, int button, char value) { - if (js->buttons[button] != value) { - const int jid = (int) (js - _glfw.joysticks); + assert(js != NULL); + assert(button >= 0); + assert(button < js->buttonCount); + assert(value == GLFW_PRESS || value == GLFW_RELEASE); + if (js->buttons[button] != value) + { + const int jid = (int)(js - _glfw.joysticks); js->buttons[button] = value; - if(_glfw.callbacks.joystick_button) + if (_glfw.callbacks.joystick_button) _glfw.callbacks.joystick_button(jid, button, value); _glfwInputGamepad(js); } + else + { + js->buttons[button] = value; + } } // Notifies shared code of the new value of a joystick hat // -void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value) +void _glfwInputJoystickHat(_GLFWjoystick *js, int hat, char value) { - const int base = js->buttonCount + hat * 4; + int base; + + assert(js != NULL); + assert(hat >= 0); + assert(hat < js->hatCount); + + // Valid hat values only use the least significant nibble and have at most two bits + // set, which can be considered adjacent plus an arbitrary rotation within the nibble + assert((value & 0xf0) == 0); + assert((value & ((value << 2) | (value >> 2))) == 0); + + base = js->buttonCount + hat * 4; js->buttons[base + 0] = (value & 0x01) ? GLFW_PRESS : GLFW_RELEASE; js->buttons[base + 1] = (value & 0x02) ? GLFW_PRESS : GLFW_RELEASE; js->buttons[base + 2] = (value & 0x04) ? GLFW_PRESS : GLFW_RELEASE; js->buttons[base + 3] = (value & 0x08) ? GLFW_PRESS : GLFW_RELEASE; - if (js->hats[hat] != value) { - const int jid = (int) (js - _glfw.joysticks); + if (js->hats[hat] != value) + { + const int jid = (int)(js - _glfw.joysticks); js->hats[hat] = value; - if(_glfw.callbacks.joystick_hat) - _glfw.callbacks.joystick_hat(jid, hat, value); + if (_glfw.callbacks.joystick_hat) + _glfw.callbacks.joystick_hat(jid, hat, value); _glfwInputGamepad(js); } } - ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// @@ -458,10 +536,10 @@ void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value) void _glfwInitGamepadMappings(void) { size_t i; - const size_t count = sizeof(_glfwDefaultMappings) / sizeof(char*); + const size_t count = sizeof(_glfwDefaultMappings) / sizeof(char *); _glfw.mappings = _glfw_calloc(count, sizeof(_GLFWmapping)); - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { if (parseMapping(&_glfw.mappings[_glfw.mappingCount], _glfwDefaultMappings[i])) _glfw.mappingCount++; @@ -470,18 +548,18 @@ void _glfwInitGamepadMappings(void) // Returns an available joystick object with arrays and name allocated // -_GLFWjoystick* _glfwAllocJoystick(const char* name, - const char* guid, +_GLFWjoystick *_glfwAllocJoystick(const char *name, + const char *guid, int axisCount, int buttonCount, int hatCount) { int jid; - _GLFWjoystick* js; + _GLFWjoystick *js; - for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) + for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) { - if (!_glfw.joysticks[jid].present) + if (!_glfw.joysticks[jid].allocated) break; } @@ -489,13 +567,13 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name, return NULL; js = _glfw.joysticks + jid; - js->present = GLFW_TRUE; - js->axes = _glfw_calloc(axisCount, sizeof(float)); - js->buttons = _glfw_calloc(buttonCount + (size_t) hatCount * 4, 1); - js->hats = _glfw_calloc(hatCount, 1); - js->axisCount = axisCount; + js->allocated = GLFW_TRUE; + js->axes = _glfw_calloc(axisCount, sizeof(float)); + js->buttons = _glfw_calloc(buttonCount + (size_t)hatCount * 4, 1); + js->hats = _glfw_calloc(hatCount, 1); + js->axisCount = axisCount; js->buttonCount = buttonCount; - js->hatCount = hatCount; + js->hatCount = hatCount; strncpy(js->name, name, sizeof(js->name) - 1); strncpy(js->guid, guid, sizeof(js->guid) - 1); @@ -506,7 +584,7 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name, // Frees arrays and name and flags the joystick object as unused // -void _glfwFreeJoystick(_GLFWjoystick* js) +void _glfwFreeJoystick(_GLFWjoystick *js) { _glfw_free(js->axes); _glfw_free(js->buttons); @@ -516,67 +594,71 @@ void _glfwFreeJoystick(_GLFWjoystick* js) // Center the cursor in the content area of the specified window // -void _glfwCenterCursorInContentArea(_GLFWwindow* window) +void _glfwCenterCursorInContentArea(_GLFWwindow *window) { int width, height; - _glfwPlatformGetWindowSize(window, &width, &height); - _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0); + _glfw.platform.getWindowSize(window, &width, &height); + _glfw.platform.setCursorPos(window, width / 2.0, height / 2.0); } -void _glfwPollAllJoysticks() { +void _glfwPollAllJoysticks() +{ int jid; - for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) + for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) { - if (_glfw.joysticks[jid].present == GLFW_TRUE) { - _glfwPlatformPollJoystick(_glfw.joysticks + jid, _GLFW_POLL_ALL); + if (_glfw.joysticks[jid].connected == GLFW_TRUE) + { + _glfwPlatformPollJoystick(_glfw.joysticks + jid, _GLFW_POLL_ALL); } } } - ////////////////////////////////////////////////////////////////////////// ////// GLFW public API ////// ////////////////////////////////////////////////////////////////////////// -GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode) +GLFWAPI int glfwGetInputMode(GLFWwindow *handle, int mode) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(0); switch (mode) { - case GLFW_CURSOR: - return window->cursorMode; - case GLFW_STICKY_KEYS: - return window->stickyKeys; - case GLFW_STICKY_MOUSE_BUTTONS: - return window->stickyMouseButtons; - case GLFW_LOCK_KEY_MODS: - return window->lockKeyMods; - case GLFW_RAW_MOUSE_MOTION: - return window->rawMouseMotion; + case GLFW_CURSOR: + return window->cursorMode; + case GLFW_STICKY_KEYS: + return window->stickyKeys; + case GLFW_STICKY_MOUSE_BUTTONS: + return window->stickyMouseButtons; + case GLFW_LOCK_KEY_MODS: + return window->lockKeyMods; + case GLFW_RAW_MOUSE_MOTION: + return window->rawMouseMotion; } _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); return 0; } -GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) +GLFWAPI void glfwSetInputMode(GLFWwindow *handle, int mode, int value) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT(); - if (mode == GLFW_CURSOR) + switch (mode) + { + case GLFW_CURSOR: { if (value != GLFW_CURSOR_NORMAL && value != GLFW_CURSOR_HIDDEN && - value != GLFW_CURSOR_DISABLED) + value != GLFW_CURSOR_DISABLED && + value != GLFW_CURSOR_CAPTURED) { _glfwInputError(GLFW_INVALID_ENUM, "Invalid cursor mode 0x%08X", @@ -589,12 +671,14 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) window->cursorMode = value; - _glfwPlatformGetCursorPos(window, - &window->virtualCursorPosX, - &window->virtualCursorPosY); - _glfwPlatformSetCursorMode(window, value); + _glfw.platform.getCursorPos(window, + &window->virtualCursorPosX, + &window->virtualCursorPosY); + _glfw.platform.setCursorMode(window, value); + return; } - else if (mode == GLFW_STICKY_KEYS) + + case GLFW_STICKY_KEYS: { value = value ? GLFW_TRUE : GLFW_FALSE; if (window->stickyKeys == value) @@ -605,7 +689,7 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) int i; // Release all sticky keys - for (i = 0; i <= GLFW_KEY_LAST; i++) + for (i = 0; i <= GLFW_KEY_LAST; i++) { if (window->keys[i] == _GLFW_STICK) window->keys[i] = GLFW_RELEASE; @@ -613,8 +697,10 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) } window->stickyKeys = value; + return; } - else if (mode == GLFW_STICKY_MOUSE_BUTTONS) + + case GLFW_STICKY_MOUSE_BUTTONS: { value = value ? GLFW_TRUE : GLFW_FALSE; if (window->stickyMouseButtons == value) @@ -625,7 +711,7 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) int i; // Release all sticky mouse buttons - for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) + for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) { if (window->mouseButtons[i] == _GLFW_STICK) window->mouseButtons[i] = GLFW_RELEASE; @@ -633,14 +719,18 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) } window->stickyMouseButtons = value; + return; } - else if (mode == GLFW_LOCK_KEY_MODS) + + case GLFW_LOCK_KEY_MODS: { window->lockKeyMods = value ? GLFW_TRUE : GLFW_FALSE; + return; } - else if (mode == GLFW_RAW_MOUSE_MOTION) + + case GLFW_RAW_MOUSE_MOTION: { - if (!_glfwPlatformRawMouseMotionSupported()) + if (!_glfw.platform.rawMouseMotionSupported()) { _glfwInputError(GLFW_PLATFORM_ERROR, "Raw mouse motion is not supported on this system"); @@ -652,19 +742,21 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) return; window->rawMouseMotion = value; - _glfwPlatformSetRawMouseMotion(window, value); + _glfw.platform.setRawMouseMotion(window, value); + return; } - else - _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); + } + + _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); } GLFWAPI int glfwRawMouseMotionSupported(void) { _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); - return _glfwPlatformRawMouseMotionSupported(); + return _glfw.platform.rawMouseMotionSupported(); } -GLFWAPI const char* glfwGetKeyName(int key, int scancode) +GLFWAPI const char *glfwGetKeyName(int key, int scancode) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL); @@ -677,10 +769,10 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode) return NULL; } - scancode = _glfwPlatformGetKeyScancode(key); + scancode = _glfw.platform.getKeyScancode(key); } - return _glfwPlatformGetScancodeName(scancode); + return _glfw.platform.getScancodeName(scancode); } GLFWAPI int glfwGetKeyScancode(int key) @@ -693,12 +785,12 @@ GLFWAPI int glfwGetKeyScancode(int key) return GLFW_RELEASE; } - return _glfwPlatformGetKeyScancode(key); + return _glfw.platform.getKeyScancode(key); } -GLFWAPI int glfwGetKey(GLFWwindow* handle, int key) +GLFWAPI int glfwGetKey(GLFWwindow *handle, int key) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE); @@ -716,12 +808,12 @@ GLFWAPI int glfwGetKey(GLFWwindow* handle, int key) return GLFW_PRESS; } - return (int) window->keys[key]; + return (int)window->keys[key]; } -GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button) +GLFWAPI int glfwGetMouseButton(GLFWwindow *handle, int button) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE); @@ -739,12 +831,12 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button) return GLFW_PRESS; } - return (int) window->mouseButtons[button]; + return (int)window->mouseButtons[button]; } -GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos) +GLFWAPI void glfwGetCursorPos(GLFWwindow *handle, double *xpos, double *ypos) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); if (xpos) @@ -762,12 +854,12 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos) *ypos = window->virtualCursorPosY; } else - _glfwPlatformGetCursorPos(window, xpos, ypos); + _glfw.platform.getCursorPos(window, xpos, ypos); } -GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos) +GLFWAPI void glfwSetCursorPos(GLFWwindow *handle, double xpos, double ypos) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT(); @@ -781,7 +873,7 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos) return; } - if (!_glfwPlatformWindowFocused(window)) + if (!_glfw.platform.windowFocused(window)) return; if (window->cursorMode == GLFW_CURSOR_DISABLED) @@ -793,34 +885,41 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos) else { // Update system cursor position - _glfwPlatformSetCursorPos(window, xpos, ypos); + _glfw.platform.setCursorPos(window, xpos, ypos); } } -GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot) +GLFWAPI GLFWcursor *glfwCreateCursor(const GLFWimage *image, int xhot, int yhot) { - _GLFWcursor* cursor; + _GLFWcursor *cursor; assert(image != NULL); + assert(image->pixels != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + if (image->width <= 0 || image->height <= 0) + { + _glfwInputError(GLFW_INVALID_VALUE, "Invalid image dimensions for cursor"); + return NULL; + } + cursor = _glfw_calloc(1, sizeof(_GLFWcursor)); cursor->next = _glfw.cursorListHead; _glfw.cursorListHead = cursor; - if (!_glfwPlatformCreateCursor(cursor, image, xhot, yhot)) + if (!_glfw.platform.createCursor(cursor, image, xhot, yhot)) { - glfwDestroyCursor((GLFWcursor*) cursor); + glfwDestroyCursor((GLFWcursor *)cursor); return NULL; } - return (GLFWcursor*) cursor; + return (GLFWcursor *)cursor; } -GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape) +GLFWAPI GLFWcursor *glfwCreateStandardCursor(int shape) { - _GLFWcursor* cursor; + _GLFWcursor *cursor; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); @@ -843,18 +942,18 @@ GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape) cursor->next = _glfw.cursorListHead; _glfw.cursorListHead = cursor; - if (!_glfwPlatformCreateStandardCursor(cursor, shape)) + if (!_glfw.platform.createStandardCursor(cursor, shape)) { - glfwDestroyCursor((GLFWcursor*) cursor); + glfwDestroyCursor((GLFWcursor *)cursor); return NULL; } - return (GLFWcursor*) cursor; + return (GLFWcursor *)cursor; } -GLFWAPI void glfwDestroyCursor(GLFWcursor* handle) +GLFWAPI void glfwDestroyCursor(GLFWcursor *handle) { - _GLFWcursor* cursor = (_GLFWcursor*) handle; + _GLFWcursor *cursor = (_GLFWcursor *)handle; _GLFW_REQUIRE_INIT(); @@ -863,20 +962,20 @@ GLFWAPI void glfwDestroyCursor(GLFWcursor* handle) // Make sure the cursor is not being used by any window { - _GLFWwindow* window; + _GLFWwindow *window; - for (window = _glfw.windowListHead; window; window = window->next) + for (window = _glfw.windowListHead; window; window = window->next) { if (window->cursor == cursor) - glfwSetCursor((GLFWwindow*) window, NULL); + glfwSetCursor((GLFWwindow *)window, NULL); } } - _glfwPlatformDestroyCursor(cursor); + _glfw.platform.destroyCursor(cursor); // Unlink cursor from global linked list { - _GLFWcursor** prev = &_glfw.cursorListHead; + _GLFWcursor **prev = &_glfw.cursorListHead; while (*prev != cursor) prev = &((*prev)->next); @@ -887,106 +986,106 @@ GLFWAPI void glfwDestroyCursor(GLFWcursor* handle) _glfw_free(cursor); } -GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle) +GLFWAPI void glfwSetCursor(GLFWwindow *windowHandle, GLFWcursor *cursorHandle) { - _GLFWwindow* window = (_GLFWwindow*) windowHandle; - _GLFWcursor* cursor = (_GLFWcursor*) cursorHandle; + _GLFWwindow *window = (_GLFWwindow *)windowHandle; + _GLFWcursor *cursor = (_GLFWcursor *)cursorHandle; assert(window != NULL); _GLFW_REQUIRE_INIT(); window->cursor = cursor; - _glfwPlatformSetCursor(window, cursor); + _glfw.platform.setCursor(window, cursor); } -GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun) +GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow *handle, GLFWkeyfun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.key, cbfun); + _GLFW_SWAP(GLFWkeyfun, window->callbacks.key, cbfun); return cbfun; } -GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun) +GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow *handle, GLFWcharfun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.character, cbfun); + _GLFW_SWAP(GLFWcharfun, window->callbacks.character, cbfun); return cbfun; } -GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmodsfun cbfun) +GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow *handle, GLFWcharmodsfun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.charmods, cbfun); + _GLFW_SWAP(GLFWcharmodsfun, window->callbacks.charmods, cbfun); return cbfun; } -GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle, +GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow *handle, GLFWmousebuttonfun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.mouseButton, cbfun); + _GLFW_SWAP(GLFWmousebuttonfun, window->callbacks.mouseButton, cbfun); return cbfun; } -GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle, +GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow *handle, GLFWcursorposfun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.cursorPos, cbfun); + _GLFW_SWAP(GLFWcursorposfun, window->callbacks.cursorPos, cbfun); return cbfun; } -GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* handle, +GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow *handle, GLFWcursorenterfun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.cursorEnter, cbfun); + _GLFW_SWAP(GLFWcursorenterfun, window->callbacks.cursorEnter, cbfun); return cbfun; } -GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle, +GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow *handle, GLFWscrollfun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.scroll, cbfun); + _GLFW_SWAP(GLFWscrollfun, window->callbacks.scroll, cbfun); return cbfun; } -GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun) +GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow *handle, GLFWdropfun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.drop, cbfun); + _GLFW_SWAP(GLFWdropfun, window->callbacks.drop, cbfun); return cbfun; } GLFWAPI int glfwJoystickPresent(int jid) { - _GLFWjoystick* js; + _GLFWjoystick *js; assert(jid >= GLFW_JOYSTICK_1); assert(jid <= GLFW_JOYSTICK_LAST); @@ -1003,15 +1102,15 @@ GLFWAPI int glfwJoystickPresent(int jid) return GLFW_FALSE; js = _glfw.joysticks + jid; - if (!js->present) + if (!js->connected) return GLFW_FALSE; - return _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE); + return _glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE); } -GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count) +GLFWAPI const float *glfwGetJoystickAxes(int jid, int *count) { - _GLFWjoystick* js; + _GLFWjoystick *js; assert(jid >= GLFW_JOYSTICK_1); assert(jid <= GLFW_JOYSTICK_LAST); @@ -1031,19 +1130,19 @@ GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count) return NULL; js = _glfw.joysticks + jid; - if (!js->present) + if (!js->connected) return NULL; - if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_AXES)) + if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_AXES)) return NULL; *count = js->axisCount; return js->axes; } -GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count) +GLFWAPI const unsigned char *glfwGetJoystickButtons(int jid, int *count) { - _GLFWjoystick* js; + _GLFWjoystick *js; assert(jid >= GLFW_JOYSTICK_1); assert(jid <= GLFW_JOYSTICK_LAST); @@ -1063,10 +1162,10 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count) return NULL; js = _glfw.joysticks + jid; - if (!js->present) + if (!js->connected) return NULL; - if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS)) + if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_BUTTONS)) return NULL; if (_glfw.hints.init.hatButtons) @@ -1077,9 +1176,9 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count) return js->buttons; } -GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count) +GLFWAPI const unsigned char *glfwGetJoystickHats(int jid, int *count) { - _GLFWjoystick* js; + _GLFWjoystick *js; assert(jid >= GLFW_JOYSTICK_1); assert(jid <= GLFW_JOYSTICK_LAST); @@ -1099,19 +1198,19 @@ GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count) return NULL; js = _glfw.joysticks + jid; - if (!js->present) + if (!js->connected) return NULL; - if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS)) + if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_BUTTONS)) return NULL; *count = js->hatCount; return js->hats; } -GLFWAPI const char* glfwGetJoystickName(int jid) +GLFWAPI const char *glfwGetJoystickName(int jid) { - _GLFWjoystick* js; + _GLFWjoystick *js; assert(jid >= GLFW_JOYSTICK_1); assert(jid <= GLFW_JOYSTICK_LAST); @@ -1128,18 +1227,18 @@ GLFWAPI const char* glfwGetJoystickName(int jid) return NULL; js = _glfw.joysticks + jid; - if (!js->present) + if (!js->connected) return NULL; - if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE)) + if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE)) return NULL; return js->name; } -GLFWAPI const char* glfwGetJoystickGUID(int jid) +GLFWAPI const char *glfwGetJoystickGUID(int jid) { - _GLFWjoystick* js; + _GLFWjoystick *js; assert(jid >= GLFW_JOYSTICK_1); assert(jid <= GLFW_JOYSTICK_LAST); @@ -1156,18 +1255,18 @@ GLFWAPI const char* glfwGetJoystickGUID(int jid) return NULL; js = _glfw.joysticks + jid; - if (!js->present) + if (!js->connected) return NULL; - if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE)) + if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE)) return NULL; return js->guid; } -GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer) +GLFWAPI void glfwSetJoystickUserPointer(int jid, void *pointer) { - _GLFWjoystick* js; + _GLFWjoystick *js; assert(jid >= GLFW_JOYSTICK_1); assert(jid <= GLFW_JOYSTICK_LAST); @@ -1175,15 +1274,15 @@ GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer) _GLFW_REQUIRE_INIT(); js = _glfw.joysticks + jid; - if (!js->present) + if (!js->allocated) return; js->userPointer = pointer; } -GLFWAPI void* glfwGetJoystickUserPointer(int jid) +GLFWAPI void *glfwGetJoystickUserPointer(int jid) { - _GLFWjoystick* js; + _GLFWjoystick *js; assert(jid >= GLFW_JOYSTICK_1); assert(jid <= GLFW_JOYSTICK_LAST); @@ -1191,7 +1290,7 @@ GLFWAPI void* glfwGetJoystickUserPointer(int jid) _GLFW_REQUIRE_INIT_OR_RETURN(NULL); js = _glfw.joysticks + jid; - if (!js->present) + if (!js->allocated) return NULL; return js->userPointer; @@ -1204,7 +1303,7 @@ GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun) if (!initJoysticks()) return NULL; - _GLFW_SWAP_POINTERS(_glfw.callbacks.joystick, cbfun); + _GLFW_SWAP(GLFWjoystickfun, _glfw.callbacks.joystick, cbfun); return cbfun; } @@ -1236,11 +1335,10 @@ GLFWAPI GLFWjoystickhatfun glfwSetJoystickHatCallback(GLFWjoystickhatfun cbfun) return cbfun; } - -GLFWAPI int glfwUpdateGamepadMappings(const char* string) +GLFWAPI int glfwUpdateGamepadMappings(const char *string) { int jid; - const char* c = string; + const char *c = string; assert(string != NULL); @@ -1264,7 +1362,7 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string) if (parseMapping(&mapping, line)) { - _GLFWmapping* previous = findMapping(mapping.guid); + _GLFWmapping *previous = findMapping(mapping.guid); if (previous) *previous = mapping; else @@ -1287,10 +1385,10 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string) } } - for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) + for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) { - _GLFWjoystick* js = _glfw.joysticks + jid; - if (js->present) + _GLFWjoystick *js = _glfw.joysticks + jid; + if (js->connected) js->mapping = findValidMapping(js); } @@ -1299,7 +1397,7 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string) GLFWAPI int glfwJoystickIsGamepad(int jid) { - _GLFWjoystick* js; + _GLFWjoystick *js; assert(jid >= GLFW_JOYSTICK_1); assert(jid <= GLFW_JOYSTICK_LAST); @@ -1316,18 +1414,18 @@ GLFWAPI int glfwJoystickIsGamepad(int jid) return GLFW_FALSE; js = _glfw.joysticks + jid; - if (!js->present) + if (!js->connected) return GLFW_FALSE; - if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE)) + if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE)) return GLFW_FALSE; return js->mapping != NULL; } -GLFWAPI const char* glfwGetGamepadName(int jid) +GLFWAPI const char *glfwGetGamepadName(int jid) { - _GLFWjoystick* js; + _GLFWjoystick *js; assert(jid >= GLFW_JOYSTICK_1); assert(jid <= GLFW_JOYSTICK_LAST); @@ -1344,10 +1442,10 @@ GLFWAPI const char* glfwGetGamepadName(int jid) return NULL; js = _glfw.joysticks + jid; - if (!js->present) + if (!js->connected) return NULL; - if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE)) + if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE)) return NULL; if (!js->mapping) @@ -1356,10 +1454,10 @@ GLFWAPI const char* glfwGetGamepadName(int jid) return js->mapping->name; } -GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state) +GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate *state) { int i; - _GLFWjoystick* js; + _GLFWjoystick *js; assert(jid >= GLFW_JOYSTICK_1); assert(jid <= GLFW_JOYSTICK_LAST); @@ -1379,18 +1477,18 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state) return GLFW_FALSE; js = _glfw.joysticks + jid; - if (!js->present) + if (!js->connected) return GLFW_FALSE; - if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_ALL)) + if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_ALL)) return GLFW_FALSE; if (!js->mapping) return GLFW_FALSE; - for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++) + for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++) { - const _GLFWmapelement* e = js->mapping->buttons + i; + const _GLFWmapelement *e = js->mapping->buttons + i; if (e->type == _GLFW_JOYSTICK_AXIS) { const float value = js->axes[e->index] * e->axisScale + e->axisOffset; @@ -1418,9 +1516,9 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state) state->buttons[i] = js->buttons[e->index]; } - for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++) + for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++) { - const _GLFWmapelement* e = js->mapping->axes + i; + const _GLFWmapelement *e = js->mapping->axes + i; if (e->type == _GLFW_JOYSTICK_AXIS) { const float value = js->axes[e->index] * e->axisScale + e->axisOffset; @@ -1442,25 +1540,25 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state) return GLFW_TRUE; } -GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string) +GLFWAPI void glfwSetClipboardString(GLFWwindow *handle, const char *string) { assert(string != NULL); _GLFW_REQUIRE_INIT(); - _glfwPlatformSetClipboardString(string); + _glfw.platform.setClipboardString(string); } -GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle) +GLFWAPI const char *glfwGetClipboardString(GLFWwindow *handle) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - return _glfwPlatformGetClipboardString(); + return _glfw.platform.getClipboardString(); } GLFWAPI double glfwGetTime(void) { _GLFW_REQUIRE_INIT_OR_RETURN(0.0); - return (double) (_glfwPlatformGetTimerValue() - _glfw.timer.offset) / - _glfwPlatformGetTimerFrequency(); + return (double)(_glfwPlatformGetTimerValue() - _glfw.timer.offset) / + _glfwPlatformGetTimerFrequency(); } GLFWAPI void glfwSetTime(double time) @@ -1474,7 +1572,7 @@ GLFWAPI void glfwSetTime(double time) } _glfw.timer.offset = _glfwPlatformGetTimerValue() - - (uint64_t) (time * _glfwPlatformGetTimerFrequency()); + (uint64_t)(time * _glfwPlatformGetTimerFrequency()); } GLFWAPI uint64_t glfwGetTimerValue(void) diff --git a/src/internal.h b/src/internal.h index 3c19a950..7aafd904 100644 --- a/src/internal.h +++ b/src/internal.h @@ -59,6 +59,7 @@ #define _GLFW_MESSAGE_SIZE 1024 typedef int GLFWbool; +typedef void (*GLFWproc)(void); typedef struct _GLFWerror _GLFWerror; typedef struct _GLFWinitconfig _GLFWinitconfig; @@ -67,6 +68,7 @@ typedef struct _GLFWctxconfig _GLFWctxconfig; typedef struct _GLFWfbconfig _GLFWfbconfig; typedef struct _GLFWcontext _GLFWcontext; typedef struct _GLFWwindow _GLFWwindow; +typedef struct _GLFWplatform _GLFWplatform; typedef struct _GLFWlibrary _GLFWlibrary; typedef struct _GLFWmonitor _GLFWmonitor; typedef struct _GLFWcursor _GLFWcursor; @@ -76,13 +78,6 @@ typedef struct _GLFWjoystick _GLFWjoystick; typedef struct _GLFWtls _GLFWtls; typedef struct _GLFWmutex _GLFWmutex; -typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*); -typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*); -typedef void (* _GLFWswapintervalfun)(int); -typedef int (* _GLFWextensionsupportedfun)(const char*); -typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*); -typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*); - #define GL_VERSION 0x1f02 #define GL_NONE 0 #define GL_COLOR_BUFFER_BIT 0x00004000 @@ -113,6 +108,165 @@ typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGPROC)(GLenum); typedef void (APIENTRY * PFNGLGETINTEGERVPROC)(GLenum,GLint*); typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint); +#if defined(_GLFW_WIN32) + #define EGLAPIENTRY __stdcall +#else + #define EGLAPIENTRY +#endif + +#define EGL_SUCCESS 0x3000 +#define EGL_NOT_INITIALIZED 0x3001 +#define EGL_BAD_ACCESS 0x3002 +#define EGL_BAD_ALLOC 0x3003 +#define EGL_BAD_ATTRIBUTE 0x3004 +#define EGL_BAD_CONFIG 0x3005 +#define EGL_BAD_CONTEXT 0x3006 +#define EGL_BAD_CURRENT_SURFACE 0x3007 +#define EGL_BAD_DISPLAY 0x3008 +#define EGL_BAD_MATCH 0x3009 +#define EGL_BAD_NATIVE_PIXMAP 0x300a +#define EGL_BAD_NATIVE_WINDOW 0x300b +#define EGL_BAD_PARAMETER 0x300c +#define EGL_BAD_SURFACE 0x300d +#define EGL_CONTEXT_LOST 0x300e +#define EGL_COLOR_BUFFER_TYPE 0x303f +#define EGL_RGB_BUFFER 0x308e +#define EGL_SURFACE_TYPE 0x3033 +#define EGL_WINDOW_BIT 0x0004 +#define EGL_RENDERABLE_TYPE 0x3040 +#define EGL_OPENGL_ES_BIT 0x0001 +#define EGL_OPENGL_ES2_BIT 0x0004 +#define EGL_OPENGL_BIT 0x0008 +#define EGL_ALPHA_SIZE 0x3021 +#define EGL_BLUE_SIZE 0x3022 +#define EGL_GREEN_SIZE 0x3023 +#define EGL_RED_SIZE 0x3024 +#define EGL_DEPTH_SIZE 0x3025 +#define EGL_STENCIL_SIZE 0x3026 +#define EGL_SAMPLES 0x3031 +#define EGL_OPENGL_ES_API 0x30a0 +#define EGL_OPENGL_API 0x30a2 +#define EGL_NONE 0x3038 +#define EGL_RENDER_BUFFER 0x3086 +#define EGL_SINGLE_BUFFER 0x3085 +#define EGL_EXTENSIONS 0x3055 +#define EGL_CONTEXT_CLIENT_VERSION 0x3098 +#define EGL_NATIVE_VISUAL_ID 0x302e +#define EGL_NO_SURFACE ((EGLSurface) 0) +#define EGL_NO_DISPLAY ((EGLDisplay) 0) +#define EGL_NO_CONTEXT ((EGLContext) 0) +#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType) 0) + +#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 +#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 +#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002 +#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001 +#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31bd +#define EGL_NO_RESET_NOTIFICATION_KHR 0x31be +#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31bf +#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004 +#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098 +#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30fb +#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30fd +#define EGL_CONTEXT_FLAGS_KHR 0x30fc +#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3 +#define EGL_GL_COLORSPACE_KHR 0x309d +#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089 +#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097 +#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0 +#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098 +#define EGL_PLATFORM_X11_EXT 0x31d5 +#define EGL_PLATFORM_WAYLAND_EXT 0x31d8 +#define EGL_PRESENT_OPAQUE_EXT 0x31df +#define EGL_PLATFORM_ANGLE_ANGLE 0x3202 +#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203 +#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320d +#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320e +#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207 +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208 +#define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450 +#define EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE 0x3489 +#define EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE 0x348f + +typedef int EGLint; +typedef unsigned int EGLBoolean; +typedef unsigned int EGLenum; +typedef void* EGLConfig; +typedef void* EGLContext; +typedef void* EGLDisplay; +typedef void* EGLSurface; + +typedef void* EGLNativeDisplayType; +typedef void* EGLNativeWindowType; + +// EGL function pointer typedefs +typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*); +typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigs)(EGLDisplay,EGLConfig*,EGLint,EGLint*); +typedef EGLDisplay (EGLAPIENTRY * PFN_eglGetDisplay)(EGLNativeDisplayType); +typedef EGLint (EGLAPIENTRY * PFN_eglGetError)(void); +typedef EGLBoolean (EGLAPIENTRY * PFN_eglInitialize)(EGLDisplay,EGLint*,EGLint*); +typedef EGLBoolean (EGLAPIENTRY * PFN_eglTerminate)(EGLDisplay); +typedef EGLBoolean (EGLAPIENTRY * PFN_eglBindAPI)(EGLenum); +typedef EGLContext (EGLAPIENTRY * PFN_eglCreateContext)(EGLDisplay,EGLConfig,EGLContext,const EGLint*); +typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroySurface)(EGLDisplay,EGLSurface); +typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext); +typedef EGLSurface (EGLAPIENTRY * PFN_eglCreateWindowSurface)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*); +typedef EGLBoolean (EGLAPIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLSurface,EGLContext); +typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface); +typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint); +typedef const char* (EGLAPIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint); +typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*); +#define eglGetConfigAttrib _glfw.egl.GetConfigAttrib +#define eglGetConfigs _glfw.egl.GetConfigs +#define eglGetDisplay _glfw.egl.GetDisplay +#define eglGetError _glfw.egl.GetError +#define eglInitialize _glfw.egl.Initialize +#define eglTerminate _glfw.egl.Terminate +#define eglBindAPI _glfw.egl.BindAPI +#define eglCreateContext _glfw.egl.CreateContext +#define eglDestroySurface _glfw.egl.DestroySurface +#define eglDestroyContext _glfw.egl.DestroyContext +#define eglCreateWindowSurface _glfw.egl.CreateWindowSurface +#define eglMakeCurrent _glfw.egl.MakeCurrent +#define eglSwapBuffers _glfw.egl.SwapBuffers +#define eglSwapInterval _glfw.egl.SwapInterval +#define eglQueryString _glfw.egl.QueryString +#define eglGetProcAddress _glfw.egl.GetProcAddress + +typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum,void*,const EGLint*); +typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)(EGLDisplay,EGLConfig,void*,const EGLint*); +#define eglGetPlatformDisplayEXT _glfw.egl.GetPlatformDisplayEXT +#define eglCreatePlatformWindowSurfaceEXT _glfw.egl.CreatePlatformWindowSurfaceEXT + +#define OSMESA_RGBA 0x1908 +#define OSMESA_FORMAT 0x22 +#define OSMESA_DEPTH_BITS 0x30 +#define OSMESA_STENCIL_BITS 0x31 +#define OSMESA_ACCUM_BITS 0x32 +#define OSMESA_PROFILE 0x33 +#define OSMESA_CORE_PROFILE 0x34 +#define OSMESA_COMPAT_PROFILE 0x35 +#define OSMESA_CONTEXT_MAJOR_VERSION 0x36 +#define OSMESA_CONTEXT_MINOR_VERSION 0x37 + +typedef void* OSMesaContext; +typedef void (*OSMESAproc)(void); + +typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextExt)(GLenum,GLint,GLint,GLint,OSMesaContext); +typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextAttribs)(const int*,OSMesaContext); +typedef void (GLAPIENTRY * PFN_OSMesaDestroyContext)(OSMesaContext); +typedef int (GLAPIENTRY * PFN_OSMesaMakeCurrent)(OSMesaContext,void*,int,int,int); +typedef int (GLAPIENTRY * PFN_OSMesaGetColorBuffer)(OSMesaContext,int*,int*,int*,void**); +typedef int (GLAPIENTRY * PFN_OSMesaGetDepthBuffer)(OSMesaContext,int*,int*,int*,void**); +typedef GLFWglproc (GLAPIENTRY * PFN_OSMesaGetProcAddress)(const char*); +#define OSMesaCreateContextExt _glfw.osmesa.CreateContextExt +#define OSMesaCreateContextAttribs _glfw.osmesa.CreateContextAttribs +#define OSMesaDestroyContext _glfw.osmesa.DestroyContext +#define OSMesaMakeCurrent _glfw.osmesa.MakeCurrent +#define OSMesaGetColorBuffer _glfw.osmesa.GetColorBuffer +#define OSMesaGetDepthBuffer _glfw.osmesa.GetDepthBuffer +#define OSMesaGetProcAddress _glfw.osmesa.GetProcAddress + #define VK_NULL_HANDLE 0 typedef void* VkInstance; @@ -170,39 +324,11 @@ typedef struct VkExtensionProperties typedef void (APIENTRY * PFN_vkVoidFunction)(void); -#if defined(_GLFW_VULKAN_STATIC) - PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance,const char*); - VkResult vkEnumerateInstanceExtensionProperties(const char*,uint32_t*,VkExtensionProperties*); -#else - typedef PFN_vkVoidFunction (APIENTRY * PFN_vkGetInstanceProcAddr)(VkInstance,const char*); - typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const char*,uint32_t*,VkExtensionProperties*); - #define vkEnumerateInstanceExtensionProperties _glfw.vk.EnumerateInstanceExtensionProperties - #define vkGetInstanceProcAddr _glfw.vk.GetInstanceProcAddr -#endif +typedef PFN_vkVoidFunction (APIENTRY * PFN_vkGetInstanceProcAddr)(VkInstance,const char*); +typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const char*,uint32_t*,VkExtensionProperties*); +#define vkGetInstanceProcAddr _glfw.vk.GetInstanceProcAddr -#if defined(_GLFW_COCOA) - #include "cocoa_platform.h" -#elif defined(_GLFW_WIN32) - #include "win32_platform.h" -#elif defined(_GLFW_X11) - #include "x11_platform.h" -#elif defined(_GLFW_WAYLAND) - #include "wl_platform.h" -#elif defined(_GLFW_OSMESA) - #include "null_platform.h" -#else - #error "No supported window creation API selected" -#endif - -#include "egl_context.h" -#include "osmesa_context.h" - -// Constructs a version number string from the public header macros -#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r -#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r) -#define _GLFW_VERSION_NUMBER _GLFW_MAKE_VERSION(GLFW_VERSION_MAJOR, \ - GLFW_VERSION_MINOR, \ - GLFW_VERSION_REVISION) +#include "platform.h" // Checks for whether the library has been initialized #define _GLFW_REQUIRE_INIT() \ @@ -219,12 +345,12 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void); } // Swaps the provided pointers -#define _GLFW_SWAP_POINTERS(x, y) \ - { \ - void* t; \ - t = x; \ - x = y; \ - y = t; \ +#define _GLFW_SWAP(type, x, y) \ + { \ + type t; \ + t = x; \ + x = y; \ + y = t; \ } // Per-thread error structure @@ -244,6 +370,8 @@ struct _GLFWinitconfig { GLFWbool hatButtons; int angleType; + int platformID; + PFN_vkGetInstanceProcAddr vulkanLoader; struct { GLFWbool menubar; GLFWbool chdir; @@ -261,6 +389,8 @@ struct _GLFWinitconfig // struct _GLFWwndconfig { + int xpos; + int ypos; int width; int height; const char* title; @@ -286,6 +416,9 @@ struct _GLFWwndconfig struct { GLFWbool keymenu; } win32; + struct { + char appId[256]; + } wl; }; // Context configuration @@ -357,19 +490,29 @@ struct _GLFWcontext PFNGLGETINTEGERVPROC GetIntegerv; PFNGLGETSTRINGPROC GetString; - _GLFWmakecontextcurrentfun makeCurrent; - _GLFWswapbuffersfun swapBuffers; - _GLFWswapintervalfun swapInterval; - _GLFWextensionsupportedfun extensionSupported; - _GLFWgetprocaddressfun getProcAddress; - _GLFWdestroycontextfun destroy; + void (*makeCurrent)(_GLFWwindow*); + void (*swapBuffers)(_GLFWwindow*); + void (*swapInterval)(int); + int (*extensionSupported)(const char*); + GLFWglproc (*getProcAddress)(const char*); + void (*destroy)(_GLFWwindow*); - // This is defined in the context API's context.h - _GLFW_PLATFORM_CONTEXT_STATE; - // This is defined in egl_context.h - _GLFWcontextEGL egl; - // This is defined in osmesa_context.h - _GLFWcontextOSMesa osmesa; + struct { + EGLConfig config; + EGLContext handle; + EGLSurface surface; + void* client; + } egl; + + struct { + OSMesaContext handle; + int width; + int height; + void* buffer; + } osmesa; + + // This is defined in platform.h + GLFW_PLATFORM_CONTEXT_STATE }; // Window and context structure @@ -428,8 +571,8 @@ struct _GLFWwindow GLFWdropfun drop; } callbacks; - // This is defined in the window API's platform.h - _GLFW_PLATFORM_WINDOW_STATE; + // This is defined in platform.h + GLFW_PLATFORM_WINDOW_STATE }; // Monitor structure @@ -452,8 +595,8 @@ struct _GLFWmonitor GLFWgammaramp originalRamp; GLFWgammaramp currentRamp; - // This is defined in the window API's platform.h - _GLFW_PLATFORM_MONITOR_STATE; + // This is defined in platform.h + GLFW_PLATFORM_MONITOR_STATE }; // Cursor structure @@ -461,9 +604,8 @@ struct _GLFWmonitor struct _GLFWcursor { _GLFWcursor* next; - - // This is defined in the window API's platform.h - _GLFW_PLATFORM_CURSOR_STATE; + // This is defined in platform.h + GLFW_PLATFORM_CURSOR_STATE }; // Gamepad mapping element structure @@ -490,7 +632,8 @@ struct _GLFWmapping // struct _GLFWjoystick { - GLFWbool present; + GLFWbool allocated; + GLFWbool connected; float* axes; int axisCount; unsigned char* buttons; @@ -502,24 +645,108 @@ struct _GLFWjoystick char guid[33]; _GLFWmapping* mapping; - // This is defined in the joystick API's joystick.h - _GLFW_PLATFORM_JOYSTICK_STATE; + // This is defined in platform.h + GLFW_PLATFORM_JOYSTICK_STATE }; // Thread local storage structure // struct _GLFWtls { - // This is defined in the platform's thread.h - _GLFW_PLATFORM_TLS_STATE; + // This is defined in platform.h + GLFW_PLATFORM_TLS_STATE }; // Mutex structure // struct _GLFWmutex { - // This is defined in the platform's thread.h - _GLFW_PLATFORM_MUTEX_STATE; + // This is defined in platform.h + GLFW_PLATFORM_MUTEX_STATE +}; + +// Platform API structure +// +struct _GLFWplatform +{ + int platformID; + // init + GLFWbool (*init)(void); + void (*terminate)(void); + // input + void (*getCursorPos)(_GLFWwindow*,double*,double*); + void (*setCursorPos)(_GLFWwindow*,double,double); + void (*setCursorMode)(_GLFWwindow*,int); + void (*setRawMouseMotion)(_GLFWwindow*,GLFWbool); + GLFWbool (*rawMouseMotionSupported)(void); + GLFWbool (*createCursor)(_GLFWcursor*,const GLFWimage*,int,int); + GLFWbool (*createStandardCursor)(_GLFWcursor*,int); + void (*destroyCursor)(_GLFWcursor*); + void (*setCursor)(_GLFWwindow*,_GLFWcursor*); + const char* (*getScancodeName)(int); + int (*getKeyScancode)(int); + void (*setClipboardString)(const char*); + const char* (*getClipboardString)(void); + GLFWbool (*initJoysticks)(void); + void (*terminateJoysticks)(void); + GLFWbool (*pollJoystick)(_GLFWjoystick*,int); + const char* (*getMappingName)(void); + void (*updateGamepadGUID)(char*); + // monitor + void (*freeMonitor)(_GLFWmonitor*); + void (*getMonitorPos)(_GLFWmonitor*,int*,int*); + void (*getMonitorContentScale)(_GLFWmonitor*,float*,float*); + void (*getMonitorWorkarea)(_GLFWmonitor*,int*,int*,int*,int*); + GLFWvidmode* (*getVideoModes)(_GLFWmonitor*,int*); + void (*getVideoMode)(_GLFWmonitor*,GLFWvidmode*); + GLFWbool (*getGammaRamp)(_GLFWmonitor*,GLFWgammaramp*); + void (*setGammaRamp)(_GLFWmonitor*,const GLFWgammaramp*); + // window + GLFWbool (*createWindow)(_GLFWwindow*,const _GLFWwndconfig*,const _GLFWctxconfig*,const _GLFWfbconfig*); + void (*destroyWindow)(_GLFWwindow*); + void (*setWindowTitle)(_GLFWwindow*,const char*); + void (*setWindowIcon)(_GLFWwindow*,int,const GLFWimage*); + void (*getWindowPos)(_GLFWwindow*,int*,int*); + void (*setWindowPos)(_GLFWwindow*,int,int); + void (*getWindowSize)(_GLFWwindow*,int*,int*); + void (*setWindowSize)(_GLFWwindow*,int,int); + void (*setWindowSizeLimits)(_GLFWwindow*,int,int,int,int); + void (*setWindowAspectRatio)(_GLFWwindow*,int,int); + void (*getFramebufferSize)(_GLFWwindow*,int*,int*); + void (*getWindowFrameSize)(_GLFWwindow*,int*,int*,int*,int*); + void (*getWindowContentScale)(_GLFWwindow*,float*,float*); + void (*iconifyWindow)(_GLFWwindow*); + void (*restoreWindow)(_GLFWwindow*); + void (*maximizeWindow)(_GLFWwindow*); + void (*showWindow)(_GLFWwindow*); + void (*hideWindow)(_GLFWwindow*); + void (*requestWindowAttention)(_GLFWwindow*); + void (*focusWindow)(_GLFWwindow*); + void (*setWindowMonitor)(_GLFWwindow*,_GLFWmonitor*,int,int,int,int,int); + GLFWbool (*windowFocused)(_GLFWwindow*); + GLFWbool (*windowIconified)(_GLFWwindow*); + GLFWbool (*windowVisible)(_GLFWwindow*); + GLFWbool (*windowMaximized)(_GLFWwindow*); + GLFWbool (*windowHovered)(_GLFWwindow*); + GLFWbool (*framebufferTransparent)(_GLFWwindow*); + float (*getWindowOpacity)(_GLFWwindow*); + void (*setWindowResizable)(_GLFWwindow*,GLFWbool); + void (*setWindowDecorated)(_GLFWwindow*,GLFWbool); + void (*setWindowFloating)(_GLFWwindow*,GLFWbool); + void (*setWindowOpacity)(_GLFWwindow*,float); + void (*setWindowMousePassthrough)(_GLFWwindow*,GLFWbool); + void (*pollEvents)(void); + void (*waitEvents)(void); + void (*waitEventsTimeout)(double); + void (*postEmptyEvent)(void); + // EGL + EGLenum (*getEGLPlatform)(EGLint**); + EGLNativeDisplayType (*getEGLNativeDisplay)(void); + EGLNativeWindowType (*getEGLNativeWindow)(_GLFWwindow*); + // vulkan + void (*getRequiredInstanceExtensions)(char**); + GLFWbool (*getPhysicalDevicePresentationSupport)(VkInstance,VkPhysicalDevice,uint32_t); + VkResult (*createWindowSurface)(VkInstance,_GLFWwindow*,const VkAllocationCallbacks*,VkSurfaceKHR*); }; // Library global data @@ -529,6 +756,8 @@ struct _GLFWlibrary GLFWbool initialized; GLFWallocator allocator; + _GLFWplatform platform; + struct { _GLFWinitconfig init; _GLFWfbconfig framebuffer; @@ -555,30 +784,80 @@ struct _GLFWlibrary struct { uint64_t offset; - // This is defined in the platform's time.h - _GLFW_PLATFORM_LIBRARY_TIMER_STATE; + // This is defined in platform.h + GLFW_PLATFORM_LIBRARY_TIMER_STATE } timer; + struct { + EGLenum platform; + EGLDisplay display; + EGLint major, minor; + GLFWbool prefix; + + GLFWbool KHR_create_context; + GLFWbool KHR_create_context_no_error; + GLFWbool KHR_gl_colorspace; + GLFWbool KHR_get_all_proc_addresses; + GLFWbool KHR_context_flush_control; + GLFWbool EXT_client_extensions; + GLFWbool EXT_platform_base; + GLFWbool EXT_platform_x11; + GLFWbool EXT_platform_wayland; + GLFWbool EXT_present_opaque; + GLFWbool ANGLE_platform_angle; + GLFWbool ANGLE_platform_angle_opengl; + GLFWbool ANGLE_platform_angle_d3d; + GLFWbool ANGLE_platform_angle_vulkan; + GLFWbool ANGLE_platform_angle_metal; + + void* handle; + + PFN_eglGetConfigAttrib GetConfigAttrib; + PFN_eglGetConfigs GetConfigs; + PFN_eglGetDisplay GetDisplay; + PFN_eglGetError GetError; + PFN_eglInitialize Initialize; + PFN_eglTerminate Terminate; + PFN_eglBindAPI BindAPI; + PFN_eglCreateContext CreateContext; + PFN_eglDestroySurface DestroySurface; + PFN_eglDestroyContext DestroyContext; + PFN_eglCreateWindowSurface CreateWindowSurface; + PFN_eglMakeCurrent MakeCurrent; + PFN_eglSwapBuffers SwapBuffers; + PFN_eglSwapInterval SwapInterval; + PFN_eglQueryString QueryString; + PFN_eglGetProcAddress GetProcAddress; + + PFNEGLGETPLATFORMDISPLAYEXTPROC GetPlatformDisplayEXT; + PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC CreatePlatformWindowSurfaceEXT; + } egl; + + struct { + void* handle; + + PFN_OSMesaCreateContextExt CreateContextExt; + PFN_OSMesaCreateContextAttribs CreateContextAttribs; + PFN_OSMesaDestroyContext DestroyContext; + PFN_OSMesaMakeCurrent MakeCurrent; + PFN_OSMesaGetColorBuffer GetColorBuffer; + PFN_OSMesaGetDepthBuffer GetDepthBuffer; + PFN_OSMesaGetProcAddress GetProcAddress; + + } osmesa; + struct { GLFWbool available; void* handle; char* extensions[2]; -#if !defined(_GLFW_VULKAN_STATIC) - PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties; PFN_vkGetInstanceProcAddr GetInstanceProcAddr; -#endif GLFWbool KHR_surface; -#if defined(_GLFW_WIN32) GLFWbool KHR_win32_surface; -#elif defined(_GLFW_COCOA) GLFWbool MVK_macos_surface; GLFWbool EXT_metal_surface; -#elif defined(_GLFW_X11) GLFWbool KHR_xlib_surface; GLFWbool KHR_xcb_surface; -#elif defined(_GLFW_WAYLAND) GLFWbool KHR_wayland_surface; -#endif } vk; struct { @@ -590,16 +869,10 @@ struct _GLFWlibrary GLFWgamepadstatefun gamepad_state; } callbacks; - // This is defined in the window API's platform.h - _GLFW_PLATFORM_LIBRARY_WINDOW_STATE; - // This is defined in the context API's context.h - _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE; - // This is defined in the platform's joystick.h - _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE; - // This is defined in egl_context.h - _GLFWlibraryEGL egl; - // This is defined in osmesa_context.h - _GLFWlibraryOSMesa osmesa; + // These are defined in platform.h + GLFW_PLATFORM_LIBRARY_WINDOW_STATE + GLFW_PLATFORM_LIBRARY_CONTEXT_STATE + GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE }; // Global state shared between compilation units of GLFW @@ -611,108 +884,10 @@ extern _GLFWlibrary _glfw; ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -int _glfwPlatformInit(void); -void _glfwPlatformTerminate(void); -const char* _glfwPlatformGetVersionString(void); - -void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos); -void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos); -void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode); -void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled); -GLFWbool _glfwPlatformRawMouseMotionSupported(void); -int _glfwPlatformCreateCursor(_GLFWcursor* cursor, - const GLFWimage* image, int xhot, int yhot); -int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape); -void _glfwPlatformDestroyCursor(_GLFWcursor* cursor); -void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor); - -const char* _glfwPlatformGetScancodeName(int scancode); -int _glfwPlatformGetKeyScancode(int key); - -void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor); -void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos); -void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, - float* xscale, float* yscale); -void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height); -GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count); -void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode); -GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp); -void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp); - -void _glfwPlatformSetClipboardString(const char* string); -const char* _glfwPlatformGetClipboardString(void); - -GLFWbool _glfwPlatformInitJoysticks(void); -void _glfwPlatformTerminateJoysticks(void); -int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode); -void _glfwPlatformUpdateGamepadGUID(char* guid); - +void _glfwPlatformInitTimer(void); uint64_t _glfwPlatformGetTimerValue(void); uint64_t _glfwPlatformGetTimerFrequency(void); -int _glfwPlatformCreateWindow(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig); -void _glfwPlatformDestroyWindow(_GLFWwindow* window); -void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title); -void _glfwPlatformSetWindowIcon(_GLFWwindow* window, - int count, const GLFWimage* images); -void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos); -void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos); -void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height); -void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height); -void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, - int minwidth, int minheight, - int maxwidth, int maxheight); -void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom); -void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height); -void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, - int* left, int* top, - int* right, int* bottom); -void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, - float* xscale, float* yscale); -void _glfwPlatformIconifyWindow(_GLFWwindow* window); -void _glfwPlatformRestoreWindow(_GLFWwindow* window); -void _glfwPlatformMaximizeWindow(_GLFWwindow* window); -void _glfwPlatformShowWindow(_GLFWwindow* window); -void _glfwPlatformHideWindow(_GLFWwindow* window); -void _glfwPlatformRequestWindowAttention(_GLFWwindow* window); -void _glfwPlatformFocusWindow(_GLFWwindow* window); -void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, - int xpos, int ypos, int width, int height, - int refreshRate); -int _glfwPlatformWindowFocused(_GLFWwindow* window); -int _glfwPlatformWindowIconified(_GLFWwindow* window); -int _glfwPlatformWindowVisible(_GLFWwindow* window); -int _glfwPlatformWindowMaximized(_GLFWwindow* window); -int _glfwPlatformWindowHovered(_GLFWwindow* window); -int _glfwPlatformFramebufferTransparent(_GLFWwindow* window); -float _glfwPlatformGetWindowOpacity(_GLFWwindow* window); -void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled); -void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled); -void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled); -void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled); -void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity); - -void _glfwPlatformPollEvents(void); -void _glfwPlatformWaitEvents(void); -void _glfwPlatformWaitEventsTimeout(double timeout); -void _glfwPlatformPostEmptyEvent(void); - -EGLenum _glfwPlatformGetEGLPlatform(EGLint** attribs); -EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void); -EGLNativeWindowType _glfwPlatformGetEGLNativeWindow(_GLFWwindow* window); - -void _glfwPlatformGetRequiredInstanceExtensions(char** extensions); -int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, - VkPhysicalDevice device, - uint32_t queuefamily); -VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, - _GLFWwindow* window, - const VkAllocationCallbacks* allocator, - VkSurfaceKHR* surface); - GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls); void _glfwPlatformDestroyTls(_GLFWtls* tls); void* _glfwPlatformGetTls(_GLFWtls* tls); @@ -723,6 +898,10 @@ void _glfwPlatformDestroyMutex(_GLFWmutex* mutex); void _glfwPlatformLockMutex(_GLFWmutex* mutex); void _glfwPlatformUnlockMutex(_GLFWmutex* mutex); +void* _glfwPlatformLoadModule(const char* path); +void _glfwPlatformFreeModule(void* module); +GLFWproc _glfwPlatformGetModuleSymbol(void* module, const char* name); + ////////////////////////////////////////////////////////////////////////// ////// GLFW event API ////// @@ -743,7 +922,7 @@ void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor); void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods); void _glfwInputChar(_GLFWwindow* window, - unsigned int codepoint, int mods, GLFWbool plain); + uint32_t codepoint, int mods, GLFWbool plain); void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset); void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods); void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos); @@ -769,6 +948,8 @@ void _glfwInputError(int code, const char* format, ...); ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// +GLFWbool _glfwSelectPlatform(int platformID, _GLFWplatform* platform); + GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions); const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, const _GLFWfbconfig* alternatives, @@ -796,11 +977,34 @@ void _glfwFreeJoystick(_GLFWjoystick* js); void _glfwCenterCursorInContentArea(_GLFWwindow* window); void _glfwPollAllJoysticks(); +GLFWbool _glfwInitEGL(void); +void _glfwTerminateEGL(void); +GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig); +#if defined(_GLFW_X11) +GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig, + Visual** visual, int* depth); +#endif /*_GLFW_X11*/ + +GLFWbool _glfwInitOSMesa(void); +void _glfwTerminateOSMesa(void); +GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig); + GLFWbool _glfwInitVulkan(int mode); void _glfwTerminateVulkan(void); const char* _glfwGetVulkanResultString(VkResult result); +size_t _glfwEncodeUTF8(char* s, uint32_t codepoint); +char** _glfwParseUriList(char* text, int* count); + char* _glfw_strdup(const char* source); +int _glfw_min(int a, int b); +int _glfw_max(int a, int b); float _glfw_fminf(float a, float b); float _glfw_fmaxf(float a, float b); diff --git a/src/linux_joystick.c b/src/linux_joystick.c index 122bc66a..26db853e 100644 --- a/src/linux_joystick.c +++ b/src/linux_joystick.c @@ -29,6 +29,8 @@ #include "internal.h" +#if defined(GLFW_BUILD_LINUX_JOYSTICK) + #include #include #include @@ -128,7 +130,7 @@ static GLFWbool openJoystickDevice(const char* path) { for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) { - if (!_glfw.joysticks[jid].present) + if (!_glfw.joysticks[jid].connected) continue; if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0) return GLFW_FALSE; @@ -157,7 +159,7 @@ static GLFWbool openJoystickDevice(const char* path) } // Ensure this device supports the events expected of a joystick - if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits)) + if (!isBitSet(EV_ABS, evBits)) { close(linjs.fd); return GLFW_FALSE; @@ -245,9 +247,9 @@ static GLFWbool openJoystickDevice(const char* path) // static void closeJoystick(_GLFWjoystick* js) { + _glfwInputJoystick(js, GLFW_DISCONNECTED); close(js->linjs.fd); _glfwFreeJoystick(js); - _glfwInputJoystick(js, GLFW_DISCONNECTED); } // Lexically compare joysticks by name; used by qsort @@ -307,7 +309,7 @@ void _glfwDetectJoystickConnectionLinux(void) ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -GLFWbool _glfwPlatformInitJoysticks(void) +GLFWbool _glfwInitJoysticksLinux(void) { const char* dirname = "/dev/input"; @@ -361,14 +363,12 @@ GLFWbool _glfwPlatformInitJoysticks(void) return GLFW_TRUE; } -void _glfwPlatformTerminateJoysticks(void) +void _glfwTerminateJoysticksLinux(void) { - int jid; - - for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) + for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) { _GLFWjoystick* js = _glfw.joysticks + jid; - if (js->present) + if (js->connected) closeJoystick(js); } @@ -382,7 +382,7 @@ void _glfwPlatformTerminateJoysticks(void) } } -int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) +GLFWbool _glfwPollJoystickLinux(_GLFWjoystick* js, int mode) { // Read all queued events (non-blocking) for (;;) @@ -419,10 +419,17 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) handleAbsEvent(js, e.code, e.value); } - return js->present; + return js->connected; } -void _glfwPlatformUpdateGamepadGUID(char* guid) +const char* _glfwGetMappingNameLinux(void) +{ + return "Linux"; +} + +void _glfwUpdateGamepadGUIDLinux(char* guid) { } +#endif // GLFW_BUILD_LINUX_JOYSTICK + diff --git a/src/linux_joystick.h b/src/linux_joystick.h index 1c3ca751..df605e72 100644 --- a/src/linux_joystick.h +++ b/src/linux_joystick.h @@ -28,11 +28,8 @@ #include #include -#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickLinux linjs -#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs - -#define _GLFW_PLATFORM_MAPPING_NAME "Linux" -#define GLFW_BUILD_LINUX_MAPPINGS +#define GLFW_LINUX_JOYSTICK_STATE _GLFWjoystickLinux linjs; +#define GLFW_LINUX_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs; // Linux-specific joystick data // @@ -58,3 +55,9 @@ typedef struct _GLFWlibraryLinux void _glfwDetectJoystickConnectionLinux(void); +GLFWbool _glfwInitJoysticksLinux(void); +void _glfwTerminateJoysticksLinux(void); +GLFWbool _glfwPollJoystickLinux(_GLFWjoystick* js, int mode); +const char* _glfwGetMappingNameLinux(void); +void _glfwUpdateGamepadGUIDLinux(char* guid); + diff --git a/src/mappings.h b/src/mappings.h index 553fe2a2..270fa4cd 100644 --- a/src/mappings.h +++ b/src/mappings.h @@ -60,7 +60,7 @@ const char* _glfwDefaultMappings[] = { -#if defined(GLFW_BUILD_WIN32_MAPPINGS) +#if defined(_GLFW_WIN32) "03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,", "03000000c82d00002038000000000000,8bitdo,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,", "03000000c82d00000951000000000000,8BitDo Dogbone Modkit,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,", @@ -426,9 +426,9 @@ const char* _glfwDefaultMappings[] = "78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", -#endif // GLFW_BUILD_WIN32_MAPPINGS +#endif // _GLFW_WIN32 -#if defined(GLFW_BUILD_COCOA_MAPPINGS) +#if defined(_GLFW_COCOA) "030000008f0e00000300000009010000,2In1 USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,", "03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,", "03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,", @@ -598,9 +598,9 @@ const char* _glfwDefaultMappings[] = "03000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,", "03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,", "03000000120c0000101e000000010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,", -#endif // GLFW_BUILD_COCOA_MAPPINGS +#endif // _GLFW_COCOA -#if defined(GLFW_BUILD_LINUX_MAPPINGS) +#if defined(GLFW_BUILD_LINUX_JOYSTICK) "03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,", "05000000c82d00001038000000010000,8Bitdo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,", "05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux,", @@ -996,6 +996,6 @@ const char* _glfwDefaultMappings[] = "03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,", "03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", "03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,", -#endif // GLFW_BUILD_LINUX_MAPPINGS +#endif // GLFW_BUILD_LINUX_JOYSTICK }; diff --git a/src/mappings.h.in b/src/mappings.h.in index f2604390..ed623680 100644 --- a/src/mappings.h.in +++ b/src/mappings.h.in @@ -60,7 +60,7 @@ const char* _glfwDefaultMappings[] = { -#if defined(GLFW_BUILD_WIN32_MAPPINGS) +#if defined(_GLFW_WIN32) @GLFW_WIN32_MAPPINGS@ "78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", @@ -69,14 +69,14 @@ const char* _glfwDefaultMappings[] = "78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", -#endif // GLFW_BUILD_WIN32_MAPPINGS +#endif // _GLFW_WIN32 -#if defined(GLFW_BUILD_COCOA_MAPPINGS) +#if defined(_GLFW_COCOA) @GLFW_COCOA_MAPPINGS@ -#endif // GLFW_BUILD_COCOA_MAPPINGS +#endif // _GLFW_COCOA -#if defined(GLFW_BUILD_LINUX_MAPPINGS) +#if defined(GLFW_BUILD_LINUX_JOYSTICK) @GLFW_LINUX_MAPPINGS@ -#endif // GLFW_BUILD_LINUX_MAPPINGS +#endif // GLFW_BUILD_LINUX_JOYSTICK }; diff --git a/src/monitor.c b/src/monitor.c index 938582b2..6429493b 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -74,7 +74,7 @@ static GLFWbool refreshVideoModes(_GLFWmonitor* monitor) if (monitor->modes) return GLFW_TRUE; - modes = _glfwPlatformGetVideoModes(monitor, &modeCount); + modes = _glfw.platform.getVideoModes(monitor, &modeCount); if (!modes) return GLFW_FALSE; @@ -96,6 +96,10 @@ static GLFWbool refreshVideoModes(_GLFWmonitor* monitor) // void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement) { + assert(monitor != NULL); + assert(action == GLFW_CONNECTED || action == GLFW_DISCONNECTED); + assert(placement == _GLFW_INSERT_FIRST || placement == _GLFW_INSERT_LAST); + if (action == GLFW_CONNECTED) { _glfw.monitorCount++; @@ -123,10 +127,10 @@ void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement) if (window->monitor == monitor) { int width, height, xoff, yoff; - _glfwPlatformGetWindowSize(window, &width, &height); - _glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0); - _glfwPlatformGetWindowFrameSize(window, &xoff, &yoff, NULL, NULL); - _glfwPlatformSetWindowPos(window, xoff, yoff); + _glfw.platform.getWindowSize(window, &width, &height); + _glfw.platform.setWindowMonitor(window, NULL, 0, 0, width, height, 0); + _glfw.platform.getWindowFrameSize(window, &xoff, &yoff, NULL, NULL); + _glfw.platform.setWindowPos(window, xoff, yoff); } } @@ -155,6 +159,7 @@ void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement) // void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window) { + assert(monitor != NULL); monitor->window = window; } @@ -183,7 +188,7 @@ void _glfwFreeMonitor(_GLFWmonitor* monitor) if (monitor == NULL) return; - _glfwPlatformFreeMonitor(monitor); + _glfw.platform.freeMonitor(monitor); _glfwFreeGammaArrays(&monitor->originalRamp); _glfwFreeGammaArrays(&monitor->currentRamp); @@ -332,7 +337,7 @@ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos) _GLFW_REQUIRE_INIT(); - _glfwPlatformGetMonitorPos(monitor, xpos, ypos); + _glfw.platform.getMonitorPos(monitor, xpos, ypos); } GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle, @@ -353,7 +358,7 @@ GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle, _GLFW_REQUIRE_INIT(); - _glfwPlatformGetMonitorWorkarea(monitor, xpos, ypos, width, height); + _glfw.platform.getMonitorWorkarea(monitor, xpos, ypos, width, height); } GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM) @@ -386,7 +391,7 @@ GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle, *yscale = 0.f; _GLFW_REQUIRE_INIT(); - _glfwPlatformGetMonitorContentScale(monitor, xscale, yscale); + _glfw.platform.getMonitorContentScale(monitor, xscale, yscale); } GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle) @@ -419,7 +424,7 @@ GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* handle) GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(_glfw.callbacks.monitor, cbfun); + _GLFW_SWAP(GLFWmonitorfun, _glfw.callbacks.monitor, cbfun); return cbfun; } @@ -447,7 +452,7 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle) _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _glfwPlatformGetVideoMode(monitor, &monitor->currentMode); + _glfw.platform.getVideoMode(monitor, &monitor->currentMode); return &monitor->currentMode; } @@ -506,7 +511,7 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle) _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _glfwFreeGammaArrays(&monitor->currentRamp); - if (!_glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp)) + if (!_glfw.platform.getGammaRamp(monitor, &monitor->currentRamp)) return NULL; return &monitor->currentRamp; @@ -522,6 +527,8 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp) assert(ramp->green != NULL); assert(ramp->blue != NULL); + _GLFW_REQUIRE_INIT(); + if (ramp->size <= 0) { _glfwInputError(GLFW_INVALID_VALUE, @@ -530,14 +537,12 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp) return; } - _GLFW_REQUIRE_INIT(); - if (!monitor->originalRamp.size) { - if (!_glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp)) + if (!_glfw.platform.getGammaRamp(monitor, &monitor->originalRamp)) return; } - _glfwPlatformSetGammaRamp(monitor, ramp); + _glfw.platform.setGammaRamp(monitor, ramp); } diff --git a/src/nsgl_context.h b/src/nsgl_context.h deleted file mode 100644 index 9c31436c..00000000 --- a/src/nsgl_context.h +++ /dev/null @@ -1,66 +0,0 @@ -//======================================================================== -// GLFW 3.4 macOS - www.glfw.org -//------------------------------------------------------------------------ -// Copyright (c) 2009-2019 Camilla Löwy -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would -// be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -// -//======================================================================== - -// NOTE: Many Cocoa enum values have been renamed and we need to build across -// SDK versions where one is unavailable or the other deprecated -// We use the newer names in code and these macros to handle compatibility -#if MAC_OS_X_VERSION_MAX_ALLOWED < 101400 - #define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval - #define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity -#endif - -#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl -#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl - -#include - - -// NSGL-specific per-context data -// -typedef struct _GLFWcontextNSGL -{ - id pixelFormat; - id object; - -} _GLFWcontextNSGL; - -// NSGL-specific global data -// -typedef struct _GLFWlibraryNSGL -{ - // dlopen handle for OpenGL.framework (for glfwGetProcAddress) - CFBundleRef framework; - -} _GLFWlibraryNSGL; - - -GLFWbool _glfwInitNSGL(void); -void _glfwTerminateNSGL(void); -GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig); -void _glfwDestroyContextNSGL(_GLFWwindow* window); - diff --git a/src/nsgl_context.m b/src/nsgl_context.m index 3f73f7a6..878f32ed 100644 --- a/src/nsgl_context.m +++ b/src/nsgl_context.m @@ -28,6 +28,8 @@ #include "internal.h" +#if defined(_GLFW_COCOA) + #include #include @@ -188,45 +190,45 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window, // No-error contexts (GL_KHR_no_error) are not yet supported by macOS but // are not a hard constraint, so ignore and continue -#define addAttrib(a) \ +#define ADD_ATTRIB(a) \ { \ assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \ attribs[index++] = a; \ } -#define setAttrib(a, v) { addAttrib(a); addAttrib(v); } +#define SET_ATTRIB(a, v) { ADD_ATTRIB(a); ADD_ATTRIB(v); } NSOpenGLPixelFormatAttribute attribs[40]; int index = 0; - addAttrib(NSOpenGLPFAAccelerated); - addAttrib(NSOpenGLPFAClosestPolicy); + ADD_ATTRIB(NSOpenGLPFAAccelerated); + ADD_ATTRIB(NSOpenGLPFAClosestPolicy); if (ctxconfig->nsgl.offline) { - addAttrib(NSOpenGLPFAAllowOfflineRenderers); + ADD_ATTRIB(NSOpenGLPFAAllowOfflineRenderers); // NOTE: This replaces the NSSupportsAutomaticGraphicsSwitching key in // Info.plist for unbundled applications // HACK: This assumes that NSOpenGLPixelFormat will remain // a straightforward wrapper of its CGL counterpart - addAttrib(kCGLPFASupportsAutomaticGraphicsSwitching); + ADD_ATTRIB(kCGLPFASupportsAutomaticGraphicsSwitching); } #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 if (ctxconfig->major >= 4) { - setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core); + SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core); } else #endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ if (ctxconfig->major >= 3) { - setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); + SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); } if (ctxconfig->major <= 2) { if (fbconfig->auxBuffers != GLFW_DONT_CARE) - setAttrib(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers); + SET_ATTRIB(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers); if (fbconfig->accumRedBits != GLFW_DONT_CARE && fbconfig->accumGreenBits != GLFW_DONT_CARE && @@ -238,7 +240,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window, fbconfig->accumBlueBits + fbconfig->accumAlphaBits; - setAttrib(NSOpenGLPFAAccumSize, accumBits); + SET_ATTRIB(NSOpenGLPFAAccumSize, accumBits); } } @@ -256,17 +258,17 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window, else if (colorBits < 15) colorBits = 15; - setAttrib(NSOpenGLPFAColorSize, colorBits); + SET_ATTRIB(NSOpenGLPFAColorSize, colorBits); } if (fbconfig->alphaBits != GLFW_DONT_CARE) - setAttrib(NSOpenGLPFAAlphaSize, fbconfig->alphaBits); + SET_ATTRIB(NSOpenGLPFAAlphaSize, fbconfig->alphaBits); if (fbconfig->depthBits != GLFW_DONT_CARE) - setAttrib(NSOpenGLPFADepthSize, fbconfig->depthBits); + SET_ATTRIB(NSOpenGLPFADepthSize, fbconfig->depthBits); if (fbconfig->stencilBits != GLFW_DONT_CARE) - setAttrib(NSOpenGLPFAStencilSize, fbconfig->stencilBits); + SET_ATTRIB(NSOpenGLPFAStencilSize, fbconfig->stencilBits); if (fbconfig->stereo) { @@ -275,33 +277,33 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window, "NSGL: Stereo rendering is deprecated"); return GLFW_FALSE; #else - addAttrib(NSOpenGLPFAStereo); + ADD_ATTRIB(NSOpenGLPFAStereo); #endif } if (fbconfig->doublebuffer) - addAttrib(NSOpenGLPFADoubleBuffer); + ADD_ATTRIB(NSOpenGLPFADoubleBuffer); if (fbconfig->samples != GLFW_DONT_CARE) { if (fbconfig->samples == 0) { - setAttrib(NSOpenGLPFASampleBuffers, 0); + SET_ATTRIB(NSOpenGLPFASampleBuffers, 0); } else { - setAttrib(NSOpenGLPFASampleBuffers, 1); - setAttrib(NSOpenGLPFASamples, fbconfig->samples); + SET_ATTRIB(NSOpenGLPFASampleBuffers, 1); + SET_ATTRIB(NSOpenGLPFASamples, fbconfig->samples); } } // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB // framebuffer, so there's no need (and no way) to request it - addAttrib(0); + ADD_ATTRIB(0); -#undef addAttrib -#undef setAttrib +#undef ADD_ATTRIB +#undef SET_ATTRIB window->context.nsgl.pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; @@ -358,7 +360,14 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle) _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(nil); - if (window->context.client == GLFW_NO_API) + if (_glfw.platform.platformID != GLFW_PLATFORM_COCOA) + { + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, + "NSGL: Platform not initialized"); + return nil; + } + + if (window->context.source != GLFW_NATIVE_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return nil; @@ -367,3 +376,5 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle) return window->context.nsgl.object; } +#endif // _GLFW_COCOA + diff --git a/src/null_init.c b/src/null_init.c index 68599d1f..de4b28f3 100644 --- a/src/null_init.c +++ b/src/null_init.c @@ -36,22 +36,98 @@ ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -int _glfwPlatformInit(void) +GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform) { - _glfwInitTimerPOSIX(); - _glfwPollMonitorsNull(); + const _GLFWplatform null = + { + GLFW_PLATFORM_NULL, + _glfwInitNull, + _glfwTerminateNull, + _glfwGetCursorPosNull, + _glfwSetCursorPosNull, + _glfwSetCursorModeNull, + _glfwSetRawMouseMotionNull, + _glfwRawMouseMotionSupportedNull, + _glfwCreateCursorNull, + _glfwCreateStandardCursorNull, + _glfwDestroyCursorNull, + _glfwSetCursorNull, + _glfwGetScancodeNameNull, + _glfwGetKeyScancodeNull, + _glfwSetClipboardStringNull, + _glfwGetClipboardStringNull, + _glfwInitJoysticksNull, + _glfwTerminateJoysticksNull, + _glfwPollJoystickNull, + _glfwGetMappingNameNull, + _glfwUpdateGamepadGUIDNull, + _glfwFreeMonitorNull, + _glfwGetMonitorPosNull, + _glfwGetMonitorContentScaleNull, + _glfwGetMonitorWorkareaNull, + _glfwGetVideoModesNull, + _glfwGetVideoModeNull, + _glfwGetGammaRampNull, + _glfwSetGammaRampNull, + _glfwCreateWindowNull, + _glfwDestroyWindowNull, + _glfwSetWindowTitleNull, + _glfwSetWindowIconNull, + _glfwGetWindowPosNull, + _glfwSetWindowPosNull, + _glfwGetWindowSizeNull, + _glfwSetWindowSizeNull, + _glfwSetWindowSizeLimitsNull, + _glfwSetWindowAspectRatioNull, + _glfwGetFramebufferSizeNull, + _glfwGetWindowFrameSizeNull, + _glfwGetWindowContentScaleNull, + _glfwIconifyWindowNull, + _glfwRestoreWindowNull, + _glfwMaximizeWindowNull, + _glfwShowWindowNull, + _glfwHideWindowNull, + _glfwRequestWindowAttentionNull, + _glfwFocusWindowNull, + _glfwSetWindowMonitorNull, + _glfwWindowFocusedNull, + _glfwWindowIconifiedNull, + _glfwWindowVisibleNull, + _glfwWindowMaximizedNull, + _glfwWindowHoveredNull, + _glfwFramebufferTransparentNull, + _glfwGetWindowOpacityNull, + _glfwSetWindowResizableNull, + _glfwSetWindowDecoratedNull, + _glfwSetWindowFloatingNull, + _glfwSetWindowOpacityNull, + _glfwSetWindowMousePassthroughNull, + _glfwPollEventsNull, + _glfwWaitEventsNull, + _glfwWaitEventsTimeoutNull, + _glfwPostEmptyEventNull, + _glfwGetEGLPlatformNull, + _glfwGetEGLNativeDisplayNull, + _glfwGetEGLNativeWindowNull, + _glfwGetRequiredInstanceExtensionsNull, + _glfwGetPhysicalDevicePresentationSupportNull, + _glfwCreateWindowSurfaceNull, + }; + *platform = null; return GLFW_TRUE; } -void _glfwPlatformTerminate(void) +int _glfwInitNull(void) { - _glfw_free(_glfw.null.clipboardString); + _glfwPollMonitorsNull(); + return GLFW_TRUE; +} + +void _glfwTerminateNull(void) +{ + free(_glfw.null.clipboardString); _glfwTerminateOSMesa(); -} - -const char* _glfwPlatformGetVersionString(void) -{ - return _GLFW_VERSION_NUMBER " null OSMesa"; + _glfwTerminateEGL(); } diff --git a/src/null_joystick.c b/src/null_joystick.c index 27756a61..1fe50721 100644 --- a/src/null_joystick.c +++ b/src/null_joystick.c @@ -33,21 +33,26 @@ ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -GLFWbool _glfwPlatformInitJoysticks(void) +GLFWbool _glfwInitJoysticksNull(void) { return GLFW_TRUE; } -void _glfwPlatformTerminateJoysticks(void) +void _glfwTerminateJoysticksNull(void) { } -int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) +GLFWbool _glfwPollJoystickNull(_GLFWjoystick* js, int mode) { return GLFW_FALSE; } -void _glfwPlatformUpdateGamepadGUID(char* guid) +const char* _glfwGetMappingNameNull(void) +{ + return ""; +} + +void _glfwUpdateGamepadGUIDNull(char* guid) { } diff --git a/src/null_joystick.h b/src/null_joystick.h index 5d19a451..a2199c56 100644 --- a/src/null_joystick.h +++ b/src/null_joystick.h @@ -24,8 +24,9 @@ // //======================================================================== -#define _GLFW_PLATFORM_JOYSTICK_STATE struct { int dummyJoystick; } -#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE struct { int dummyLibraryJoystick; } - -#define _GLFW_PLATFORM_MAPPING_NAME "" +GLFWbool _glfwInitJoysticksNull(void); +void _glfwTerminateJoysticksNull(void); +GLFWbool _glfwPollJoystickNull(_GLFWjoystick* js, int mode); +const char* _glfwGetMappingNameNull(void); +void _glfwUpdateGamepadGUIDNull(char* guid); diff --git a/src/null_monitor.c b/src/null_monitor.c index a071e0c4..63a1cd20 100644 --- a/src/null_monitor.c +++ b/src/null_monitor.c @@ -65,12 +65,12 @@ void _glfwPollMonitorsNull(void) ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor) +void _glfwFreeMonitorNull(_GLFWmonitor* monitor) { _glfwFreeGammaArrays(&monitor->null.ramp); } -void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) +void _glfwGetMonitorPosNull(_GLFWmonitor* monitor, int* xpos, int* ypos) { if (xpos) *xpos = 0; @@ -78,8 +78,8 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) *ypos = 0; } -void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, - float* xscale, float* yscale) +void _glfwGetMonitorContentScaleNull(_GLFWmonitor* monitor, + float* xscale, float* yscale) { if (xscale) *xscale = 1.f; @@ -87,9 +87,9 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, *yscale = 1.f; } -void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, - int* xpos, int* ypos, - int* width, int* height) +void _glfwGetMonitorWorkareaNull(_GLFWmonitor* monitor, + int* xpos, int* ypos, + int* width, int* height) { const GLFWvidmode mode = getVideoMode(); @@ -103,7 +103,7 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, *height = mode.height - 10; } -GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) +GLFWvidmode* _glfwGetVideoModesNull(_GLFWmonitor* monitor, int* found) { GLFWvidmode* mode = _glfw_calloc(1, sizeof(GLFWvidmode)); *mode = getVideoMode(); @@ -111,18 +111,20 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) return mode; } -void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) +void _glfwGetVideoModeNull(_GLFWmonitor* monitor, GLFWvidmode* mode) { *mode = getVideoMode(); } -GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) +GLFWbool _glfwGetGammaRampNull(_GLFWmonitor* monitor, GLFWgammaramp* ramp) { if (!monitor->null.ramp.size) { + unsigned int i; + _glfwAllocGammaArrays(&monitor->null.ramp, 256); - for (unsigned int i = 0; i < monitor->null.ramp.size; i++) + for (i = 0; i < monitor->null.ramp.size; i++) { const float gamma = 2.2f; float value; @@ -143,7 +145,7 @@ GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) return GLFW_TRUE; } -void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) +void _glfwSetGammaRampNull(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) { if (monitor->null.ramp.size != ramp->size) { diff --git a/src/null_platform.h b/src/null_platform.h index 49436dcc..b646acb3 100644 --- a/src/null_platform.h +++ b/src/null_platform.h @@ -25,29 +25,14 @@ // //======================================================================== -#include +#define GLFW_NULL_WINDOW_STATE _GLFWwindowNull null; +#define GLFW_NULL_LIBRARY_WINDOW_STATE _GLFWlibraryNull null; +#define GLFW_NULL_MONITOR_STATE _GLFWmonitorNull null; -#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNull null -#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNull null -#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNull null +#define GLFW_NULL_CONTEXT_STATE +#define GLFW_NULL_CURSOR_STATE +#define GLFW_NULL_LIBRARY_CONTEXT_STATE -#define _GLFW_PLATFORM_CONTEXT_STATE struct { int dummyContext; } -#define _GLFW_PLATFORM_CURSOR_STATE struct { int dummyCursor; } -#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE struct { int dummyLibraryContext; } - -#include "posix_time.h" -#include "posix_thread.h" -#include "null_joystick.h" - -#if defined(_GLFW_WIN32) - #define _glfw_dlopen(name) LoadLibraryA(name) - #define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle) - #define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name) -#else - #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) - #define _glfw_dlclose(handle) dlclose(handle) - #define _glfw_dlsym(handle, name) dlsym(handle, name) -#endif // Null-specific per-window data // @@ -87,3 +72,78 @@ typedef struct _GLFWlibraryNull void _glfwPollMonitorsNull(void); +GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform); +int _glfwInitNull(void); +void _glfwTerminateNull(void); + +void _glfwFreeMonitorNull(_GLFWmonitor* monitor); +void _glfwGetMonitorPosNull(_GLFWmonitor* monitor, int* xpos, int* ypos); +void _glfwGetMonitorContentScaleNull(_GLFWmonitor* monitor, float* xscale, float* yscale); +void _glfwGetMonitorWorkareaNull(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height); +GLFWvidmode* _glfwGetVideoModesNull(_GLFWmonitor* monitor, int* found); +void _glfwGetVideoModeNull(_GLFWmonitor* monitor, GLFWvidmode* mode); +GLFWbool _glfwGetGammaRampNull(_GLFWmonitor* monitor, GLFWgammaramp* ramp); +void _glfwSetGammaRampNull(_GLFWmonitor* monitor, const GLFWgammaramp* ramp); + +GLFWbool _glfwCreateWindowNull(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); +void _glfwDestroyWindowNull(_GLFWwindow* window); +void _glfwSetWindowTitleNull(_GLFWwindow* window, const char* title); +void _glfwSetWindowIconNull(_GLFWwindow* window, int count, const GLFWimage* images); +void _glfwSetWindowMonitorNull(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); +void _glfwGetWindowPosNull(_GLFWwindow* window, int* xpos, int* ypos); +void _glfwSetWindowPosNull(_GLFWwindow* window, int xpos, int ypos); +void _glfwGetWindowSizeNull(_GLFWwindow* window, int* width, int* height); +void _glfwSetWindowSizeNull(_GLFWwindow* window, int width, int height); +void _glfwSetWindowSizeLimitsNull(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); +void _glfwSetWindowAspectRatioNull(_GLFWwindow* window, int n, int d); +void _glfwGetFramebufferSizeNull(_GLFWwindow* window, int* width, int* height); +void _glfwGetWindowFrameSizeNull(_GLFWwindow* window, int* left, int* top, int* right, int* bottom); +void _glfwGetWindowContentScaleNull(_GLFWwindow* window, float* xscale, float* yscale); +void _glfwIconifyWindowNull(_GLFWwindow* window); +void _glfwRestoreWindowNull(_GLFWwindow* window); +void _glfwMaximizeWindowNull(_GLFWwindow* window); +GLFWbool _glfwWindowMaximizedNull(_GLFWwindow* window); +GLFWbool _glfwWindowHoveredNull(_GLFWwindow* window); +GLFWbool _glfwFramebufferTransparentNull(_GLFWwindow* window); +void _glfwSetWindowResizableNull(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowDecoratedNull(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowFloatingNull(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowMousePassthroughNull(_GLFWwindow* window, GLFWbool enabled); +float _glfwGetWindowOpacityNull(_GLFWwindow* window); +void _glfwSetWindowOpacityNull(_GLFWwindow* window, float opacity); +void _glfwSetRawMouseMotionNull(_GLFWwindow *window, GLFWbool enabled); +GLFWbool _glfwRawMouseMotionSupportedNull(void); +void _glfwShowWindowNull(_GLFWwindow* window); +void _glfwRequestWindowAttentionNull(_GLFWwindow* window); +void _glfwRequestWindowAttentionNull(_GLFWwindow* window); +void _glfwHideWindowNull(_GLFWwindow* window); +void _glfwFocusWindowNull(_GLFWwindow* window); +GLFWbool _glfwWindowFocusedNull(_GLFWwindow* window); +GLFWbool _glfwWindowIconifiedNull(_GLFWwindow* window); +GLFWbool _glfwWindowVisibleNull(_GLFWwindow* window); +void _glfwPollEventsNull(void); +void _glfwWaitEventsNull(void); +void _glfwWaitEventsTimeoutNull(double timeout); +void _glfwPostEmptyEventNull(void); +void _glfwGetCursorPosNull(_GLFWwindow* window, double* xpos, double* ypos); +void _glfwSetCursorPosNull(_GLFWwindow* window, double x, double y); +void _glfwSetCursorModeNull(_GLFWwindow* window, int mode); +GLFWbool _glfwCreateCursorNull(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot); +GLFWbool _glfwCreateStandardCursorNull(_GLFWcursor* cursor, int shape); +void _glfwDestroyCursorNull(_GLFWcursor* cursor); +void _glfwSetCursorNull(_GLFWwindow* window, _GLFWcursor* cursor); +void _glfwSetClipboardStringNull(const char* string); +const char* _glfwGetClipboardStringNull(void); +const char* _glfwGetScancodeNameNull(int scancode); +int _glfwGetKeyScancodeNull(int key); + +EGLenum _glfwGetEGLPlatformNull(EGLint** attribs); +EGLNativeDisplayType _glfwGetEGLNativeDisplayNull(void); +EGLNativeWindowType _glfwGetEGLNativeWindowNull(_GLFWwindow* window); + +void _glfwGetRequiredInstanceExtensionsNull(char** extensions); +GLFWbool _glfwGetPhysicalDevicePresentationSupportNull(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); +VkResult _glfwCreateWindowSurfaceNull(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +void _glfwPollMonitorsNull(void); + diff --git a/src/null_window.c b/src/null_window.c index 1f59540e..5cdf3e23 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -39,24 +39,24 @@ static void applySizeLimits(_GLFWwindow* window, int* width, int* height) *height = (int) (*width / ratio); } - if (window->minwidth != GLFW_DONT_CARE && *width < window->minwidth) - *width = window->minwidth; - else if (window->maxwidth != GLFW_DONT_CARE && *width > window->maxwidth) - *width = window->maxwidth; + if (window->minwidth != GLFW_DONT_CARE) + *width = _glfw_max(*width, window->minwidth); + else if (window->maxwidth != GLFW_DONT_CARE) + *width = _glfw_min(*width, window->maxwidth); - if (window->minheight != GLFW_DONT_CARE && *height < window->minheight) - *height = window->minheight; - else if (window->maxheight != GLFW_DONT_CARE && *height > window->maxheight) - *height = window->maxheight; + if (window->minheight != GLFW_DONT_CARE) + *height = _glfw_min(*height, window->minheight); + else if (window->maxheight != GLFW_DONT_CARE) + *height = _glfw_max(*height, window->maxheight); } static void fitToMonitor(_GLFWwindow* window) { GLFWvidmode mode; - _glfwPlatformGetVideoMode(window->monitor, &mode); - _glfwPlatformGetMonitorPos(window->monitor, - &window->null.xpos, - &window->null.ypos); + _glfwGetVideoModeNull(window->monitor, &mode); + _glfwGetMonitorPosNull(window->monitor, + &window->null.xpos, + &window->null.ypos); window->null.width = mode.width; window->null.height = mode.height; } @@ -82,8 +82,17 @@ static int createNativeWindow(_GLFWwindow* window, fitToMonitor(window); else { - window->null.xpos = 17; - window->null.ypos = 17; + if (wndconfig->xpos == GLFW_ANY_POSITION && wndconfig->ypos == GLFW_ANY_POSITION) + { + window->null.xpos = 17; + window->null.ypos = 17; + } + else + { + window->null.xpos = wndconfig->xpos; + window->null.ypos = wndconfig->ypos; + } + window->null.width = wndconfig->width; window->null.height = wndconfig->height; } @@ -103,10 +112,10 @@ static int createNativeWindow(_GLFWwindow* window, ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -int _glfwPlatformCreateWindow(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig) +GLFWbool _glfwCreateWindowNull(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig) { if (!createNativeWindow(window, wndconfig, fbconfig)) return GLFW_FALSE; @@ -121,24 +130,44 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig)) return GLFW_FALSE; } - else + else if (ctxconfig->source == GLFW_EGL_CONTEXT_API) { - _glfwInputError(GLFW_API_UNAVAILABLE, "Null: EGL not available"); - return GLFW_FALSE; + if (!_glfwInitEGL()) + return GLFW_FALSE; + if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) + return GLFW_FALSE; } + + if (!_glfwRefreshContextAttribs(window, ctxconfig)) + return GLFW_FALSE; } + if (wndconfig->mousePassthrough) + _glfwSetWindowMousePassthroughNull(window, GLFW_TRUE); + if (window->monitor) { - _glfwPlatformShowWindow(window); - _glfwPlatformFocusWindow(window); + _glfwShowWindowNull(window); + _glfwFocusWindowNull(window); acquireMonitor(window); + + if (wndconfig->centerCursor) + _glfwCenterCursorInContentArea(window); + } + else + { + if (wndconfig->visible) + { + _glfwShowWindowNull(window); + if (wndconfig->focused) + _glfwFocusWindowNull(window); + } } return GLFW_TRUE; } -void _glfwPlatformDestroyWindow(_GLFWwindow* window) +void _glfwDestroyWindowNull(_GLFWwindow* window) { if (window->monitor) releaseMonitor(window); @@ -150,27 +179,26 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) window->context.destroy(window); } -void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) +void _glfwSetWindowTitleNull(_GLFWwindow* window, const char* title) { } -void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count, - const GLFWimage* images) +void _glfwSetWindowIconNull(_GLFWwindow* window, int count, const GLFWimage* images) { } -void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, - _GLFWmonitor* monitor, - int xpos, int ypos, - int width, int height, - int refreshRate) +void _glfwSetWindowMonitorNull(_GLFWwindow* window, + _GLFWmonitor* monitor, + int xpos, int ypos, + int width, int height, + int refreshRate) { if (window->monitor == monitor) { if (!monitor) { - _glfwPlatformSetWindowPos(window, xpos, ypos); - _glfwPlatformSetWindowSize(window, width, height); + _glfwSetWindowPosNull(window, xpos, ypos); + _glfwSetWindowSizeNull(window, width, height); } return; @@ -189,12 +217,12 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, } else { - _glfwPlatformSetWindowPos(window, xpos, ypos); - _glfwPlatformSetWindowSize(window, width, height); + _glfwSetWindowPosNull(window, xpos, ypos); + _glfwSetWindowSizeNull(window, width, height); } } -void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) +void _glfwGetWindowPosNull(_GLFWwindow* window, int* xpos, int* ypos) { if (xpos) *xpos = window->null.xpos; @@ -202,7 +230,7 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) *ypos = window->null.ypos; } -void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) +void _glfwSetWindowPosNull(_GLFWwindow* window, int xpos, int ypos) { if (window->monitor) return; @@ -215,7 +243,7 @@ void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) } } -void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) +void _glfwGetWindowSizeNull(_GLFWwindow* window, int* width, int* height) { if (width) *width = window->null.width; @@ -223,7 +251,7 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) *height = window->null.height; } -void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) +void _glfwSetWindowSizeNull(_GLFWwindow* window, int width, int height) { if (window->monitor) return; @@ -237,25 +265,25 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) } } -void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, - int minwidth, int minheight, - int maxwidth, int maxheight) +void _glfwSetWindowSizeLimitsNull(_GLFWwindow* window, + int minwidth, int minheight, + int maxwidth, int maxheight) { int width = window->null.width; int height = window->null.height; applySizeLimits(window, &width, &height); - _glfwPlatformSetWindowSize(window, width, height); + _glfwSetWindowSizeNull(window, width, height); } -void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int n, int d) +void _glfwSetWindowAspectRatioNull(_GLFWwindow* window, int n, int d) { int width = window->null.width; int height = window->null.height; applySizeLimits(window, &width, &height); - _glfwPlatformSetWindowSize(window, width, height); + _glfwSetWindowSizeNull(window, width, height); } -void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) +void _glfwGetFramebufferSizeNull(_GLFWwindow* window, int* width, int* height) { if (width) *width = window->null.width; @@ -263,9 +291,9 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* heigh *height = window->null.height; } -void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, - int* left, int* top, - int* right, int* bottom) +void _glfwGetWindowFrameSizeNull(_GLFWwindow* window, + int* left, int* top, + int* right, int* bottom) { if (window->null.decorated && !window->monitor) { @@ -291,8 +319,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, } } -void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, - float* xscale, float* yscale) +void _glfwGetWindowContentScaleNull(_GLFWwindow* window, float* xscale, float* yscale) { if (xscale) *xscale = 1.f; @@ -300,7 +327,7 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, *yscale = 1.f; } -void _glfwPlatformIconifyWindow(_GLFWwindow* window) +void _glfwIconifyWindowNull(_GLFWwindow* window) { if (_glfw.null.focusedWindow == window) { @@ -318,7 +345,7 @@ void _glfwPlatformIconifyWindow(_GLFWwindow* window) } } -void _glfwPlatformRestoreWindow(_GLFWwindow* window) +void _glfwRestoreWindowNull(_GLFWwindow* window) { if (window->null.iconified) { @@ -335,7 +362,7 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) } } -void _glfwPlatformMaximizeWindow(_GLFWwindow* window) +void _glfwMaximizeWindowNull(_GLFWwindow* window) { if (!window->null.maximized) { @@ -344,12 +371,12 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window) } } -int _glfwPlatformWindowMaximized(_GLFWwindow* window) +GLFWbool _glfwWindowMaximizedNull(_GLFWwindow* window) { return window->null.maximized; } -int _glfwPlatformWindowHovered(_GLFWwindow* window) +GLFWbool _glfwWindowHoveredNull(_GLFWwindow* window) { return _glfw.null.xcursor >= window->null.xpos && _glfw.null.ycursor >= window->null.ypos && @@ -357,59 +384,59 @@ int _glfwPlatformWindowHovered(_GLFWwindow* window) _glfw.null.ycursor <= window->null.ypos + window->null.height - 1; } -int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) +GLFWbool _glfwFramebufferTransparentNull(_GLFWwindow* window) { return window->null.transparent; } -void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowResizableNull(_GLFWwindow* window, GLFWbool enabled) { window->null.resizable = enabled; } -void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowDecoratedNull(_GLFWwindow* window, GLFWbool enabled) { window->null.decorated = enabled; } -void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowFloatingNull(_GLFWwindow* window, GLFWbool enabled) { window->null.floating = enabled; } -void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowMousePassthroughNull(_GLFWwindow* window, GLFWbool enabled) { } -float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) +float _glfwGetWindowOpacityNull(_GLFWwindow* window) { return window->null.opacity; } -void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) +void _glfwSetWindowOpacityNull(_GLFWwindow* window, float opacity) { window->null.opacity = opacity; } -void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled) +void _glfwSetRawMouseMotionNull(_GLFWwindow *window, GLFWbool enabled) { } -GLFWbool _glfwPlatformRawMouseMotionSupported(void) +GLFWbool _glfwRawMouseMotionSupportedNull(void) { return GLFW_TRUE; } -void _glfwPlatformShowWindow(_GLFWwindow* window) +void _glfwShowWindowNull(_GLFWwindow* window) { window->null.visible = GLFW_TRUE; } -void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) +void _glfwRequestWindowAttentionNull(_GLFWwindow* window) { } -void _glfwPlatformHideWindow(_GLFWwindow* window) +void _glfwHideWindowNull(_GLFWwindow* window) { if (_glfw.null.focusedWindow == window) { @@ -420,59 +447,61 @@ void _glfwPlatformHideWindow(_GLFWwindow* window) window->null.visible = GLFW_FALSE; } -void _glfwPlatformFocusWindow(_GLFWwindow* window) +void _glfwFocusWindowNull(_GLFWwindow* window) { + _GLFWwindow* previous; + if (_glfw.null.focusedWindow == window) return; if (!window->null.visible) return; - _GLFWwindow* previous = _glfw.null.focusedWindow; + previous = _glfw.null.focusedWindow; _glfw.null.focusedWindow = window; if (previous) { _glfwInputWindowFocus(previous, GLFW_FALSE); if (previous->monitor && previous->autoIconify) - _glfwPlatformIconifyWindow(previous); + _glfwIconifyWindowNull(previous); } _glfwInputWindowFocus(window, GLFW_TRUE); } -int _glfwPlatformWindowFocused(_GLFWwindow* window) +GLFWbool _glfwWindowFocusedNull(_GLFWwindow* window) { return _glfw.null.focusedWindow == window; } -int _glfwPlatformWindowIconified(_GLFWwindow* window) +GLFWbool _glfwWindowIconifiedNull(_GLFWwindow* window) { return window->null.iconified; } -int _glfwPlatformWindowVisible(_GLFWwindow* window) +GLFWbool _glfwWindowVisibleNull(_GLFWwindow* window) { return window->null.visible; } -void _glfwPlatformPollEvents(void) +void _glfwPollEventsNull(void) { } -void _glfwPlatformWaitEvents(void) +void _glfwWaitEventsNull(void) { } -void _glfwPlatformWaitEventsTimeout(double timeout) +void _glfwWaitEventsTimeoutNull(double timeout) { } -void _glfwPlatformPostEmptyEvent(void) +void _glfwPostEmptyEventNull(void) { } -void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) +void _glfwGetCursorPosNull(_GLFWwindow* window, double* xpos, double* ypos) { if (xpos) *xpos = _glfw.null.xcursor - window->null.xpos; @@ -480,49 +509,64 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) *ypos = _glfw.null.ycursor - window->null.ypos; } -void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) +void _glfwSetCursorPosNull(_GLFWwindow* window, double x, double y) { _glfw.null.xcursor = window->null.xpos + (int) x; _glfw.null.ycursor = window->null.ypos + (int) y; } -void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) +void _glfwSetCursorModeNull(_GLFWwindow* window, int mode) { } -int _glfwPlatformCreateCursor(_GLFWcursor* cursor, - const GLFWimage* image, - int xhot, int yhot) +GLFWbool _glfwCreateCursorNull(_GLFWcursor* cursor, + const GLFWimage* image, + int xhot, int yhot) { return GLFW_TRUE; } -int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) +GLFWbool _glfwCreateStandardCursorNull(_GLFWcursor* cursor, int shape) { return GLFW_TRUE; } -void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) +void _glfwDestroyCursorNull(_GLFWcursor* cursor) { } -void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) +void _glfwSetCursorNull(_GLFWwindow* window, _GLFWcursor* cursor) { } -void _glfwPlatformSetClipboardString(const char* string) +void _glfwSetClipboardStringNull(const char* string) { char* copy = _glfw_strdup(string); _glfw_free(_glfw.null.clipboardString); _glfw.null.clipboardString = copy; } -const char* _glfwPlatformGetClipboardString(void) +const char* _glfwGetClipboardStringNull(void) { return _glfw.null.clipboardString; } -const char* _glfwPlatformGetScancodeName(int scancode) +EGLenum _glfwGetEGLPlatformNull(EGLint** attribs) +{ + return 0; +} + +EGLNativeDisplayType _glfwGetEGLNativeDisplayNull(void) +{ + return 0; +} + +EGLNativeWindowType _glfwGetEGLNativeWindowNull(_GLFWwindow* window) +{ + return 0; +} + +const char* _glfwGetScancodeNameNull(int scancode) { if (scancode < GLFW_KEY_SPACE || scancode > GLFW_KEY_LAST) { @@ -649,26 +693,26 @@ const char* _glfwPlatformGetScancodeName(int scancode) return NULL; } -int _glfwPlatformGetKeyScancode(int key) +int _glfwGetKeyScancodeNull(int key) { return key; } -void _glfwPlatformGetRequiredInstanceExtensions(char** extensions) +void _glfwGetRequiredInstanceExtensionsNull(char** extensions) { } -int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, - VkPhysicalDevice device, - uint32_t queuefamily) +GLFWbool _glfwGetPhysicalDevicePresentationSupportNull(VkInstance instance, + VkPhysicalDevice device, + uint32_t queuefamily) { return GLFW_FALSE; } -VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, - _GLFWwindow* window, - const VkAllocationCallbacks* allocator, - VkSurfaceKHR* surface) +VkResult _glfwCreateWindowSurfaceNull(VkInstance instance, + _GLFWwindow* window, + const VkAllocationCallbacks* allocator, + VkSurfaceKHR* surface) { // This seems like the most appropriate error to return here return VK_ERROR_EXTENSION_NOT_PRESENT; diff --git a/src/osmesa_context.c b/src/osmesa_context.c index 74a9291b..38adabbc 100644 --- a/src/osmesa_context.c +++ b/src/osmesa_context.c @@ -39,7 +39,7 @@ static void makeContextCurrentOSMesa(_GLFWwindow* window) if (window) { int width, height; - _glfwPlatformGetFramebufferSize(window, &width, &height); + _glfw.platform.getFramebufferSize(window, &width, &height); // Check to see if we need to allocate a new buffer if ((window->context.osmesa.buffer == NULL) || @@ -124,6 +124,8 @@ GLFWbool _glfwInitOSMesa(void) "libOSMesa.8.dylib", #elif defined(__CYGWIN__) "libOSMesa-8.so", +#elif defined(__OpenBSD__) || defined(__NetBSD__) + "libOSMesa.so", #else "libOSMesa.so.8", "libOSMesa.so.6", @@ -136,7 +138,7 @@ GLFWbool _glfwInitOSMesa(void) for (i = 0; sonames[i]; i++) { - _glfw.osmesa.handle = _glfw_dlopen(sonames[i]); + _glfw.osmesa.handle = _glfwPlatformLoadModule(sonames[i]); if (_glfw.osmesa.handle) break; } @@ -148,19 +150,19 @@ GLFWbool _glfwInitOSMesa(void) } _glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt) - _glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextExt"); + _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaCreateContextExt"); _glfw.osmesa.CreateContextAttribs = (PFN_OSMesaCreateContextAttribs) - _glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextAttribs"); + _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaCreateContextAttribs"); _glfw.osmesa.DestroyContext = (PFN_OSMesaDestroyContext) - _glfw_dlsym(_glfw.osmesa.handle, "OSMesaDestroyContext"); + _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaDestroyContext"); _glfw.osmesa.MakeCurrent = (PFN_OSMesaMakeCurrent) - _glfw_dlsym(_glfw.osmesa.handle, "OSMesaMakeCurrent"); + _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaMakeCurrent"); _glfw.osmesa.GetColorBuffer = (PFN_OSMesaGetColorBuffer) - _glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetColorBuffer"); + _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaGetColorBuffer"); _glfw.osmesa.GetDepthBuffer = (PFN_OSMesaGetDepthBuffer) - _glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetDepthBuffer"); + _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaGetDepthBuffer"); _glfw.osmesa.GetProcAddress = (PFN_OSMesaGetProcAddress) - _glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetProcAddress"); + _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaGetProcAddress"); if (!_glfw.osmesa.CreateContextExt || !_glfw.osmesa.DestroyContext || @@ -183,12 +185,12 @@ void _glfwTerminateOSMesa(void) { if (_glfw.osmesa.handle) { - _glfw_dlclose(_glfw.osmesa.handle); + _glfwPlatformFreeModule(_glfw.osmesa.handle); _glfw.osmesa.handle = NULL; } } -#define setAttrib(a, v) \ +#define SET_ATTRIB(a, v) \ { \ assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ attribs[index++] = a; \ @@ -219,24 +221,24 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window, { int index = 0, attribs[40]; - setAttrib(OSMESA_FORMAT, OSMESA_RGBA); - setAttrib(OSMESA_DEPTH_BITS, fbconfig->depthBits); - setAttrib(OSMESA_STENCIL_BITS, fbconfig->stencilBits); - setAttrib(OSMESA_ACCUM_BITS, accumBits); + SET_ATTRIB(OSMESA_FORMAT, OSMESA_RGBA); + SET_ATTRIB(OSMESA_DEPTH_BITS, fbconfig->depthBits); + SET_ATTRIB(OSMESA_STENCIL_BITS, fbconfig->stencilBits); + SET_ATTRIB(OSMESA_ACCUM_BITS, accumBits); if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE) { - setAttrib(OSMESA_PROFILE, OSMESA_CORE_PROFILE); + SET_ATTRIB(OSMESA_PROFILE, OSMESA_CORE_PROFILE); } else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE) { - setAttrib(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE); + SET_ATTRIB(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE); } if (ctxconfig->major != 1 || ctxconfig->minor != 0) { - setAttrib(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major); - setAttrib(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor); + SET_ATTRIB(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major); + SET_ATTRIB(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor); } if (ctxconfig->forward) @@ -246,7 +248,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window, return GLFW_FALSE; } - setAttrib(0, 0); + SET_ATTRIB(0, 0); window->context.osmesa.handle = OSMesaCreateContextAttribs(attribs, share); @@ -285,7 +287,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window, return GLFW_TRUE; } -#undef setAttrib +#undef SET_ATTRIB ////////////////////////////////////////////////////////////////////////// @@ -302,6 +304,12 @@ GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width, _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); + if (window->context.source != GLFW_OSMESA_CONTEXT_API) + { + _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); + return GLFW_FALSE; + } + if (!OSMesaGetColorBuffer(window->context.osmesa.handle, &mesaWidth, &mesaHeight, &mesaFormat, &mesaBuffer)) @@ -335,6 +343,12 @@ GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle, _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); + if (window->context.source != GLFW_OSMESA_CONTEXT_API) + { + _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); + return GLFW_FALSE; + } + if (!OSMesaGetDepthBuffer(window->context.osmesa.handle, &mesaWidth, &mesaHeight, &mesaBytes, &mesaBuffer)) @@ -361,7 +375,7 @@ GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle) _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - if (window->context.client == GLFW_NO_API) + if (window->context.source != GLFW_OSMESA_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return NULL; diff --git a/src/osmesa_context.h b/src/osmesa_context.h deleted file mode 100644 index ce1f1a29..00000000 --- a/src/osmesa_context.h +++ /dev/null @@ -1,90 +0,0 @@ -//======================================================================== -// GLFW 3.4 OSMesa - www.glfw.org -//------------------------------------------------------------------------ -// Copyright (c) 2016 Google Inc. -// Copyright (c) 2016-2017 Camilla Löwy -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would -// be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -// -//======================================================================== - -#define OSMESA_RGBA 0x1908 -#define OSMESA_FORMAT 0x22 -#define OSMESA_DEPTH_BITS 0x30 -#define OSMESA_STENCIL_BITS 0x31 -#define OSMESA_ACCUM_BITS 0x32 -#define OSMESA_PROFILE 0x33 -#define OSMESA_CORE_PROFILE 0x34 -#define OSMESA_COMPAT_PROFILE 0x35 -#define OSMESA_CONTEXT_MAJOR_VERSION 0x36 -#define OSMESA_CONTEXT_MINOR_VERSION 0x37 - -typedef void* OSMesaContext; -typedef void (*OSMESAproc)(void); - -typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextExt)(GLenum,GLint,GLint,GLint,OSMesaContext); -typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextAttribs)(const int*,OSMesaContext); -typedef void (GLAPIENTRY * PFN_OSMesaDestroyContext)(OSMesaContext); -typedef int (GLAPIENTRY * PFN_OSMesaMakeCurrent)(OSMesaContext,void*,int,int,int); -typedef int (GLAPIENTRY * PFN_OSMesaGetColorBuffer)(OSMesaContext,int*,int*,int*,void**); -typedef int (GLAPIENTRY * PFN_OSMesaGetDepthBuffer)(OSMesaContext,int*,int*,int*,void**); -typedef GLFWglproc (GLAPIENTRY * PFN_OSMesaGetProcAddress)(const char*); -#define OSMesaCreateContextExt _glfw.osmesa.CreateContextExt -#define OSMesaCreateContextAttribs _glfw.osmesa.CreateContextAttribs -#define OSMesaDestroyContext _glfw.osmesa.DestroyContext -#define OSMesaMakeCurrent _glfw.osmesa.MakeCurrent -#define OSMesaGetColorBuffer _glfw.osmesa.GetColorBuffer -#define OSMesaGetDepthBuffer _glfw.osmesa.GetDepthBuffer -#define OSMesaGetProcAddress _glfw.osmesa.GetProcAddress - -// OSMesa-specific per-context data -// -typedef struct _GLFWcontextOSMesa -{ - OSMesaContext handle; - int width; - int height; - void* buffer; - -} _GLFWcontextOSMesa; - -// OSMesa-specific global data -// -typedef struct _GLFWlibraryOSMesa -{ - void* handle; - - PFN_OSMesaCreateContextExt CreateContextExt; - PFN_OSMesaCreateContextAttribs CreateContextAttribs; - PFN_OSMesaDestroyContext DestroyContext; - PFN_OSMesaMakeCurrent MakeCurrent; - PFN_OSMesaGetColorBuffer GetColorBuffer; - PFN_OSMesaGetDepthBuffer GetDepthBuffer; - PFN_OSMesaGetProcAddress GetProcAddress; - -} _GLFWlibraryOSMesa; - - -GLFWbool _glfwInitOSMesa(void); -void _glfwTerminateOSMesa(void); -GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig); - diff --git a/src/platform.c b/src/platform.c new file mode 100644 index 00000000..c5966ae7 --- /dev/null +++ b/src/platform.c @@ -0,0 +1,195 @@ +//======================================================================== +// GLFW 3.4 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2002-2006 Marcus Geelnard +// Copyright (c) 2006-2018 Camilla Löwy +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== +// Please use C89 style variable declarations in this file because VS 2010 +//======================================================================== + +#include "internal.h" + +// These construct a string literal from individual numeric constants +#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r +#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r) + +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +static const struct +{ + int ID; + GLFWbool (*connect)(int,_GLFWplatform*); +} supportedPlatforms[] = +{ +#if defined(_GLFW_WIN32) + { GLFW_PLATFORM_WIN32, _glfwConnectWin32 }, +#endif +#if defined(_GLFW_COCOA) + { GLFW_PLATFORM_COCOA, _glfwConnectCocoa }, +#endif +#if defined(_GLFW_X11) + { GLFW_PLATFORM_X11, _glfwConnectX11 }, +#endif +#if defined(_GLFW_WAYLAND) + { GLFW_PLATFORM_WAYLAND, _glfwConnectWayland }, +#endif +}; + +GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform) +{ + const size_t count = sizeof(supportedPlatforms) / sizeof(supportedPlatforms[0]); + size_t i; + + if (desiredID != GLFW_ANY_PLATFORM && + desiredID != GLFW_PLATFORM_WIN32 && + desiredID != GLFW_PLATFORM_COCOA && + desiredID != GLFW_PLATFORM_WAYLAND && + desiredID != GLFW_PLATFORM_X11 && + desiredID != GLFW_PLATFORM_NULL) + { + _glfwInputError(GLFW_INVALID_ENUM, "Invalid platform ID 0x%08X", desiredID); + return GLFW_FALSE; + } + + // Only allow the Null platform if specifically requested + if (desiredID == GLFW_PLATFORM_NULL) + return _glfwConnectNull(desiredID, platform); + else if (count == 0) + { + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "This binary only supports the Null platform"); + return GLFW_FALSE; + } + + if (desiredID == GLFW_ANY_PLATFORM) + { + // If there is exactly one platform available for auto-selection, let it emit the + // error on failure as the platform-specific error description may be more helpful + if (count == 1) + return supportedPlatforms[0].connect(supportedPlatforms[0].ID, platform); + + for (i = 0; i < count; i++) + { + if (supportedPlatforms[i].connect(desiredID, platform)) + return GLFW_TRUE; + } + + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "Failed to detect any supported platform"); + } + else + { + for (i = 0; i < count; i++) + { + if (supportedPlatforms[i].ID == desiredID) + return supportedPlatforms[i].connect(desiredID, platform); + } + + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "The requested platform is not supported"); + } + + return GLFW_FALSE; +} + +////////////////////////////////////////////////////////////////////////// +////// GLFW public API ////// +////////////////////////////////////////////////////////////////////////// + +GLFWAPI int glfwGetPlatform(void) +{ + _GLFW_REQUIRE_INIT_OR_RETURN(0); + return _glfw.platform.platformID; +} + +GLFWAPI int glfwPlatformSupported(int platformID) +{ + const size_t count = sizeof(supportedPlatforms) / sizeof(supportedPlatforms[0]); + size_t i; + + if (platformID != GLFW_PLATFORM_WIN32 && + platformID != GLFW_PLATFORM_COCOA && + platformID != GLFW_PLATFORM_WAYLAND && + platformID != GLFW_PLATFORM_X11 && + platformID != GLFW_PLATFORM_NULL) + { + _glfwInputError(GLFW_INVALID_ENUM, "Invalid platform ID 0x%08X", platformID); + return GLFW_FALSE; + } + + if (platformID == GLFW_PLATFORM_NULL) + return GLFW_TRUE; + + for (i = 0; i < count; i++) + { + if (platformID == supportedPlatforms[i].ID) + return GLFW_TRUE; + } + + return GLFW_FALSE; +} + +GLFWAPI const char* glfwGetVersionString(void) +{ + return _GLFW_MAKE_VERSION(GLFW_VERSION_MAJOR, + GLFW_VERSION_MINOR, + GLFW_VERSION_REVISION) +#if defined(_GLFW_WIN32) + " Win32 WGL" +#endif +#if defined(_GLFW_COCOA) + " Cocoa NSGL" +#endif +#if defined(_GLFW_WAYLAND) + " Wayland" +#endif +#if defined(_GLFW_X11) + " X11 GLX" +#endif + " Null" + " EGL" + " OSMesa" +#if defined(__MINGW64_VERSION_MAJOR) + " MinGW-w64" +#elif defined(__MINGW32__) + " MinGW" +#elif defined(_MSC_VER) + " VisualC" +#endif +#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG) + " hybrid-GPU" +#endif +#if defined(_POSIX_MONOTONIC_CLOCK) + " monotonic" +#endif +#if defined(_GLFW_BUILD_DLL) +#if defined(_WIN32) + " DLL" +#elif defined(__APPLE__) + " dynamic" +#else + " shared" +#endif +#endif + ; +} + diff --git a/src/platform.h b/src/platform.h new file mode 100644 index 00000000..4e924a69 --- /dev/null +++ b/src/platform.h @@ -0,0 +1,203 @@ +//======================================================================== +// GLFW 3.4 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2002-2006 Marcus Geelnard +// Copyright (c) 2006-2018 Camilla Löwy +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#if defined(GLFW_BUILD_WIN32_TIMER) || \ + defined(GLFW_BUILD_WIN32_MODULE) || \ + defined(GLFW_BUILD_WIN32_THREAD) || \ + defined(GLFW_BUILD_COCOA_TIMER) || \ + defined(GLFW_BUILD_POSIX_TIMER) || \ + defined(GLFW_BUILD_POSIX_MODULE) || \ + defined(GLFW_BUILD_POSIX_THREAD) || \ + defined(GLFW_BUILD_POSIX_POLL) || \ + defined(GLFW_BUILD_LINUX_JOYSTICK) + #error "You must not define these; define zero or more _GLFW_ macros instead" +#endif + +#include "null_platform.h" + +#if defined(_GLFW_WIN32) + #include "win32_platform.h" +#else + #define GLFW_WIN32_WINDOW_STATE + #define GLFW_WIN32_MONITOR_STATE + #define GLFW_WIN32_CURSOR_STATE + #define GLFW_WIN32_LIBRARY_WINDOW_STATE + #define GLFW_WGL_CONTEXT_STATE + #define GLFW_WGL_LIBRARY_CONTEXT_STATE +#endif + +#if defined(_GLFW_COCOA) + #include "cocoa_platform.h" +#else + #define GLFW_COCOA_WINDOW_STATE + #define GLFW_COCOA_MONITOR_STATE + #define GLFW_COCOA_CURSOR_STATE + #define GLFW_COCOA_LIBRARY_WINDOW_STATE + #define GLFW_NSGL_CONTEXT_STATE + #define GLFW_NSGL_LIBRARY_CONTEXT_STATE +#endif + +#if defined(_GLFW_WAYLAND) + #include "wl_platform.h" +#else + #define GLFW_WAYLAND_WINDOW_STATE + #define GLFW_WAYLAND_MONITOR_STATE + #define GLFW_WAYLAND_CURSOR_STATE + #define GLFW_WAYLAND_LIBRARY_WINDOW_STATE +#endif + +#if defined(_GLFW_X11) + #include "x11_platform.h" +#else + #define GLFW_X11_WINDOW_STATE + #define GLFW_X11_MONITOR_STATE + #define GLFW_X11_CURSOR_STATE + #define GLFW_X11_LIBRARY_WINDOW_STATE + #define GLFW_GLX_CONTEXT_STATE + #define GLFW_GLX_LIBRARY_CONTEXT_STATE +#endif + +#include "null_joystick.h" + +#if defined(_GLFW_WIN32) + #include "win32_joystick.h" +#else + #define GLFW_WIN32_JOYSTICK_STATE + #define GLFW_WIN32_LIBRARY_JOYSTICK_STATE +#endif + +#if defined(_GLFW_COCOA) + #include "cocoa_joystick.h" +#else + #define GLFW_COCOA_JOYSTICK_STATE + #define GLFW_COCOA_LIBRARY_JOYSTICK_STATE +#endif + +#if (defined(_GLFW_X11) || defined(_GLFW_WAYLAND)) && defined(__linux__) + #define GLFW_BUILD_LINUX_JOYSTICK +#endif + +#if defined(GLFW_BUILD_LINUX_JOYSTICK) + #include "linux_joystick.h" +#else + #define GLFW_LINUX_JOYSTICK_STATE + #define GLFW_LINUX_LIBRARY_JOYSTICK_STATE +#endif + +#define GLFW_PLATFORM_WINDOW_STATE \ + GLFW_WIN32_WINDOW_STATE \ + GLFW_COCOA_WINDOW_STATE \ + GLFW_WAYLAND_WINDOW_STATE \ + GLFW_X11_WINDOW_STATE \ + GLFW_NULL_WINDOW_STATE \ + +#define GLFW_PLATFORM_MONITOR_STATE \ + GLFW_WIN32_MONITOR_STATE \ + GLFW_COCOA_MONITOR_STATE \ + GLFW_WAYLAND_MONITOR_STATE \ + GLFW_X11_MONITOR_STATE \ + GLFW_NULL_MONITOR_STATE \ + +#define GLFW_PLATFORM_CURSOR_STATE \ + GLFW_WIN32_CURSOR_STATE \ + GLFW_COCOA_CURSOR_STATE \ + GLFW_WAYLAND_CURSOR_STATE \ + GLFW_X11_CURSOR_STATE \ + GLFW_NULL_CURSOR_STATE \ + +#define GLFW_PLATFORM_JOYSTICK_STATE \ + GLFW_WIN32_JOYSTICK_STATE \ + GLFW_COCOA_JOYSTICK_STATE \ + GLFW_LINUX_JOYSTICK_STATE + +#define GLFW_PLATFORM_LIBRARY_WINDOW_STATE \ + GLFW_WIN32_LIBRARY_WINDOW_STATE \ + GLFW_COCOA_LIBRARY_WINDOW_STATE \ + GLFW_WAYLAND_LIBRARY_WINDOW_STATE \ + GLFW_X11_LIBRARY_WINDOW_STATE \ + GLFW_NULL_LIBRARY_WINDOW_STATE \ + +#define GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \ + GLFW_WIN32_LIBRARY_JOYSTICK_STATE \ + GLFW_COCOA_LIBRARY_JOYSTICK_STATE \ + GLFW_LINUX_LIBRARY_JOYSTICK_STATE + +#define GLFW_PLATFORM_CONTEXT_STATE \ + GLFW_WGL_CONTEXT_STATE \ + GLFW_NSGL_CONTEXT_STATE \ + GLFW_GLX_CONTEXT_STATE + +#define GLFW_PLATFORM_LIBRARY_CONTEXT_STATE \ + GLFW_WGL_LIBRARY_CONTEXT_STATE \ + GLFW_NSGL_LIBRARY_CONTEXT_STATE \ + GLFW_GLX_LIBRARY_CONTEXT_STATE + +#if defined(_WIN32) + #define GLFW_BUILD_WIN32_THREAD +#else + #define GLFW_BUILD_POSIX_THREAD +#endif + +#if defined(GLFW_BUILD_WIN32_THREAD) + #include "win32_thread.h" + #define GLFW_PLATFORM_TLS_STATE GLFW_WIN32_TLS_STATE + #define GLFW_PLATFORM_MUTEX_STATE GLFW_WIN32_MUTEX_STATE +#elif defined(GLFW_BUILD_POSIX_THREAD) + #include "posix_thread.h" + #define GLFW_PLATFORM_TLS_STATE GLFW_POSIX_TLS_STATE + #define GLFW_PLATFORM_MUTEX_STATE GLFW_POSIX_MUTEX_STATE +#endif + +#if defined(_WIN32) + #define GLFW_BUILD_WIN32_TIMER +#elif defined(__APPLE__) + #define GLFW_BUILD_COCOA_TIMER +#else + #define GLFW_BUILD_POSIX_TIMER +#endif + +#if defined(GLFW_BUILD_WIN32_TIMER) + #include "win32_time.h" + #define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_WIN32_LIBRARY_TIMER_STATE +#elif defined(GLFW_BUILD_COCOA_TIMER) + #include "cocoa_time.h" + #define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_COCOA_LIBRARY_TIMER_STATE +#elif defined(GLFW_BUILD_POSIX_TIMER) + #include "posix_time.h" + #define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_POSIX_LIBRARY_TIMER_STATE +#endif + +#if defined(_WIN32) + #define GLFW_BUILD_WIN32_MODULE +#else + #define GLFW_BUILD_POSIX_MODULE +#endif + +#if defined(_GLFW_WAYLAND) || defined(_GLFW_X11) + #define GLFW_BUILD_POSIX_POLL +#endif + diff --git a/src/posix_module.c b/src/posix_module.c new file mode 100644 index 00000000..ba5024a3 --- /dev/null +++ b/src/posix_module.c @@ -0,0 +1,55 @@ +//======================================================================== +// GLFW 3.4 POSIX - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2021 Camilla Löwy +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== +// It is fine to use C99 in this file because it will not be built with VS +//======================================================================== + +#include "internal.h" + +#if defined(GLFW_BUILD_POSIX_MODULE) + +#include + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +void* _glfwPlatformLoadModule(const char* path) +{ + return dlopen(path, RTLD_LAZY | RTLD_LOCAL); +} + +void _glfwPlatformFreeModule(void* module) +{ + dlclose(module); +} + +GLFWproc _glfwPlatformGetModuleSymbol(void* module, const char* name) +{ + return dlsym(module, name); +} + +#endif // GLFW_BUILD_POSIX_MODULE + diff --git a/src/posix_poll.c b/src/posix_poll.c new file mode 100644 index 00000000..a5016a13 --- /dev/null +++ b/src/posix_poll.c @@ -0,0 +1,85 @@ +//======================================================================== +// GLFW 3.4 POSIX - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2022 Camilla Löwy +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== +// It is fine to use C99 in this file because it will not be built with VS +//======================================================================== + +#define _GNU_SOURCE + +#include "internal.h" + +#if defined(GLFW_BUILD_POSIX_POLL) + +#include +#include +#include + +GLFWbool _glfwPollPOSIX(struct pollfd* fds, nfds_t count, double* timeout) +{ + for (;;) + { + if (timeout) + { + const uint64_t base = _glfwPlatformGetTimerValue(); + +#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) + const time_t seconds = (time_t) *timeout; + const long nanoseconds = (long) ((*timeout - seconds) * 1e9); + const struct timespec ts = { seconds, nanoseconds }; + const int result = ppoll(fds, count, &ts, NULL); +#elif defined(__NetBSD__) + const time_t seconds = (time_t) *timeout; + const long nanoseconds = (long) ((*timeout - seconds) * 1e9); + const struct timespec ts = { seconds, nanoseconds }; + const int result = pollts(fds, count, &ts, NULL); +#else + const int milliseconds = (int) (*timeout * 1e3); + const int result = poll(fds, count, milliseconds); +#endif + const int error = errno; // clock_gettime may overwrite our error + + *timeout -= (_glfwPlatformGetTimerValue() - base) / + (double) _glfwPlatformGetTimerFrequency(); + + if (result > 0) + return GLFW_TRUE; + else if (result == -1 && error != EINTR && error != EAGAIN) + return GLFW_FALSE; + else if (*timeout <= 0.0) + return GLFW_FALSE; + } + else + { + const int result = poll(fds, count, -1); + if (result > 0) + return GLFW_TRUE; + else if (result == -1 && errno != EINTR && errno != EAGAIN) + return GLFW_FALSE; + } + } +} + +#endif // GLFW_BUILD_POSIX_POLL + diff --git a/src/posix_poll.h b/src/posix_poll.h new file mode 100644 index 00000000..1effd1cd --- /dev/null +++ b/src/posix_poll.h @@ -0,0 +1,32 @@ +//======================================================================== +// GLFW 3.4 POSIX - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2022 Camilla Löwy +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== +// It is fine to use C99 in this file because it will not be built with VS +//======================================================================== + +#include + +GLFWbool _glfwPollPOSIX(struct pollfd* fds, nfds_t count, double* timeout); + diff --git a/src/posix_thread.c b/src/posix_thread.c index 02361457..4ce55526 100644 --- a/src/posix_thread.c +++ b/src/posix_thread.c @@ -29,6 +29,8 @@ #include "internal.h" +#if defined(GLFW_BUILD_POSIX_THREAD) + #include #include @@ -103,3 +105,5 @@ void _glfwPlatformUnlockMutex(_GLFWmutex* mutex) pthread_mutex_unlock(&mutex->posix.handle); } +#endif // GLFW_BUILD_POSIX_THREAD + diff --git a/src/posix_thread.h b/src/posix_thread.h index 85ce596c..5a5d7b7c 100644 --- a/src/posix_thread.h +++ b/src/posix_thread.h @@ -27,8 +27,8 @@ #include -#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsPOSIX posix -#define _GLFW_PLATFORM_MUTEX_STATE _GLFWmutexPOSIX posix +#define GLFW_POSIX_TLS_STATE _GLFWtlsPOSIX posix; +#define GLFW_POSIX_MUTEX_STATE _GLFWmutexPOSIX posix; // POSIX-specific thread local storage data @@ -37,7 +37,6 @@ typedef struct _GLFWtlsPOSIX { GLFWbool allocated; pthread_key_t key; - } _GLFWtlsPOSIX; // POSIX-specific mutex data @@ -46,6 +45,5 @@ typedef struct _GLFWmutexPOSIX { GLFWbool allocated; pthread_mutex_t handle; - } _GLFWmutexPOSIX; diff --git a/src/posix_time.c b/src/posix_time.c index b47a0b13..caed678e 100644 --- a/src/posix_time.c +++ b/src/posix_time.c @@ -29,17 +29,17 @@ #include "internal.h" +#if defined(GLFW_BUILD_POSIX_TIMER) + #include #include ////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// +////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -// Initialise timer -// -void _glfwInitTimerPOSIX(void) +void _glfwPlatformInitTimer(void) { _glfw.timer.posix.clock = CLOCK_REALTIME; _glfw.timer.posix.frequency = 1000000000; @@ -51,11 +51,6 @@ void _glfwInitTimerPOSIX(void) #endif } - -////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// - uint64_t _glfwPlatformGetTimerValue(void) { struct timespec ts; @@ -68,3 +63,5 @@ uint64_t _glfwPlatformGetTimerFrequency(void) return _glfw.timer.posix.frequency; } +#endif // GLFW_BUILD_POSIX_TIMER + diff --git a/src/posix_time.h b/src/posix_time.h index 17805cf6..94374adb 100644 --- a/src/posix_time.h +++ b/src/posix_time.h @@ -25,7 +25,7 @@ // //======================================================================== -#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerPOSIX posix +#define GLFW_POSIX_LIBRARY_TIMER_STATE _GLFWtimerPOSIX posix; #include #include @@ -37,9 +37,5 @@ typedef struct _GLFWtimerPOSIX { clockid_t clock; uint64_t frequency; - } _GLFWtimerPOSIX; - -void _glfwInitTimerPOSIX(void); - diff --git a/src/vulkan.c b/src/vulkan.c index e810ca06..64a4650f 100644 --- a/src/vulkan.c +++ b/src/vulkan.c @@ -45,45 +45,52 @@ GLFWbool _glfwInitVulkan(int mode) { VkResult err; VkExtensionProperties* ep; + PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; uint32_t i, count; if (_glfw.vk.available) return GLFW_TRUE; -#if !defined(_GLFW_VULKAN_STATIC) + if (_glfw.hints.init.vulkanLoader) + _glfw.vk.GetInstanceProcAddr = _glfw.hints.init.vulkanLoader; + else + { #if defined(_GLFW_VULKAN_LIBRARY) - _glfw.vk.handle = _glfw_dlopen(_GLFW_VULKAN_LIBRARY); + _glfw.vk.handle = _glfwPlatformLoadModule(_GLFW_VULKAN_LIBRARY); #elif defined(_GLFW_WIN32) - _glfw.vk.handle = _glfw_dlopen("vulkan-1.dll"); + _glfw.vk.handle = _glfwPlatformLoadModule("vulkan-1.dll"); #elif defined(_GLFW_COCOA) - _glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib"); - if (!_glfw.vk.handle) - _glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS(); + _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib"); + if (!_glfw.vk.handle) + _glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa(); +#elif defined(__OpenBSD__) || defined(__NetBSD__) + _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so"); #else - _glfw.vk.handle = _glfw_dlopen("libvulkan.so.1"); + _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so.1"); #endif - if (!_glfw.vk.handle) - { - if (mode == _GLFW_REQUIRE_LOADER) - _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found"); + if (!_glfw.vk.handle) + { + if (mode == _GLFW_REQUIRE_LOADER) + _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found"); - return GLFW_FALSE; + return GLFW_FALSE; + } + + _glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) + _glfwPlatformGetModuleSymbol(_glfw.vk.handle, "vkGetInstanceProcAddr"); + if (!_glfw.vk.GetInstanceProcAddr) + { + _glfwInputError(GLFW_API_UNAVAILABLE, + "Vulkan: Loader does not export vkGetInstanceProcAddr"); + + _glfwTerminateVulkan(); + return GLFW_FALSE; + } } - _glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) - _glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr"); - if (!_glfw.vk.GetInstanceProcAddr) - { - _glfwInputError(GLFW_API_UNAVAILABLE, - "Vulkan: Loader does not export vkGetInstanceProcAddr"); - - _glfwTerminateVulkan(); - return GLFW_FALSE; - } - - _glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties) + vkEnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties) vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties"); - if (!_glfw.vk.EnumerateInstanceExtensionProperties) + if (!vkEnumerateInstanceExtensionProperties) { _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties"); @@ -91,7 +98,6 @@ GLFWbool _glfwInitVulkan(int mode) _glfwTerminateVulkan(); return GLFW_FALSE; } -#endif // _GLFW_VULKAN_STATIC err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL); if (err) @@ -126,40 +132,33 @@ GLFWbool _glfwInitVulkan(int mode) { if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0) _glfw.vk.KHR_surface = GLFW_TRUE; -#if defined(_GLFW_WIN32) else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0) _glfw.vk.KHR_win32_surface = GLFW_TRUE; -#elif defined(_GLFW_COCOA) else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0) _glfw.vk.MVK_macos_surface = GLFW_TRUE; else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0) _glfw.vk.EXT_metal_surface = GLFW_TRUE; -#elif defined(_GLFW_X11) else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0) _glfw.vk.KHR_xlib_surface = GLFW_TRUE; else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0) _glfw.vk.KHR_xcb_surface = GLFW_TRUE; -#elif defined(_GLFW_WAYLAND) else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0) _glfw.vk.KHR_wayland_surface = GLFW_TRUE; -#endif } _glfw_free(ep); _glfw.vk.available = GLFW_TRUE; - _glfwPlatformGetRequiredInstanceExtensions(_glfw.vk.extensions); + _glfw.platform.getRequiredInstanceExtensions(_glfw.vk.extensions); return GLFW_TRUE; } void _glfwTerminateVulkan(void) { -#if !defined(_GLFW_VULKAN_STATIC) if (_glfw.vk.handle) - _glfw_dlclose(_glfw.vk.handle); -#endif + _glfwPlatformFreeModule(_glfw.vk.handle); } const char* _glfwGetVulkanResultString(VkResult result) @@ -257,17 +256,16 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) return NULL; + // NOTE: Vulkan 1.0 and 1.1 vkGetInstanceProcAddr cannot return itself + if (strcmp(procname, "vkGetInstanceProcAddr") == 0) + return (GLFWvkproc) vkGetInstanceProcAddr; + proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname); -#if defined(_GLFW_VULKAN_STATIC) if (!proc) { - if (strcmp(procname, "vkGetInstanceProcAddr") == 0) - return (GLFWvkproc) vkGetInstanceProcAddr; + if (_glfw.vk.handle) + proc = (GLFWvkproc) _glfwPlatformGetModuleSymbol(_glfw.vk.handle, procname); } -#else - if (!proc) - proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname); -#endif return proc; } @@ -291,9 +289,9 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, return GLFW_FALSE; } - return _glfwPlatformGetPhysicalDevicePresentationSupport(instance, - device, - queuefamily); + return _glfw.platform.getPhysicalDevicePresentationSupport(instance, + device, + queuefamily); } GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, @@ -327,6 +325,6 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR; } - return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface); + return _glfw.platform.createWindowSurface(instance, window, allocator, surface); } diff --git a/src/wgl_context.c b/src/wgl_context.c index 62055847..cfe24b27 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -29,15 +29,17 @@ #include "internal.h" +#if defined(_GLFW_WIN32) + #include #include // Return the value corresponding to the specified attribute // -static int findPixelFormatAttribValue(const int* attribs, - int attribCount, - const int* values, - int attrib) +static int findPixelFormatAttribValueWGL(const int* attribs, + int attribCount, + const int* values, + int attrib) { int i; @@ -52,19 +54,19 @@ static int findPixelFormatAttribValue(const int* attribs, return 0; } -#define addAttrib(a) \ +#define ADD_ATTRIB(a) \ { \ assert((size_t) attribCount < sizeof(attribs) / sizeof(attribs[0])); \ attribs[attribCount++] = a; \ } -#define findAttribValue(a) \ - findPixelFormatAttribValue(attribs, attribCount, values, a) +#define FIND_ATTRIB_VALUE(a) \ + findPixelFormatAttribValueWGL(attribs, attribCount, values, a) // Return a list of available and usable framebuffer configs // -static int choosePixelFormat(_GLFWwindow* window, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig) +static int choosePixelFormatWGL(_GLFWwindow* window, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig) { _GLFWfbconfig* usableConfigs; const _GLFWfbconfig* closest; @@ -72,62 +74,50 @@ static int choosePixelFormat(_GLFWwindow* window, int attribs[40]; int values[sizeof(attribs) / sizeof(attribs[0])]; + nativeCount = DescribePixelFormat(window->context.wgl.dc, + 1, + sizeof(PIXELFORMATDESCRIPTOR), + NULL); + if (_glfw.wgl.ARB_pixel_format) { - const int attrib = WGL_NUMBER_PIXEL_FORMATS_ARB; - - if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc, - 1, 0, 1, &attrib, &nativeCount)) - { - _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "WGL: Failed to retrieve pixel format attribute"); - return 0; - } - - addAttrib(WGL_SUPPORT_OPENGL_ARB); - addAttrib(WGL_DRAW_TO_WINDOW_ARB); - addAttrib(WGL_PIXEL_TYPE_ARB); - addAttrib(WGL_ACCELERATION_ARB); - addAttrib(WGL_RED_BITS_ARB); - addAttrib(WGL_RED_SHIFT_ARB); - addAttrib(WGL_GREEN_BITS_ARB); - addAttrib(WGL_GREEN_SHIFT_ARB); - addAttrib(WGL_BLUE_BITS_ARB); - addAttrib(WGL_BLUE_SHIFT_ARB); - addAttrib(WGL_ALPHA_BITS_ARB); - addAttrib(WGL_ALPHA_SHIFT_ARB); - addAttrib(WGL_DEPTH_BITS_ARB); - addAttrib(WGL_STENCIL_BITS_ARB); - addAttrib(WGL_ACCUM_BITS_ARB); - addAttrib(WGL_ACCUM_RED_BITS_ARB); - addAttrib(WGL_ACCUM_GREEN_BITS_ARB); - addAttrib(WGL_ACCUM_BLUE_BITS_ARB); - addAttrib(WGL_ACCUM_ALPHA_BITS_ARB); - addAttrib(WGL_AUX_BUFFERS_ARB); - addAttrib(WGL_STEREO_ARB); - addAttrib(WGL_DOUBLE_BUFFER_ARB); + ADD_ATTRIB(WGL_SUPPORT_OPENGL_ARB); + ADD_ATTRIB(WGL_DRAW_TO_WINDOW_ARB); + ADD_ATTRIB(WGL_PIXEL_TYPE_ARB); + ADD_ATTRIB(WGL_ACCELERATION_ARB); + ADD_ATTRIB(WGL_RED_BITS_ARB); + ADD_ATTRIB(WGL_RED_SHIFT_ARB); + ADD_ATTRIB(WGL_GREEN_BITS_ARB); + ADD_ATTRIB(WGL_GREEN_SHIFT_ARB); + ADD_ATTRIB(WGL_BLUE_BITS_ARB); + ADD_ATTRIB(WGL_BLUE_SHIFT_ARB); + ADD_ATTRIB(WGL_ALPHA_BITS_ARB); + ADD_ATTRIB(WGL_ALPHA_SHIFT_ARB); + ADD_ATTRIB(WGL_DEPTH_BITS_ARB); + ADD_ATTRIB(WGL_STENCIL_BITS_ARB); + ADD_ATTRIB(WGL_ACCUM_BITS_ARB); + ADD_ATTRIB(WGL_ACCUM_RED_BITS_ARB); + ADD_ATTRIB(WGL_ACCUM_GREEN_BITS_ARB); + ADD_ATTRIB(WGL_ACCUM_BLUE_BITS_ARB); + ADD_ATTRIB(WGL_ACCUM_ALPHA_BITS_ARB); + ADD_ATTRIB(WGL_AUX_BUFFERS_ARB); + ADD_ATTRIB(WGL_STEREO_ARB); + ADD_ATTRIB(WGL_DOUBLE_BUFFER_ARB); if (_glfw.wgl.ARB_multisample) - addAttrib(WGL_SAMPLES_ARB); + ADD_ATTRIB(WGL_SAMPLES_ARB); if (ctxconfig->client == GLFW_OPENGL_API) { if (_glfw.wgl.ARB_framebuffer_sRGB || _glfw.wgl.EXT_framebuffer_sRGB) - addAttrib(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB); + ADD_ATTRIB(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB); } else { if (_glfw.wgl.EXT_colorspace) - addAttrib(WGL_COLORSPACE_EXT); + ADD_ATTRIB(WGL_COLORSPACE_EXT); } } - else - { - nativeCount = DescribePixelFormat(window->context.wgl.dc, - 1, - sizeof(PIXELFORMATDESCRIPTOR), - NULL); - } usableConfigs = _glfw_calloc(nativeCount, sizeof(_GLFWfbconfig)); @@ -152,48 +142,48 @@ static int choosePixelFormat(_GLFWwindow* window, return 0; } - if (!findAttribValue(WGL_SUPPORT_OPENGL_ARB) || - !findAttribValue(WGL_DRAW_TO_WINDOW_ARB)) + if (!FIND_ATTRIB_VALUE(WGL_SUPPORT_OPENGL_ARB) || + !FIND_ATTRIB_VALUE(WGL_DRAW_TO_WINDOW_ARB)) { continue; } - if (findAttribValue(WGL_PIXEL_TYPE_ARB) != WGL_TYPE_RGBA_ARB) + if (FIND_ATTRIB_VALUE(WGL_PIXEL_TYPE_ARB) != WGL_TYPE_RGBA_ARB) continue; - if (findAttribValue(WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB) + if (FIND_ATTRIB_VALUE(WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB) continue; - if (findAttribValue(WGL_DOUBLE_BUFFER_ARB) != fbconfig->doublebuffer) + if (FIND_ATTRIB_VALUE(WGL_DOUBLE_BUFFER_ARB) != fbconfig->doublebuffer) continue; - u->redBits = findAttribValue(WGL_RED_BITS_ARB); - u->greenBits = findAttribValue(WGL_GREEN_BITS_ARB); - u->blueBits = findAttribValue(WGL_BLUE_BITS_ARB); - u->alphaBits = findAttribValue(WGL_ALPHA_BITS_ARB); + u->redBits = FIND_ATTRIB_VALUE(WGL_RED_BITS_ARB); + u->greenBits = FIND_ATTRIB_VALUE(WGL_GREEN_BITS_ARB); + u->blueBits = FIND_ATTRIB_VALUE(WGL_BLUE_BITS_ARB); + u->alphaBits = FIND_ATTRIB_VALUE(WGL_ALPHA_BITS_ARB); - u->depthBits = findAttribValue(WGL_DEPTH_BITS_ARB); - u->stencilBits = findAttribValue(WGL_STENCIL_BITS_ARB); + u->depthBits = FIND_ATTRIB_VALUE(WGL_DEPTH_BITS_ARB); + u->stencilBits = FIND_ATTRIB_VALUE(WGL_STENCIL_BITS_ARB); - u->accumRedBits = findAttribValue(WGL_ACCUM_RED_BITS_ARB); - u->accumGreenBits = findAttribValue(WGL_ACCUM_GREEN_BITS_ARB); - u->accumBlueBits = findAttribValue(WGL_ACCUM_BLUE_BITS_ARB); - u->accumAlphaBits = findAttribValue(WGL_ACCUM_ALPHA_BITS_ARB); + u->accumRedBits = FIND_ATTRIB_VALUE(WGL_ACCUM_RED_BITS_ARB); + u->accumGreenBits = FIND_ATTRIB_VALUE(WGL_ACCUM_GREEN_BITS_ARB); + u->accumBlueBits = FIND_ATTRIB_VALUE(WGL_ACCUM_BLUE_BITS_ARB); + u->accumAlphaBits = FIND_ATTRIB_VALUE(WGL_ACCUM_ALPHA_BITS_ARB); - u->auxBuffers = findAttribValue(WGL_AUX_BUFFERS_ARB); + u->auxBuffers = FIND_ATTRIB_VALUE(WGL_AUX_BUFFERS_ARB); - if (findAttribValue(WGL_STEREO_ARB)) + if (FIND_ATTRIB_VALUE(WGL_STEREO_ARB)) u->stereo = GLFW_TRUE; if (_glfw.wgl.ARB_multisample) - u->samples = findAttribValue(WGL_SAMPLES_ARB); + u->samples = FIND_ATTRIB_VALUE(WGL_SAMPLES_ARB); if (ctxconfig->client == GLFW_OPENGL_API) { if (_glfw.wgl.ARB_framebuffer_sRGB || _glfw.wgl.EXT_framebuffer_sRGB) { - if (findAttribValue(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB)) + if (FIND_ATTRIB_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB)) u->sRGB = GLFW_TRUE; } } @@ -201,7 +191,7 @@ static int choosePixelFormat(_GLFWwindow* window, { if (_glfw.wgl.EXT_colorspace) { - if (findAttribValue(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT) + if (FIND_ATTRIB_VALUE(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT) u->sRGB = GLFW_TRUE; } } @@ -290,8 +280,8 @@ static int choosePixelFormat(_GLFWwindow* window, return pixelFormat; } -#undef addAttrib -#undef findAttribValue +#undef ADD_ATTRIB +#undef FIND_ATTRIB_VALUE static void makeContextCurrentWGL(_GLFWwindow* window) { @@ -322,14 +312,12 @@ static void swapBuffersWGL(_GLFWwindow* window) { if (!window->monitor) { - if (IsWindowsVistaOrGreater()) + // HACK: Use DwmFlush when desktop composition is enabled on Windows Vista and 7 + if (!IsWindows8OrGreater() && IsWindowsVistaOrGreater()) { - // DWM Composition is always enabled on Win8+ - BOOL enabled = IsWindows8OrGreater(); + BOOL enabled = FALSE; - // HACK: Use DwmFlush when desktop composition is enabled - if (enabled || - (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)) + if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled) { int count = abs(window->context.wgl.interval); while (count--) @@ -349,15 +337,13 @@ static void swapIntervalWGL(int interval) if (!window->monitor) { - if (IsWindowsVistaOrGreater()) + // HACK: Disable WGL swap interval when desktop composition is enabled on Windows + // Vista and 7 to avoid interfering with DWM vsync + if (!IsWindows8OrGreater() && IsWindowsVistaOrGreater()) { - // DWM Composition is always enabled on Win8+ - BOOL enabled = IsWindows8OrGreater(); + BOOL enabled = FALSE; - // HACK: Disable WGL swap interval when desktop composition is enabled to - // avoid interfering with DWM vsync - if (enabled || - (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)) + if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled) interval = 0; } } @@ -387,7 +373,7 @@ static GLFWglproc getProcAddressWGL(const char* procname) if (proc) return proc; - return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname); + return (GLFWglproc) _glfwPlatformGetModuleSymbol(_glfw.wgl.instance, procname); } static void destroyContextWGL(_GLFWwindow* window) @@ -399,11 +385,6 @@ static void destroyContextWGL(_GLFWwindow* window) } } - -////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// -////////////////////////////////////////////////////////////////////////// - // Initialize WGL // GLFWbool _glfwInitWGL(void) @@ -415,7 +396,7 @@ GLFWbool _glfwInitWGL(void) if (_glfw.wgl.instance) return GLFW_TRUE; - _glfw.wgl.instance = LoadLibraryA("opengl32.dll"); + _glfw.wgl.instance = _glfwPlatformLoadModule("opengl32.dll"); if (!_glfw.wgl.instance) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, @@ -424,19 +405,19 @@ GLFWbool _glfwInitWGL(void) } _glfw.wgl.CreateContext = (PFN_wglCreateContext) - GetProcAddress(_glfw.wgl.instance, "wglCreateContext"); + _glfwPlatformGetModuleSymbol(_glfw.wgl.instance, "wglCreateContext"); _glfw.wgl.DeleteContext = (PFN_wglDeleteContext) - GetProcAddress(_glfw.wgl.instance, "wglDeleteContext"); + _glfwPlatformGetModuleSymbol(_glfw.wgl.instance, "wglDeleteContext"); _glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress) - GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress"); + _glfwPlatformGetModuleSymbol(_glfw.wgl.instance, "wglGetProcAddress"); _glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC) - GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC"); + _glfwPlatformGetModuleSymbol(_glfw.wgl.instance, "wglGetCurrentDC"); _glfw.wgl.GetCurrentContext = (PFN_wglGetCurrentContext) - GetProcAddress(_glfw.wgl.instance, "wglGetCurrentContext"); + _glfwPlatformGetModuleSymbol(_glfw.wgl.instance, "wglGetCurrentContext"); _glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent) - GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent"); + _glfwPlatformGetModuleSymbol(_glfw.wgl.instance, "wglMakeCurrent"); _glfw.wgl.ShareLists = (PFN_wglShareLists) - GetProcAddress(_glfw.wgl.instance, "wglShareLists"); + _glfwPlatformGetModuleSymbol(_glfw.wgl.instance, "wglShareLists"); // NOTE: A dummy context has to be created for opengl32.dll to load the // OpenGL ICD, from which we can then query WGL extensions @@ -529,10 +510,10 @@ GLFWbool _glfwInitWGL(void) void _glfwTerminateWGL(void) { if (_glfw.wgl.instance) - FreeLibrary(_glfw.wgl.instance); + _glfwPlatformFreeModule(_glfw.wgl.instance); } -#define setAttrib(a, v) \ +#define SET_ATTRIB(a, v) \ { \ assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ attribs[index++] = a; \ @@ -561,7 +542,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, return GLFW_FALSE; } - pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig); + pixelFormat = choosePixelFormatWGL(window, ctxconfig, fbconfig); if (!pixelFormat) return GLFW_FALSE; @@ -640,13 +621,13 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, { if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION) { - setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, - WGL_NO_RESET_NOTIFICATION_ARB); + SET_ATTRIB(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, + WGL_NO_RESET_NOTIFICATION_ARB); } else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET) { - setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, - WGL_LOSE_CONTEXT_ON_RESET_ARB); + SET_ATTRIB(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, + WGL_LOSE_CONTEXT_ON_RESET_ARB); } flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB; @@ -659,13 +640,13 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, { if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE) { - setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB, - WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB); + SET_ATTRIB(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB, + WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB); } else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH) { - setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB, - WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB); + SET_ATTRIB(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB, + WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB); } } } @@ -673,7 +654,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, if (ctxconfig->noerror) { if (_glfw.wgl.ARB_create_context_no_error) - setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE); + SET_ATTRIB(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE); } // NOTE: Only request an explicitly versioned context when necessary, as @@ -681,17 +662,17 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, // highest version supported by the driver if (ctxconfig->major != 1 || ctxconfig->minor != 0) { - setAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major); - setAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor); + SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major); + SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor); } if (flags) - setAttrib(WGL_CONTEXT_FLAGS_ARB, flags); + SET_ATTRIB(WGL_CONTEXT_FLAGS_ARB, flags); if (mask) - setAttrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask); + SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, mask); - setAttrib(0, 0); + SET_ATTRIB(0, 0); window->context.wgl.handle = wglCreateContextAttribsARB(window->context.wgl.dc, share, attribs); @@ -774,19 +755,21 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, return GLFW_TRUE; } -#undef setAttrib - - -////////////////////////////////////////////////////////////////////////// -////// GLFW native API ////// -////////////////////////////////////////////////////////////////////////// +#undef SET_ATTRIB GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - if (window->context.client == GLFW_NO_API) + if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32) + { + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, + "WGL: Platform not initialized"); + return NULL; + } + + if (window->context.source != GLFW_NATIVE_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return NULL; @@ -795,3 +778,5 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle) return window->context.wgl.handle; } +#endif // _GLFW_WIN32 + diff --git a/src/wgl_context.h b/src/wgl_context.h deleted file mode 100644 index 2cf7e4e5..00000000 --- a/src/wgl_context.h +++ /dev/null @@ -1,160 +0,0 @@ -//======================================================================== -// GLFW 3.4 WGL - www.glfw.org -//------------------------------------------------------------------------ -// Copyright (c) 2002-2006 Marcus Geelnard -// Copyright (c) 2006-2018 Camilla Löwy -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would -// be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -// -//======================================================================== - -#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 -#define WGL_SUPPORT_OPENGL_ARB 0x2010 -#define WGL_DRAW_TO_WINDOW_ARB 0x2001 -#define WGL_PIXEL_TYPE_ARB 0x2013 -#define WGL_TYPE_RGBA_ARB 0x202b -#define WGL_ACCELERATION_ARB 0x2003 -#define WGL_NO_ACCELERATION_ARB 0x2025 -#define WGL_RED_BITS_ARB 0x2015 -#define WGL_RED_SHIFT_ARB 0x2016 -#define WGL_GREEN_BITS_ARB 0x2017 -#define WGL_GREEN_SHIFT_ARB 0x2018 -#define WGL_BLUE_BITS_ARB 0x2019 -#define WGL_BLUE_SHIFT_ARB 0x201a -#define WGL_ALPHA_BITS_ARB 0x201b -#define WGL_ALPHA_SHIFT_ARB 0x201c -#define WGL_ACCUM_BITS_ARB 0x201d -#define WGL_ACCUM_RED_BITS_ARB 0x201e -#define WGL_ACCUM_GREEN_BITS_ARB 0x201f -#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 -#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 -#define WGL_DEPTH_BITS_ARB 0x2022 -#define WGL_STENCIL_BITS_ARB 0x2023 -#define WGL_AUX_BUFFERS_ARB 0x2024 -#define WGL_STEREO_ARB 0x2012 -#define WGL_DOUBLE_BUFFER_ARB 0x2011 -#define WGL_SAMPLES_ARB 0x2042 -#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9 -#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001 -#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 -#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 -#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 -#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 -#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define WGL_CONTEXT_FLAGS_ARB 0x2094 -#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 -#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 -#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 -#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 -#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261 -#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097 -#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0 -#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 -#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3 -#define WGL_COLORSPACE_EXT 0x309d -#define WGL_COLORSPACE_SRGB_EXT 0x3089 - -#define ERROR_INVALID_VERSION_ARB 0x2095 -#define ERROR_INVALID_PROFILE_ARB 0x2096 -#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 - -// WGL extension pointer typedefs -typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int); -typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*); -typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void); -typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC); -typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC,HGLRC,const int*); -#define wglSwapIntervalEXT _glfw.wgl.SwapIntervalEXT -#define wglGetPixelFormatAttribivARB _glfw.wgl.GetPixelFormatAttribivARB -#define wglGetExtensionsStringEXT _glfw.wgl.GetExtensionsStringEXT -#define wglGetExtensionsStringARB _glfw.wgl.GetExtensionsStringARB -#define wglCreateContextAttribsARB _glfw.wgl.CreateContextAttribsARB - -// opengl32.dll function pointer typedefs -typedef HGLRC (WINAPI * PFN_wglCreateContext)(HDC); -typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC); -typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR); -typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void); -typedef HGLRC (WINAPI * PFN_wglGetCurrentContext)(void); -typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC); -typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC); -#define wglCreateContext _glfw.wgl.CreateContext -#define wglDeleteContext _glfw.wgl.DeleteContext -#define wglGetProcAddress _glfw.wgl.GetProcAddress -#define wglGetCurrentDC _glfw.wgl.GetCurrentDC -#define wglGetCurrentContext _glfw.wgl.GetCurrentContext -#define wglMakeCurrent _glfw.wgl.MakeCurrent -#define wglShareLists _glfw.wgl.ShareLists - -#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL wgl -#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl - - -// WGL-specific per-context data -// -typedef struct _GLFWcontextWGL -{ - HDC dc; - HGLRC handle; - int interval; - -} _GLFWcontextWGL; - -// WGL-specific global data -// -typedef struct _GLFWlibraryWGL -{ - HINSTANCE instance; - PFN_wglCreateContext CreateContext; - PFN_wglDeleteContext DeleteContext; - PFN_wglGetProcAddress GetProcAddress; - PFN_wglGetCurrentDC GetCurrentDC; - PFN_wglGetCurrentContext GetCurrentContext; - PFN_wglMakeCurrent MakeCurrent; - PFN_wglShareLists ShareLists; - - PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT; - PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB; - PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT; - PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB; - PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; - GLFWbool EXT_swap_control; - GLFWbool EXT_colorspace; - GLFWbool ARB_multisample; - GLFWbool ARB_framebuffer_sRGB; - GLFWbool EXT_framebuffer_sRGB; - GLFWbool ARB_pixel_format; - GLFWbool ARB_create_context; - GLFWbool ARB_create_context_profile; - GLFWbool EXT_create_context_es2_profile; - GLFWbool ARB_create_context_robustness; - GLFWbool ARB_create_context_no_error; - GLFWbool ARB_context_flush_control; - -} _GLFWlibraryWGL; - - -GLFWbool _glfwInitWGL(void); -void _glfwTerminateWGL(void); -GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig); - diff --git a/src/win32_init.c b/src/win32_init.c index c5370230..64393e77 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -29,6 +29,8 @@ #include "internal.h" +#if defined(_GLFW_WIN32) + #include static const GUID _glfw_GUID_DEVINTERFACE_HID = @@ -71,18 +73,17 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) // static GLFWbool loadLibraries(void) { - _glfw.win32.winmm.instance = LoadLibraryA("winmm.dll"); - if (!_glfw.win32.winmm.instance) + if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (const WCHAR*) &_glfw, + (HMODULE*) &_glfw.win32.instance)) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to load winmm.dll"); + "Win32: Failed to retrieve own module handle"); return GLFW_FALSE; } - _glfw.win32.winmm.GetTime = (PFN_timeGetTime) - GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime"); - - _glfw.win32.user32.instance = LoadLibraryA("user32.dll"); + _glfw.win32.user32.instance = _glfwPlatformLoadModule("user32.dll"); if (!_glfw.win32.user32.instance) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, @@ -91,23 +92,25 @@ static GLFWbool loadLibraries(void) } _glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware) - GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware"); + _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "SetProcessDPIAware"); _glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx) - GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx"); + _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx"); _glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling) - GetProcAddress(_glfw.win32.user32.instance, "EnableNonClientDpiScaling"); + _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "EnableNonClientDpiScaling"); _glfw.win32.user32.SetProcessDpiAwarenessContext_ = (PFN_SetProcessDpiAwarenessContext) - GetProcAddress(_glfw.win32.user32.instance, "SetProcessDpiAwarenessContext"); + _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "SetProcessDpiAwarenessContext"); _glfw.win32.user32.GetDpiForWindow_ = (PFN_GetDpiForWindow) - GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow"); + _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "GetDpiForWindow"); _glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi) - GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi"); + _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi"); + _glfw.win32.user32.GetSystemMetricsForDpi_ = (PFN_GetSystemMetricsForDpi) + _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "GetSystemMetricsForDpi"); - _glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll"); + _glfw.win32.dinput8.instance = _glfwPlatformLoadModule("dinput8.dll"); if (_glfw.win32.dinput8.instance) { _glfw.win32.dinput8.Create = (PFN_DirectInput8Create) - GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create"); + _glfwPlatformGetModuleSymbol(_glfw.win32.dinput8.instance, "DirectInput8Create"); } { @@ -124,46 +127,46 @@ static GLFWbool loadLibraries(void) for (i = 0; names[i]; i++) { - _glfw.win32.xinput.instance = LoadLibraryA(names[i]); + _glfw.win32.xinput.instance = _glfwPlatformLoadModule(names[i]); if (_glfw.win32.xinput.instance) { _glfw.win32.xinput.GetCapabilities = (PFN_XInputGetCapabilities) - GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities"); + _glfwPlatformGetModuleSymbol(_glfw.win32.xinput.instance, "XInputGetCapabilities"); _glfw.win32.xinput.GetState = (PFN_XInputGetState) - GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState"); + _glfwPlatformGetModuleSymbol(_glfw.win32.xinput.instance, "XInputGetState"); break; } } } - _glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll"); + _glfw.win32.dwmapi.instance = _glfwPlatformLoadModule("dwmapi.dll"); if (_glfw.win32.dwmapi.instance) { _glfw.win32.dwmapi.IsCompositionEnabled = (PFN_DwmIsCompositionEnabled) - GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled"); + _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled"); _glfw.win32.dwmapi.Flush = (PFN_DwmFlush) - GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush"); + _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmFlush"); _glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow) - GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow"); + _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow"); _glfw.win32.dwmapi.GetColorizationColor = (PFN_DwmGetColorizationColor) - GetProcAddress(_glfw.win32.dwmapi.instance, "DwmGetColorizationColor"); + _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmGetColorizationColor"); } - _glfw.win32.shcore.instance = LoadLibraryA("shcore.dll"); + _glfw.win32.shcore.instance = _glfwPlatformLoadModule("shcore.dll"); if (_glfw.win32.shcore.instance) { _glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness) - GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness"); + _glfwPlatformGetModuleSymbol(_glfw.win32.shcore.instance, "SetProcessDpiAwareness"); _glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor) - GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor"); + _glfwPlatformGetModuleSymbol(_glfw.win32.shcore.instance, "GetDpiForMonitor"); } - _glfw.win32.ntdll.instance = LoadLibraryA("ntdll.dll"); + _glfw.win32.ntdll.instance = _glfwPlatformLoadModule("ntdll.dll"); if (_glfw.win32.ntdll.instance) { _glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo) - GetProcAddress(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo"); + _glfwPlatformGetModuleSymbol(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo"); } return GLFW_TRUE; @@ -174,25 +177,22 @@ static GLFWbool loadLibraries(void) static void freeLibraries(void) { if (_glfw.win32.xinput.instance) - FreeLibrary(_glfw.win32.xinput.instance); + _glfwPlatformFreeModule(_glfw.win32.xinput.instance); if (_glfw.win32.dinput8.instance) - FreeLibrary(_glfw.win32.dinput8.instance); - - if (_glfw.win32.winmm.instance) - FreeLibrary(_glfw.win32.winmm.instance); + _glfwPlatformFreeModule(_glfw.win32.dinput8.instance); if (_glfw.win32.user32.instance) - FreeLibrary(_glfw.win32.user32.instance); + _glfwPlatformFreeModule(_glfw.win32.user32.instance); if (_glfw.win32.dwmapi.instance) - FreeLibrary(_glfw.win32.dwmapi.instance); + _glfwPlatformFreeModule(_glfw.win32.dwmapi.instance); if (_glfw.win32.shcore.instance) - FreeLibrary(_glfw.win32.shcore.instance); + _glfwPlatformFreeModule(_glfw.win32.shcore.instance); if (_glfw.win32.ntdll.instance) - FreeLibrary(_glfw.win32.ntdll.instance); + _glfwPlatformFreeModule(_glfw.win32.ntdll.instance); } // Create key code translation tables @@ -265,7 +265,6 @@ static void createKeyTables(void) _glfw.win32.keycodes[0x151] = GLFW_KEY_PAGE_DOWN; _glfw.win32.keycodes[0x149] = GLFW_KEY_PAGE_UP; _glfw.win32.keycodes[0x045] = GLFW_KEY_PAUSE; - _glfw.win32.keycodes[0x146] = GLFW_KEY_PAUSE; _glfw.win32.keycodes[0x039] = GLFW_KEY_SPACE; _glfw.win32.keycodes[0x00F] = GLFW_KEY_TAB; _glfw.win32.keycodes[0x03A] = GLFW_KEY_CAPS_LOCK; @@ -334,20 +333,69 @@ static void createKeyTables(void) } } +// Window procedure for the hidden helper window +// +static LRESULT CALLBACK helperWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_DISPLAYCHANGE: + _glfwPollMonitorsWin32(); + break; + + case WM_DEVICECHANGE: + { + if (!_glfw.joysticksInitialized) + break; + + if (wParam == DBT_DEVICEARRIVAL) + { + DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam; + if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) + _glfwDetectJoystickConnectionWin32(); + } + else if (wParam == DBT_DEVICEREMOVECOMPLETE) + { + DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam; + if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) + _glfwDetectJoystickDisconnectionWin32(); + } + + break; + } + } + + return DefWindowProcW(hWnd, uMsg, wParam, lParam); +} + // Creates a dummy window for behind-the-scenes work // static GLFWbool createHelperWindow(void) { MSG msg; + WNDCLASSEXW wc = { sizeof(wc) }; + + wc.style = CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) helperWindowProc; + wc.hInstance = _glfw.win32.instance; + wc.lpszClassName = L"GLFW3 Helper"; + + _glfw.win32.helperWindowClass = RegisterClassExW(&wc); + if (!_glfw.win32.helperWindowClass) + { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "WIn32: Failed to register helper window class"); + return GLFW_FALSE; + } _glfw.win32.helperWindowHandle = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW, - _GLFW_WNDCLASSNAME, + MAKEINTATOM(_glfw.win32.helperWindowClass), L"GLFW message window", WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, 1, 1, NULL, NULL, - GetModuleHandleW(NULL), + _glfw.win32.instance, NULL); if (!_glfw.win32.helperWindowHandle) @@ -497,7 +545,7 @@ void _glfwUpdateKeyNamesWin32(void) vk = vks[key - GLFW_KEY_KP_0]; } else - vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK); + vk = MapVirtualKeyW(scancode, MAPVK_VSC_TO_VK); length = ToUnicode(vk, scancode, state, chars, sizeof(chars) / sizeof(WCHAR), @@ -505,6 +553,8 @@ void _glfwUpdateKeyNamesWin32(void) if (length == -1) { + // This is a dead key, so we need a second simulated key press + // to make it output its own character (usually a diacritic) length = ToUnicode(vk, scancode, state, chars, sizeof(chars) / sizeof(WCHAR), 0); @@ -520,7 +570,8 @@ void _glfwUpdateKeyNamesWin32(void) } } -// Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h +// Replacement for IsWindowsVersionOrGreater, as we cannot rely on the +// application having a correct embedded manifest // BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp) { @@ -550,12 +601,89 @@ BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build) return RtlVerifyVersionInfo(&osvi, mask, cond) == 0; } +GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform) +{ + const _GLFWplatform win32 = + { + GLFW_PLATFORM_WIN32, + _glfwInitWin32, + _glfwTerminateWin32, + _glfwGetCursorPosWin32, + _glfwSetCursorPosWin32, + _glfwSetCursorModeWin32, + _glfwSetRawMouseMotionWin32, + _glfwRawMouseMotionSupportedWin32, + _glfwCreateCursorWin32, + _glfwCreateStandardCursorWin32, + _glfwDestroyCursorWin32, + _glfwSetCursorWin32, + _glfwGetScancodeNameWin32, + _glfwGetKeyScancodeWin32, + _glfwSetClipboardStringWin32, + _glfwGetClipboardStringWin32, + _glfwInitJoysticksWin32, + _glfwTerminateJoysticksWin32, + _glfwPollJoystickWin32, + _glfwGetMappingNameWin32, + _glfwUpdateGamepadGUIDWin32, + _glfwFreeMonitorWin32, + _glfwGetMonitorPosWin32, + _glfwGetMonitorContentScaleWin32, + _glfwGetMonitorWorkareaWin32, + _glfwGetVideoModesWin32, + _glfwGetVideoModeWin32, + _glfwGetGammaRampWin32, + _glfwSetGammaRampWin32, + _glfwCreateWindowWin32, + _glfwDestroyWindowWin32, + _glfwSetWindowTitleWin32, + _glfwSetWindowIconWin32, + _glfwGetWindowPosWin32, + _glfwSetWindowPosWin32, + _glfwGetWindowSizeWin32, + _glfwSetWindowSizeWin32, + _glfwSetWindowSizeLimitsWin32, + _glfwSetWindowAspectRatioWin32, + _glfwGetFramebufferSizeWin32, + _glfwGetWindowFrameSizeWin32, + _glfwGetWindowContentScaleWin32, + _glfwIconifyWindowWin32, + _glfwRestoreWindowWin32, + _glfwMaximizeWindowWin32, + _glfwShowWindowWin32, + _glfwHideWindowWin32, + _glfwRequestWindowAttentionWin32, + _glfwFocusWindowWin32, + _glfwSetWindowMonitorWin32, + _glfwWindowFocusedWin32, + _glfwWindowIconifiedWin32, + _glfwWindowVisibleWin32, + _glfwWindowMaximizedWin32, + _glfwWindowHoveredWin32, + _glfwFramebufferTransparentWin32, + _glfwGetWindowOpacityWin32, + _glfwSetWindowResizableWin32, + _glfwSetWindowDecoratedWin32, + _glfwSetWindowFloatingWin32, + _glfwSetWindowOpacityWin32, + _glfwSetWindowMousePassthroughWin32, + _glfwPollEventsWin32, + _glfwWaitEventsWin32, + _glfwWaitEventsTimeoutWin32, + _glfwPostEmptyEventWin32, + _glfwGetEGLPlatformWin32, + _glfwGetEGLNativeDisplayWin32, + _glfwGetEGLNativeWindowWin32, + _glfwGetRequiredInstanceExtensionsWin32, + _glfwGetPhysicalDevicePresentationSupportWin32, + _glfwCreateWindowSurfaceWin32, + }; -////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// + *platform = win32; + return GLFW_TRUE; +} -int _glfwPlatformInit(void) +int _glfwInitWin32(void) { if (!loadLibraries()) return GLFW_FALSE; @@ -563,60 +691,41 @@ int _glfwPlatformInit(void) createKeyTables(); _glfwUpdateKeyNamesWin32(); - if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32()) + if (_glfwIsWindows10Version1703OrGreaterWin32()) SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); else if (IsWindows8Point1OrGreater()) SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); else if (IsWindowsVistaOrGreater()) SetProcessDPIAware(); - if (!_glfwRegisterWindowClassWin32()) - return GLFW_FALSE; - if (!createHelperWindow()) return GLFW_FALSE; - _glfwInitTimerWin32(); - _glfwPollMonitorsWin32(); return GLFW_TRUE; } -void _glfwPlatformTerminate(void) +void _glfwTerminateWin32(void) { if (_glfw.win32.deviceNotificationHandle) UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle); if (_glfw.win32.helperWindowHandle) DestroyWindow(_glfw.win32.helperWindowHandle); - - _glfwUnregisterWindowClassWin32(); + if (_glfw.win32.helperWindowClass) + UnregisterClassW(MAKEINTATOM(_glfw.win32.helperWindowClass), _glfw.win32.instance); + if (_glfw.win32.mainWindowClass) + UnregisterClassW(MAKEINTATOM(_glfw.win32.mainWindowClass), _glfw.win32.instance); _glfw_free(_glfw.win32.clipboardString); _glfw_free(_glfw.win32.rawInput); _glfwTerminateWGL(); _glfwTerminateEGL(); + _glfwTerminateOSMesa(); freeLibraries(); } -const char* _glfwPlatformGetVersionString(void) -{ - return _GLFW_VERSION_NUMBER " Win32 WGL EGL OSMesa" -#if defined(__MINGW64_VERSION_MAJOR) - " MinGW-w64" -#elif defined(__MINGW32__) - " MinGW" -#elif defined(_MSC_VER) - " VisualC" -#endif -#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG) - " hybrid-GPU" -#endif -#if defined(_GLFW_BUILD_DLL) - " DLL" -#endif - ; -} +#endif // _GLFW_WIN32 diff --git a/src/win32_joystick.c b/src/win32_joystick.c index 3ac29d1d..4e83577a 100644 --- a/src/win32_joystick.c +++ b/src/win32_joystick.c @@ -29,6 +29,8 @@ #include "internal.h" +#if defined(_GLFW_WIN32) + #include #include @@ -256,6 +258,8 @@ static GLFWbool supportsXInput(const GUID* guid) // static void closeJoystick(_GLFWjoystick* js) { + _glfwInputJoystick(js, GLFW_DISCONNECTED); + if (js->win32.device) { IDirectInputDevice8_Unacquire(js->win32.device); @@ -263,9 +267,7 @@ static void closeJoystick(_GLFWjoystick* js) } _glfw_free(js->win32.objects); - _glfwFreeJoystick(js); - _glfwInputJoystick(js, GLFW_DISCONNECTED); } // DirectInput device object enumeration callback @@ -357,7 +359,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user) for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) { js = _glfw.joysticks + jid; - if (js->present) + if (js->connected) { if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0) return DIENUM_CONTINUE; @@ -508,7 +510,7 @@ void _glfwDetectJoystickConnectionWin32(void) for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) { - if (_glfw.joysticks[jid].present && + if (_glfw.joysticks[jid].connected && _glfw.joysticks[jid].win32.device == NULL && _glfw.joysticks[jid].win32.index == index) { @@ -560,8 +562,8 @@ void _glfwDetectJoystickDisconnectionWin32(void) for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) { _GLFWjoystick* js = _glfw.joysticks + jid; - if (js->present) - _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE); + if (js->connected) + _glfwPollJoystickWin32(js, _GLFW_POLL_PRESENCE); } } @@ -570,11 +572,11 @@ void _glfwDetectJoystickDisconnectionWin32(void) ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -GLFWbool _glfwPlatformInitJoysticks(void) +GLFWbool _glfwInitJoysticksWin32(void) { if (_glfw.win32.dinput8.instance) { - if (FAILED(DirectInput8Create(GetModuleHandle(NULL), + if (FAILED(DirectInput8Create(_glfw.win32.instance, DIRECTINPUT_VERSION, &IID_IDirectInput8W, (void**) &_glfw.win32.dinput8.api, @@ -590,7 +592,7 @@ GLFWbool _glfwPlatformInitJoysticks(void) return GLFW_TRUE; } -void _glfwPlatformTerminateJoysticks(void) +void _glfwTerminateJoysticksWin32(void) { int jid; @@ -601,13 +603,13 @@ void _glfwPlatformTerminateJoysticks(void) IDirectInput8_Release(_glfw.win32.dinput8.api); } -int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) +GLFWbool _glfwPollJoystickWin32(_GLFWjoystick* js, int mode) { if (js->win32.device) { int i, ai = 0, bi = 0, pi = 0; HRESULT result; - DIJOYSTATE state; + DIJOYSTATE state = {0}; IDirectInputDevice8_Poll(js->win32.device); result = IDirectInputDevice8_GetDeviceState(js->win32.device, @@ -740,7 +742,12 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) return GLFW_TRUE; } -void _glfwPlatformUpdateGamepadGUID(char* guid) +const char* _glfwGetMappingNameWin32(void) +{ + return "Windows"; +} + +void _glfwUpdateGamepadGUIDWin32(char* guid) { if (strcmp(guid + 20, "504944564944") == 0) { @@ -751,3 +758,5 @@ void _glfwPlatformUpdateGamepadGUID(char* guid) } } +#endif // _GLFW_WIN32 + diff --git a/src/win32_joystick.h b/src/win32_joystick.h index c469fcdc..9ab6438b 100644 --- a/src/win32_joystick.h +++ b/src/win32_joystick.h @@ -24,11 +24,8 @@ // //======================================================================== -#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickWin32 win32 -#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE struct { int dummyLibraryJoystick; } - -#define _GLFW_PLATFORM_MAPPING_NAME "Windows" -#define GLFW_BUILD_WIN32_MAPPINGS +#define GLFW_WIN32_JOYSTICK_STATE _GLFWjoystickWin32 win32; +#define GLFW_WIN32_LIBRARY_JOYSTICK_STATE // Joystick element (axis, button or slider) // diff --git a/src/win32_module.c b/src/win32_module.c new file mode 100644 index 00000000..9c2b6d24 --- /dev/null +++ b/src/win32_module.c @@ -0,0 +1,53 @@ +//======================================================================== +// GLFW 3.4 Win32 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2021 Camilla Löwy +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== +// Please use C89 style variable declarations in this file because VS 2010 +//======================================================================== + +#include "internal.h" + +#if defined(GLFW_BUILD_WIN32_MODULE) + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +void* _glfwPlatformLoadModule(const char* path) +{ + return LoadLibraryA(path); +} + +void _glfwPlatformFreeModule(void* module) +{ + FreeLibrary((HMODULE) module); +} + +GLFWproc _glfwPlatformGetModuleSymbol(void* module, const char* name) +{ + return (GLFWproc) GetProcAddress((HMODULE) module, name); +} + +#endif // GLFW_BUILD_WIN32_MODULE + diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 10e3d282..2935ac28 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -29,6 +29,8 @@ #include "internal.h" +#if defined(_GLFW_WIN32) + #include #include #include @@ -253,7 +255,7 @@ void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired) LONG result; best = _glfwChooseVideoMode(monitor, desired); - _glfwPlatformGetVideoMode(monitor, ¤t); + _glfwGetVideoModeWin32(monitor, ¤t); if (_glfwCompareVideoModes(¤t, best) == 0) return; @@ -313,12 +315,23 @@ void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor) } } -void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale) +void _glfwGetHMONITORContentScaleWin32(HMONITOR handle, float* xscale, float* yscale) { UINT xdpi, ydpi; + if (xscale) + *xscale = 0.f; + if (yscale) + *yscale = 0.f; + if (IsWindows8Point1OrGreater()) - GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi); + { + if (GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi) != S_OK) + { + _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to query monitor DPI"); + return; + } + } else { const HDC dc = GetDC(NULL); @@ -338,11 +351,11 @@ void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* ysc ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor) +void _glfwFreeMonitorWin32(_GLFWmonitor* monitor) { } -void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) +void _glfwGetMonitorPosWin32(_GLFWmonitor* monitor, int* xpos, int* ypos) { DEVMODEW dm; ZeroMemory(&dm, sizeof(dm)); @@ -359,18 +372,18 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) *ypos = dm.dmPosition.y; } -void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, - float* xscale, float* yscale) +void _glfwGetMonitorContentScaleWin32(_GLFWmonitor* monitor, + float* xscale, float* yscale) { - _glfwGetMonitorContentScaleWin32(monitor->win32.handle, xscale, yscale); + _glfwGetHMONITORContentScaleWin32(monitor->win32.handle, xscale, yscale); } -void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, - int* xpos, int* ypos, - int* width, int* height) +void _glfwGetMonitorWorkareaWin32(_GLFWmonitor* monitor, + int* xpos, int* ypos, + int* width, int* height) { MONITORINFO mi = { sizeof(mi) }; - GetMonitorInfo(monitor->win32.handle, &mi); + GetMonitorInfoW(monitor->win32.handle, &mi); if (xpos) *xpos = mi.rcWork.left; @@ -382,7 +395,7 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, *height = mi.rcWork.bottom - mi.rcWork.top; } -GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) +GLFWvidmode* _glfwGetVideoModesWin32(_GLFWmonitor* monitor, int* count) { int modeIndex = 0, size = 0; GLFWvidmode* result = NULL; @@ -452,14 +465,14 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) { // HACK: Report the current mode if no valid modes were found result = _glfw_calloc(1, sizeof(GLFWvidmode)); - _glfwPlatformGetVideoMode(monitor, result); + _glfwGetVideoModeWin32(monitor, result); *count = 1; } return result; } -void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) +void _glfwGetVideoModeWin32(_GLFWmonitor* monitor, GLFWvidmode* mode) { DEVMODEW dm; ZeroMemory(&dm, sizeof(dm)); @@ -476,7 +489,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) &mode->blueBits); } -GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) +GLFWbool _glfwGetGammaRampWin32(_GLFWmonitor* monitor, GLFWgammaramp* ramp) { HDC dc; WORD values[3][256]; @@ -494,7 +507,7 @@ GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) return GLFW_TRUE; } -void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) +void _glfwSetGammaRampWin32(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) { HDC dc; WORD values[3][256]; @@ -534,3 +547,5 @@ GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle) return monitor->win32.publicDisplayName; } +#endif // _GLFW_WIN32 + diff --git a/src/win32_platform.h b/src/win32_platform.h index a16047ae..82b34bb9 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -162,7 +162,9 @@ typedef enum #define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE) -4) #endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/ -// HACK: Define versionhelpers.h functions manually as MinGW lacks the header +// Replacement for versionhelpers.h macros, as we cannot rely on the +// application having a correct embedded manifest +// #define IsWindowsVistaOrGreater() \ _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_VISTA), \ LOBYTE(_WIN32_WINNT_VISTA), 0) @@ -176,9 +178,11 @@ typedef enum _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINBLUE), \ LOBYTE(_WIN32_WINNT_WINBLUE), 0) -#define _glfwIsWindows10AnniversaryUpdateOrGreaterWin32() \ +// Windows 10 Anniversary Update +#define _glfwIsWindows10Version1607OrGreaterWin32() \ _glfwIsWindows10BuildOrGreaterWin32(14393) -#define _glfwIsWindows10CreatorsUpdateOrGreaterWin32() \ +// Windows 10 Creators Update +#define _glfwIsWindows10Version1703OrGreaterWin32() \ _glfwIsWindows10BuildOrGreaterWin32(15063) // HACK: Define macros that some xinput.h variants don't @@ -215,9 +219,56 @@ typedef enum #define DIDFT_OPTIONAL 0x80000000 #endif -// winmm.dll function pointer typedefs -typedef DWORD (WINAPI * PFN_timeGetTime)(void); -#define timeGetTime _glfw.win32.winmm.GetTime +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_TYPE_RGBA_ARB 0x202b +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201a +#define WGL_ALPHA_BITS_ARB 0x201b +#define WGL_ALPHA_SHIFT_ARB 0x201c +#define WGL_ACCUM_BITS_ARB 0x201d +#define WGL_ACCUM_RED_BITS_ARB 0x201e +#define WGL_ACCUM_GREEN_BITS_ARB 0x201f +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_STEREO_ARB 0x2012 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_SAMPLES_ARB 0x2042 +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9 +#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 +#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 +#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_FLAGS_ARB 0x2094 +#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 +#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261 +#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097 +#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0 +#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 +#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3 +#define WGL_COLORSPACE_EXT 0x309d +#define WGL_COLORSPACE_SRGB_EXT 0x3089 + +#define ERROR_INVALID_VERSION_ARB 0x2095 +#define ERROR_INVALID_PROFILE_ARB 0x2096 +#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 // xinput.dll function pointer typedefs typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*); @@ -236,12 +287,14 @@ typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND); typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE); typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND); typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT); +typedef int (WINAPI * PFN_GetSystemMetricsForDpi)(int,UINT); #define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_ #define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_ #define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_ #define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_ #define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_ #define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_ +#define GetSystemMetricsForDpi _glfw.win32.user32.GetSystemMetricsForDpi_ // dwmapi.dll function pointer typedefs typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*); @@ -263,6 +316,34 @@ typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*, typedef LONG (WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*,ULONG,ULONGLONG); #define RtlVerifyVersionInfo _glfw.win32.ntdll.RtlVerifyVersionInfo_ +// WGL extension pointer typedefs +typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*); +typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void); +typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC); +typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC,HGLRC,const int*); +#define wglSwapIntervalEXT _glfw.wgl.SwapIntervalEXT +#define wglGetPixelFormatAttribivARB _glfw.wgl.GetPixelFormatAttribivARB +#define wglGetExtensionsStringEXT _glfw.wgl.GetExtensionsStringEXT +#define wglGetExtensionsStringARB _glfw.wgl.GetExtensionsStringARB +#define wglCreateContextAttribsARB _glfw.wgl.CreateContextAttribsARB + +// opengl32.dll function pointer typedefs +typedef HGLRC (WINAPI * PFN_wglCreateContext)(HDC); +typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC); +typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR); +typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void); +typedef HGLRC (WINAPI * PFN_wglGetCurrentContext)(void); +typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC); +typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC); +#define wglCreateContext _glfw.wgl.CreateContext +#define wglDeleteContext _glfw.wgl.DeleteContext +#define wglGetProcAddress _glfw.wgl.GetProcAddress +#define wglGetCurrentDC _glfw.wgl.GetCurrentDC +#define wglGetCurrentContext _glfw.wgl.GetCurrentContext +#define wglMakeCurrent _glfw.wgl.MakeCurrent +#define wglShareLists _glfw.wgl.ShareLists + typedef VkFlags VkWin32SurfaceCreateFlagsKHR; typedef struct VkWin32SurfaceCreateInfoKHR @@ -277,25 +358,55 @@ typedef struct VkWin32SurfaceCreateInfoKHR typedef VkResult (APIENTRY *PFN_vkCreateWin32SurfaceKHR)(VkInstance,const VkWin32SurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*); typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t); -#include "win32_joystick.h" -#include "wgl_context.h" +#define GLFW_WIN32_WINDOW_STATE _GLFWwindowWin32 win32; +#define GLFW_WIN32_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32; +#define GLFW_WIN32_MONITOR_STATE _GLFWmonitorWin32 win32; +#define GLFW_WIN32_CURSOR_STATE _GLFWcursorWin32 win32; -#if !defined(_GLFW_WNDCLASSNAME) - #define _GLFW_WNDCLASSNAME L"GLFW30" -#endif +#define GLFW_WGL_CONTEXT_STATE _GLFWcontextWGL wgl; +#define GLFW_WGL_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl; -#define _glfw_dlopen(name) LoadLibraryA(name) -#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle) -#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name) -#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32 -#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32 -#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerWin32 win32 -#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32 -#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32 -#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsWin32 win32 -#define _GLFW_PLATFORM_MUTEX_STATE _GLFWmutexWin32 win32 +// WGL-specific per-context data +// +typedef struct _GLFWcontextWGL +{ + HDC dc; + HGLRC handle; + int interval; +} _GLFWcontextWGL; +// WGL-specific global data +// +typedef struct _GLFWlibraryWGL +{ + HINSTANCE instance; + PFN_wglCreateContext CreateContext; + PFN_wglDeleteContext DeleteContext; + PFN_wglGetProcAddress GetProcAddress; + PFN_wglGetCurrentDC GetCurrentDC; + PFN_wglGetCurrentContext GetCurrentContext; + PFN_wglMakeCurrent MakeCurrent; + PFN_wglShareLists ShareLists; + + PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT; + PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB; + PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT; + PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB; + PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; + GLFWbool EXT_swap_control; + GLFWbool EXT_colorspace; + GLFWbool ARB_multisample; + GLFWbool ARB_framebuffer_sRGB; + GLFWbool EXT_framebuffer_sRGB; + GLFWbool ARB_pixel_format; + GLFWbool ARB_create_context; + GLFWbool ARB_create_context_profile; + GLFWbool EXT_create_context_es2_profile; + GLFWbool ARB_create_context_robustness; + GLFWbool ARB_create_context_no_error; + GLFWbool ARB_context_flush_control; +} _GLFWlibraryWGL; // Win32-specific per-window data // @@ -319,16 +430,18 @@ typedef struct _GLFWwindowWin32 // The last received cursor position, regardless of source int lastCursorPosX, lastCursorPosY; - // The last recevied high surrogate when decoding pairs of UTF-16 messages + // The last received high surrogate when decoding pairs of UTF-16 messages WCHAR highSurrogate; - } _GLFWwindowWin32; // Win32-specific global data // typedef struct _GLFWlibraryWin32 { + HINSTANCE instance; HWND helperWindowHandle; + ATOM helperWindowClass; + ATOM mainWindowClass; HDEVNOTIFY deviceNotificationHandle; int acquiredMonitorCount; char* clipboardString; @@ -339,15 +452,12 @@ typedef struct _GLFWlibraryWin32 double restoreCursorPosX, restoreCursorPosY; // The window whose disabled cursor mode is active _GLFWwindow* disabledCursorWindow; + // The window the cursor is captured in + _GLFWwindow* capturedCursorWindow; RAWINPUT* rawInput; int rawInputSize; UINT mouseTrailSize; - struct { - HINSTANCE instance; - PFN_timeGetTime GetTime; - } winmm; - struct { HINSTANCE instance; PFN_DirectInput8Create Create; @@ -368,6 +478,7 @@ typedef struct _GLFWlibraryWin32 PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_; PFN_GetDpiForWindow GetDpiForWindow_; PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_; + PFN_GetSystemMetricsForDpi GetSystemMetricsForDpi_; } user32; struct { @@ -388,7 +499,6 @@ typedef struct _GLFWlibraryWin32 HINSTANCE instance; PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_; } ntdll; - } _GLFWlibraryWin32; // Win32-specific per-monitor data @@ -403,7 +513,6 @@ typedef struct _GLFWmonitorWin32 char publicDisplayName[32]; GLFWbool modesPruned; GLFWbool modeChanged; - } _GLFWmonitorWin32; // Win32-specific per-cursor data @@ -411,39 +520,12 @@ typedef struct _GLFWmonitorWin32 typedef struct _GLFWcursorWin32 { HCURSOR handle; - } _GLFWcursorWin32; -// Win32-specific global timer data -// -typedef struct _GLFWtimerWin32 -{ - GLFWbool hasPC; - uint64_t frequency; -} _GLFWtimerWin32; - -// Win32-specific thread local storage data -// -typedef struct _GLFWtlsWin32 -{ - GLFWbool allocated; - DWORD index; - -} _GLFWtlsWin32; - -// Win32-specific mutex data -// -typedef struct _GLFWmutexWin32 -{ - GLFWbool allocated; - CRITICAL_SECTION section; - -} _GLFWmutexWin32; - - -GLFWbool _glfwRegisterWindowClassWin32(void); -void _glfwUnregisterWindowClassWin32(void); +GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform); +int _glfwInitWin32(void); +void _glfwTerminateWin32(void); WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source); char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source); @@ -452,10 +534,91 @@ BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build); void _glfwInputErrorWin32(int error, const char* description); void _glfwUpdateKeyNamesWin32(void); -void _glfwInitTimerWin32(void); - void _glfwPollMonitorsWin32(void); void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired); void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor); -void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale); +void _glfwGetHMONITORContentScaleWin32(HMONITOR handle, float* xscale, float* yscale); + +GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); +void _glfwDestroyWindowWin32(_GLFWwindow* window); +void _glfwSetWindowTitleWin32(_GLFWwindow* window, const char* title); +void _glfwSetWindowIconWin32(_GLFWwindow* window, int count, const GLFWimage* images); +void _glfwGetWindowPosWin32(_GLFWwindow* window, int* xpos, int* ypos); +void _glfwSetWindowPosWin32(_GLFWwindow* window, int xpos, int ypos); +void _glfwGetWindowSizeWin32(_GLFWwindow* window, int* width, int* height); +void _glfwSetWindowSizeWin32(_GLFWwindow* window, int width, int height); +void _glfwSetWindowSizeLimitsWin32(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); +void _glfwSetWindowAspectRatioWin32(_GLFWwindow* window, int numer, int denom); +void _glfwGetFramebufferSizeWin32(_GLFWwindow* window, int* width, int* height); +void _glfwGetWindowFrameSizeWin32(_GLFWwindow* window, int* left, int* top, int* right, int* bottom); +void _glfwGetWindowContentScaleWin32(_GLFWwindow* window, float* xscale, float* yscale); +void _glfwIconifyWindowWin32(_GLFWwindow* window); +void _glfwRestoreWindowWin32(_GLFWwindow* window); +void _glfwMaximizeWindowWin32(_GLFWwindow* window); +void _glfwShowWindowWin32(_GLFWwindow* window); +void _glfwHideWindowWin32(_GLFWwindow* window); +void _glfwRequestWindowAttentionWin32(_GLFWwindow* window); +void _glfwFocusWindowWin32(_GLFWwindow* window); +void _glfwSetWindowMonitorWin32(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); +GLFWbool _glfwWindowFocusedWin32(_GLFWwindow* window); +GLFWbool _glfwWindowIconifiedWin32(_GLFWwindow* window); +GLFWbool _glfwWindowVisibleWin32(_GLFWwindow* window); +GLFWbool _glfwWindowMaximizedWin32(_GLFWwindow* window); +GLFWbool _glfwWindowHoveredWin32(_GLFWwindow* window); +GLFWbool _glfwFramebufferTransparentWin32(_GLFWwindow* window); +void _glfwSetWindowResizableWin32(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowDecoratedWin32(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowFloatingWin32(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowMousePassthroughWin32(_GLFWwindow* window, GLFWbool enabled); +float _glfwGetWindowOpacityWin32(_GLFWwindow* window); +void _glfwSetWindowOpacityWin32(_GLFWwindow* window, float opacity); + +void _glfwSetRawMouseMotionWin32(_GLFWwindow *window, GLFWbool enabled); +GLFWbool _glfwRawMouseMotionSupportedWin32(void); + +void _glfwPollEventsWin32(void); +void _glfwWaitEventsWin32(void); +void _glfwWaitEventsTimeoutWin32(double timeout); +void _glfwPostEmptyEventWin32(void); + +void _glfwGetCursorPosWin32(_GLFWwindow* window, double* xpos, double* ypos); +void _glfwSetCursorPosWin32(_GLFWwindow* window, double xpos, double ypos); +void _glfwSetCursorModeWin32(_GLFWwindow* window, int mode); +const char* _glfwGetScancodeNameWin32(int scancode); +int _glfwGetKeyScancodeWin32(int key); +GLFWbool _glfwCreateCursorWin32(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot); +GLFWbool _glfwCreateStandardCursorWin32(_GLFWcursor* cursor, int shape); +void _glfwDestroyCursorWin32(_GLFWcursor* cursor); +void _glfwSetCursorWin32(_GLFWwindow* window, _GLFWcursor* cursor); +void _glfwSetClipboardStringWin32(const char* string); +const char* _glfwGetClipboardStringWin32(void); + +EGLenum _glfwGetEGLPlatformWin32(EGLint** attribs); +EGLNativeDisplayType _glfwGetEGLNativeDisplayWin32(void); +EGLNativeWindowType _glfwGetEGLNativeWindowWin32(_GLFWwindow* window); + +void _glfwGetRequiredInstanceExtensionsWin32(char** extensions); +GLFWbool _glfwGetPhysicalDevicePresentationSupportWin32(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); +VkResult _glfwCreateWindowSurfaceWin32(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +void _glfwFreeMonitorWin32(_GLFWmonitor* monitor); +void _glfwGetMonitorPosWin32(_GLFWmonitor* monitor, int* xpos, int* ypos); +void _glfwGetMonitorContentScaleWin32(_GLFWmonitor* monitor, float* xscale, float* yscale); +void _glfwGetMonitorWorkareaWin32(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height); +GLFWvidmode* _glfwGetVideoModesWin32(_GLFWmonitor* monitor, int* count); +void _glfwGetVideoModeWin32(_GLFWmonitor* monitor, GLFWvidmode* mode); +GLFWbool _glfwGetGammaRampWin32(_GLFWmonitor* monitor, GLFWgammaramp* ramp); +void _glfwSetGammaRampWin32(_GLFWmonitor* monitor, const GLFWgammaramp* ramp); + +GLFWbool _glfwInitJoysticksWin32(void); +void _glfwTerminateJoysticksWin32(void); +GLFWbool _glfwPollJoystickWin32(_GLFWjoystick* js, int mode); +const char* _glfwGetMappingNameWin32(void); +void _glfwUpdateGamepadGUIDWin32(char* guid); + +GLFWbool _glfwInitWGL(void); +void _glfwTerminateWGL(void); +GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig); diff --git a/src/win32_thread.c b/src/win32_thread.c index 53b34af2..db997915 100644 --- a/src/win32_thread.c +++ b/src/win32_thread.c @@ -29,6 +29,8 @@ #include "internal.h" +#if defined(GLFW_BUILD_WIN32_THREAD) + #include @@ -43,8 +45,7 @@ GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls) tls->win32.index = TlsAlloc(); if (tls->win32.index == TLS_OUT_OF_INDEXES) { - _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to allocate TLS index"); + _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to allocate TLS index"); return GLFW_FALSE; } @@ -97,3 +98,5 @@ void _glfwPlatformUnlockMutex(_GLFWmutex* mutex) LeaveCriticalSection(&mutex->win32.section); } +#endif // GLFW_BUILD_WIN32_THREAD + diff --git a/src/win32_thread.h b/src/win32_thread.h new file mode 100644 index 00000000..4b5a696f --- /dev/null +++ b/src/win32_thread.h @@ -0,0 +1,48 @@ +//======================================================================== +// GLFW 3.4 Win32 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2002-2006 Marcus Geelnard +// Copyright (c) 2006-2017 Camilla Löwy +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#include + +#define GLFW_WIN32_TLS_STATE _GLFWtlsWin32 win32; +#define GLFW_WIN32_MUTEX_STATE _GLFWmutexWin32 win32; + +// Win32-specific thread local storage data +// +typedef struct _GLFWtlsWin32 +{ + GLFWbool allocated; + DWORD index; +} _GLFWtlsWin32; + +// Win32-specific mutex data +// +typedef struct _GLFWmutexWin32 +{ + GLFWbool allocated; + CRITICAL_SECTION section; +} _GLFWmutexWin32; + diff --git a/src/win32_time.c b/src/win32_time.c index 721b0d0d..fcfe2005 100644 --- a/src/win32_time.c +++ b/src/win32_time.c @@ -29,44 +29,22 @@ #include "internal.h" - -////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// -////////////////////////////////////////////////////////////////////////// - -// Initialise timer -// -void _glfwInitTimerWin32(void) -{ - uint64_t frequency; - - if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency)) - { - _glfw.timer.win32.hasPC = GLFW_TRUE; - _glfw.timer.win32.frequency = frequency; - } - else - { - _glfw.timer.win32.hasPC = GLFW_FALSE; - _glfw.timer.win32.frequency = 1000; - } -} - +#if defined(GLFW_BUILD_WIN32_TIMER) ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// +void _glfwPlatformInitTimer(void) +{ + QueryPerformanceFrequency((LARGE_INTEGER*) &_glfw.timer.win32.frequency); +} + uint64_t _glfwPlatformGetTimerValue(void) { - if (_glfw.timer.win32.hasPC) - { - uint64_t value; - QueryPerformanceCounter((LARGE_INTEGER*) &value); - return value; - } - else - return (uint64_t) timeGetTime(); + uint64_t value; + QueryPerformanceCounter((LARGE_INTEGER*) &value); + return value; } uint64_t _glfwPlatformGetTimerFrequency(void) @@ -74,3 +52,5 @@ uint64_t _glfwPlatformGetTimerFrequency(void) return _glfw.timer.win32.frequency; } +#endif // GLFW_BUILD_WIN32_TIMER + diff --git a/src/win32_time.h b/src/win32_time.h new file mode 100644 index 00000000..da5afa41 --- /dev/null +++ b/src/win32_time.h @@ -0,0 +1,38 @@ +//======================================================================== +// GLFW 3.4 Win32 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2002-2006 Marcus Geelnard +// Copyright (c) 2006-2017 Camilla Löwy +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#include + +#define GLFW_WIN32_LIBRARY_TIMER_STATE _GLFWtimerWin32 win32; + +// Win32-specific global timer data +// +typedef struct _GLFWtimerWin32 +{ + uint64_t frequency; +} _GLFWtimerWin32; + diff --git a/src/win32_window.c b/src/win32_window.c index 80ae7c79..676640bf 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -29,6 +29,8 @@ #include "internal.h" +#if defined(_GLFW_WIN32) + #include #include #include @@ -97,8 +99,7 @@ static const GLFWimage* chooseImage(int count, const GLFWimage* images, // Creates an RGBA icon or cursor // -static HICON createIcon(const GLFWimage* image, - int xhot, int yhot, GLFWbool icon) +static HICON createIcon(const GLFWimage* image, int xhot, int yhot, GLFWbool icon) { int i; HDC dc; @@ -185,53 +186,38 @@ static HICON createIcon(const GLFWimage* image, return handle; } -// Translate content area size to full window size according to styles and DPI -// -static void getFullWindowSize(DWORD style, DWORD exStyle, - int contentWidth, int contentHeight, - int* fullWidth, int* fullHeight, - UINT dpi) -{ - RECT rect = { 0, 0, contentWidth, contentHeight }; - - if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32()) - AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi); - else - AdjustWindowRectEx(&rect, style, FALSE, exStyle); - - *fullWidth = rect.right - rect.left; - *fullHeight = rect.bottom - rect.top; -} - // Enforce the content area aspect ratio based on which edge is being dragged // static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area) { - int xoff, yoff; - UINT dpi = USER_DEFAULT_SCREEN_DPI; + RECT frame = {0}; const float ratio = (float) window->numer / (float) window->denom; + const DWORD style = getWindowStyle(window); + const DWORD exStyle = getWindowExStyle(window); - if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32()) - dpi = GetDpiForWindow(window->win32.handle); - - getFullWindowSize(getWindowStyle(window), getWindowExStyle(window), - 0, 0, &xoff, &yoff, dpi); + if (_glfwIsWindows10Version1607OrGreaterWin32()) + { + AdjustWindowRectExForDpi(&frame, style, FALSE, exStyle, + GetDpiForWindow(window->win32.handle)); + } + else + AdjustWindowRectEx(&frame, style, FALSE, exStyle); if (edge == WMSZ_LEFT || edge == WMSZ_BOTTOMLEFT || edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT) { - area->bottom = area->top + yoff + - (int) ((area->right - area->left - xoff) / ratio); + area->bottom = area->top + (frame.bottom - frame.top) + + (int) (((area->right - area->left) - (frame.right - frame.left)) / ratio); } else if (edge == WMSZ_TOPLEFT || edge == WMSZ_TOPRIGHT) { - area->top = area->bottom - yoff - - (int) ((area->right - area->left - xoff) / ratio); + area->top = area->bottom - (frame.bottom - frame.top) - + (int) (((area->right - area->left) - (frame.right - frame.left)) / ratio); } else if (edge == WMSZ_TOP || edge == WMSZ_BOTTOM) { - area->right = area->left + xoff + - (int) ((area->bottom - area->top - yoff) * ratio); + area->right = area->left + (frame.right - frame.left) + + (int) (((area->bottom - area->top) - (frame.bottom - frame.top)) * ratio); } } @@ -239,7 +225,8 @@ static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area) // static void updateCursorImage(_GLFWwindow* window) { - if (window->cursorMode == GLFW_CURSOR_NORMAL) + if (window->cursorMode == GLFW_CURSOR_NORMAL || + window->cursorMode == GLFW_CURSOR_CAPTURED) { if (window->cursor) SetCursor(window->cursor->win32.handle); @@ -250,20 +237,24 @@ static void updateCursorImage(_GLFWwindow* window) SetCursor(NULL); } -// Updates the cursor clip rect +// Sets the cursor clip rect to the window content area // -static void updateClipRect(_GLFWwindow* window) +static void captureCursor(_GLFWwindow* window) { - if (window) - { - RECT clipRect; - GetClientRect(window->win32.handle, &clipRect); - ClientToScreen(window->win32.handle, (POINT*) &clipRect.left); - ClientToScreen(window->win32.handle, (POINT*) &clipRect.right); - ClipCursor(&clipRect); - } - else - ClipCursor(NULL); + RECT clipRect; + GetClientRect(window->win32.handle, &clipRect); + ClientToScreen(window->win32.handle, (POINT*) &clipRect.left); + ClientToScreen(window->win32.handle, (POINT*) &clipRect.right); + ClipCursor(&clipRect); + _glfw.win32.capturedCursorWindow = window; +} + +// Disabled clip cursor +// +static void releaseCursor(void) +{ + ClipCursor(NULL); + _glfw.win32.capturedCursorWindow = NULL; } // Enables WM_INPUT messages for the mouse for the specified window @@ -297,12 +288,12 @@ static void disableRawMouseMotion(_GLFWwindow* window) static void disableCursor(_GLFWwindow* window) { _glfw.win32.disabledCursorWindow = window; - _glfwPlatformGetCursorPos(window, - &_glfw.win32.restoreCursorPosX, - &_glfw.win32.restoreCursorPosY); + _glfwGetCursorPosWin32(window, + &_glfw.win32.restoreCursorPosX, + &_glfw.win32.restoreCursorPosY); updateCursorImage(window); _glfwCenterCursorInContentArea(window); - updateClipRect(window); + captureCursor(window); if (window->rawMouseMotion) enableRawMouseMotion(window); @@ -316,10 +307,10 @@ static void enableCursor(_GLFWwindow* window) disableRawMouseMotion(window); _glfw.win32.disabledCursorWindow = NULL; - updateClipRect(NULL); - _glfwPlatformSetCursorPos(window, - _glfw.win32.restoreCursorPosX, - _glfw.win32.restoreCursorPosY); + releaseCursor(); + _glfwSetCursorPosWin32(window, + _glfw.win32.restoreCursorPosX, + _glfw.win32.restoreCursorPosY); updateCursorImage(window); } @@ -354,7 +345,7 @@ static void updateWindowStyles(const _GLFWwindow* window) GetClientRect(window->win32.handle, &rect); - if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32()) + if (_glfwIsWindows10Version1607OrGreaterWin32()) { AdjustWindowRectExForDpi(&rect, style, FALSE, getWindowExStyle(window), @@ -434,7 +425,7 @@ static int getKeyMods(void) static void fitToMonitor(_GLFWwindow* window) { MONITORINFO mi = { sizeof(mi) }; - GetMonitorInfo(window->monitor->win32.handle, &mi); + GetMonitorInfoW(window->monitor->win32.handle, &mi); SetWindowPos(window->win32.handle, HWND_TOPMOST, mi.rcMonitor.left, mi.rcMonitor.top, @@ -453,8 +444,8 @@ static void acquireMonitor(_GLFWwindow* window) // HACK: When mouse trails are enabled the cursor becomes invisible when // the OpenGL ICD switches to page flipping - SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0); - SystemParametersInfo(SPI_SETMOUSETRAILS, 0, 0, 0); + SystemParametersInfoW(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0); + SystemParametersInfoW(SPI_SETMOUSETRAILS, 0, 0, 0); } if (!window->monitor->window) @@ -477,67 +468,83 @@ static void releaseMonitor(_GLFWwindow* window) SetThreadExecutionState(ES_CONTINUOUS); // HACK: Restore mouse trail length saved in acquireMonitor - SystemParametersInfo(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0); + SystemParametersInfoW(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0); } _glfwInputMonitorWindow(window->monitor, NULL); _glfwRestoreVideoModeWin32(window->monitor); } -// Window callback function (handles window messages) +// Manually maximize the window, for when SW_MAXIMIZE cannot be used // -static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, - WPARAM wParam, LPARAM lParam) +static void maximizeWindowManually(_GLFWwindow* window) +{ + RECT rect; + DWORD style; + MONITORINFO mi = { sizeof(mi) }; + + GetMonitorInfoW(MonitorFromWindow(window->win32.handle, + MONITOR_DEFAULTTONEAREST), &mi); + + rect = mi.rcWork; + + if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE) + { + rect.right = _glfw_min(rect.right, rect.left + window->maxwidth); + rect.bottom = _glfw_min(rect.bottom, rect.top + window->maxheight); + } + + style = GetWindowLongW(window->win32.handle, GWL_STYLE); + style |= WS_MAXIMIZE; + SetWindowLongW(window->win32.handle, GWL_STYLE, style); + + if (window->decorated) + { + const DWORD exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE); + + if (_glfwIsWindows10Version1607OrGreaterWin32()) + { + const UINT dpi = GetDpiForWindow(window->win32.handle); + AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi); + OffsetRect(&rect, 0, GetSystemMetricsForDpi(SM_CYCAPTION, dpi)); + } + else + { + AdjustWindowRectEx(&rect, style, FALSE, exStyle); + OffsetRect(&rect, 0, GetSystemMetrics(SM_CYCAPTION)); + } + + rect.bottom = _glfw_min(rect.bottom, mi.rcWork.bottom); + } + + SetWindowPos(window->win32.handle, HWND_TOP, + rect.left, + rect.top, + rect.right - rect.left, + rect.bottom - rect.top, + SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED); +} + +// Window procedure for user-created windows +// +static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { _GLFWwindow* window = GetPropW(hWnd, L"GLFW"); if (!window) { - // This is the message handling for the hidden helper window - // and for a regular window during its initial creation - - switch (uMsg) + if (uMsg == WM_NCCREATE) { - case WM_NCCREATE: + if (_glfwIsWindows10Version1607OrGreaterWin32()) { - if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32()) - { - const CREATESTRUCTW* cs = (const CREATESTRUCTW*) lParam; - const _GLFWwndconfig* wndconfig = cs->lpCreateParams; + const CREATESTRUCTW* cs = (const CREATESTRUCTW*) lParam; + const _GLFWwndconfig* wndconfig = cs->lpCreateParams; - // On per-monitor DPI aware V1 systems, only enable - // non-client scaling for windows that scale the client area - // We need WM_GETDPISCALEDSIZE from V2 to keep the client - // area static when the non-client area is scaled - if (wndconfig && wndconfig->scaleToMonitor) - EnableNonClientDpiScaling(hWnd); - } - - break; - } - - case WM_DISPLAYCHANGE: - _glfwPollMonitorsWin32(); - break; - - case WM_DEVICECHANGE: - { - if (!_glfw.joysticksInitialized) - break; - - if (wParam == DBT_DEVICEARRIVAL) - { - DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam; - if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) - _glfwDetectJoystickConnectionWin32(); - } - else if (wParam == DBT_DEVICEREMOVECOMPLETE) - { - DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam; - if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) - _glfwDetectJoystickDisconnectionWin32(); - } - - break; + // On per-monitor DPI aware V1 systems, only enable + // non-client scaling for windows that scale the client area + // We need WM_GETDPISCALEDSIZE from V2 to keep the client + // area static when the non-client area is scaled + if (wndconfig && wndconfig->scaleToMonitor) + EnableNonClientDpiScaling(hWnd); } } @@ -567,6 +574,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, { if (window->cursorMode == GLFW_CURSOR_DISABLED) disableCursor(window); + else if (window->cursorMode == GLFW_CURSOR_CAPTURED) + captureCursor(window); window->win32.frameAction = GLFW_FALSE; } @@ -585,6 +594,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, if (window->cursorMode == GLFW_CURSOR_DISABLED) disableCursor(window); + else if (window->cursorMode == GLFW_CURSOR_CAPTURED) + captureCursor(window); return 0; } @@ -593,9 +604,11 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, { if (window->cursorMode == GLFW_CURSOR_DISABLED) enableCursor(window); + else if (window->cursorMode == GLFW_CURSOR_CAPTURED) + releaseCursor(); if (window->monitor && window->autoIconify) - _glfwPlatformIconifyWindow(window); + _glfwIconifyWindowWin32(window); _glfwInputWindowFocus(window, GLFW_FALSE); return 0; @@ -649,7 +662,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, window->win32.highSurrogate = (WCHAR) wParam; else { - unsigned int codepoint = 0; + uint32_t codepoint = 0; if (wParam >= 0xdc00 && wParam <= 0xdfff) { @@ -683,7 +696,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, return TRUE; } - _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GLFW_TRUE); + _glfwInputChar(window, (uint32_t) wParam, getKeyMods(), GLFW_TRUE); return 0; } @@ -704,6 +717,18 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, scancode = MapVirtualKeyW((UINT) wParam, MAPVK_VK_TO_VSC); } + // HACK: Alt+PrtSc has a different scancode than just PrtSc + if (scancode == 0x54) + scancode = 0x137; + + // HACK: Ctrl+Pause has a different scancode than just Pause + if (scancode == 0x146) + scancode = 0x45; + + // HACK: CJK IME sets the extended bit for right Shift + if (scancode == 0x136) + scancode = 0x36; + key = _glfw.win32.keycodes[scancode]; // The Ctrl keys require special handling @@ -755,7 +780,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, { // HACK: Release both Shift keys on Shift up event, as when both // are pressed the first release does not emit any event - // NOTE: The other half of this is in _glfwPlatformPollEvents + // NOTE: The other half of this is in _glfwPollEventsWin32 _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, action, mods); _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, action, mods); } @@ -950,6 +975,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, // resizing the window or using the window menu if (window->cursorMode == GLFW_CURSOR_DISABLED) enableCursor(window); + else if (window->cursorMode == GLFW_CURSOR_CAPTURED) + releaseCursor(); break; } @@ -964,6 +991,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, // resizing the window or using the menu if (window->cursorMode == GLFW_CURSOR_DISABLED) disableCursor(window); + else if (window->cursorMode == GLFW_CURSOR_CAPTURED) + captureCursor(window); break; } @@ -977,8 +1006,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, (window->win32.maximized && wParam != SIZE_RESTORED); - if (_glfw.win32.disabledCursorWindow == window) - updateClipRect(window); + if (_glfw.win32.capturedCursorWindow == window) + captureCursor(window); if (window->win32.iconified != iconified) _glfwInputWindowIconify(window, iconified); @@ -1013,8 +1042,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_MOVE: { - if (_glfw.win32.disabledCursorWindow == window) - updateClipRect(window); + if (_glfw.win32.capturedCursorWindow == window) + captureCursor(window); // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as // those macros do not handle negative window positions correctly @@ -1038,31 +1067,34 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_GETMINMAXINFO: { - int xoff, yoff; - UINT dpi = USER_DEFAULT_SCREEN_DPI; + RECT frame = {0}; MINMAXINFO* mmi = (MINMAXINFO*) lParam; + const DWORD style = getWindowStyle(window); + const DWORD exStyle = getWindowExStyle(window); if (window->monitor) break; - if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32()) - dpi = GetDpiForWindow(window->win32.handle); - - getFullWindowSize(getWindowStyle(window), getWindowExStyle(window), - 0, 0, &xoff, &yoff, dpi); + if (_glfwIsWindows10Version1607OrGreaterWin32()) + { + AdjustWindowRectExForDpi(&frame, style, FALSE, exStyle, + GetDpiForWindow(window->win32.handle)); + } + else + AdjustWindowRectEx(&frame, style, FALSE, exStyle); if (window->minwidth != GLFW_DONT_CARE && window->minheight != GLFW_DONT_CARE) { - mmi->ptMinTrackSize.x = window->minwidth + xoff; - mmi->ptMinTrackSize.y = window->minheight + yoff; + mmi->ptMinTrackSize.x = window->minwidth + frame.right - frame.left; + mmi->ptMinTrackSize.y = window->minheight + frame.bottom - frame.top; } if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE) { - mmi->ptMaxTrackSize.x = window->maxwidth + xoff; - mmi->ptMaxTrackSize.y = window->maxheight + yoff; + mmi->ptMaxTrackSize.x = window->maxwidth + frame.right - frame.left; + mmi->ptMaxTrackSize.y = window->maxheight + frame.bottom - frame.top; } if (!window->decorated) @@ -1073,7 +1105,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, ZeroMemory(&mi, sizeof(mi)); mi.cbSize = sizeof(mi); - GetMonitorInfo(mh, &mi); + GetMonitorInfoW(mh, &mi); mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left; mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top; @@ -1120,7 +1152,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, break; // Adjust the window size to keep the content area size constant - if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32()) + if (_glfwIsWindows10Version1703OrGreaterWin32()) { RECT source = {0}, target = {0}; SIZE* size = (SIZE*) lParam; @@ -1151,7 +1183,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, // need it to compensate for non-client area scaling if (!window->monitor && (window->win32.scaleToMonitor || - _glfwIsWindows10CreatorsUpdateOrGreaterWin32())) + _glfwIsWindows10Version1703OrGreaterWin32())) { RECT* suggested = (RECT*) lParam; SetWindowPos(window->win32.handle, HWND_TOP, @@ -1221,36 +1253,80 @@ static int createNativeWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWfbconfig* fbconfig) { - int xpos, ypos, fullWidth, fullHeight; + int frameX, frameY, frameWidth, frameHeight; WCHAR* wideTitle; DWORD style = getWindowStyle(window); DWORD exStyle = getWindowExStyle(window); + if (!_glfw.win32.mainWindowClass) + { + WNDCLASSEXW wc = { sizeof(wc) }; + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = windowProc; + wc.hInstance = _glfw.win32.instance; + wc.hCursor = LoadCursorW(NULL, IDC_ARROW); +#if defined(_GLFW_WNDCLASSNAME) + wc.lpszClassName = _GLFW_WNDCLASSNAME; +#else + wc.lpszClassName = L"GLFW30"; +#endif + // Load user-provided icon if available + wc.hIcon = LoadImageW(GetModuleHandleW(NULL), + L"GLFW_ICON", IMAGE_ICON, + 0, 0, LR_DEFAULTSIZE | LR_SHARED); + if (!wc.hIcon) + { + // No user-provided icon found, load default icon + wc.hIcon = LoadImageW(NULL, + IDI_APPLICATION, IMAGE_ICON, + 0, 0, LR_DEFAULTSIZE | LR_SHARED); + } + + _glfw.win32.mainWindowClass = RegisterClassExW(&wc); + if (!_glfw.win32.mainWindowClass) + { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to register window class"); + return GLFW_FALSE; + } + } + if (window->monitor) { - GLFWvidmode mode; + MONITORINFO mi = { sizeof(mi) }; + GetMonitorInfoW(window->monitor->win32.handle, &mi); // NOTE: This window placement is temporary and approximate, as the // correct position and size cannot be known until the monitor // video mode has been picked in _glfwSetVideoModeWin32 - _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos); - _glfwPlatformGetVideoMode(window->monitor, &mode); - fullWidth = mode.width; - fullHeight = mode.height; + frameX = mi.rcMonitor.left; + frameY = mi.rcMonitor.top; + frameWidth = mi.rcMonitor.right - mi.rcMonitor.left; + frameHeight = mi.rcMonitor.bottom - mi.rcMonitor.top; } else { - xpos = CW_USEDEFAULT; - ypos = CW_USEDEFAULT; + RECT rect = { 0, 0, wndconfig->width, wndconfig->height }; window->win32.maximized = wndconfig->maximized; if (wndconfig->maximized) style |= WS_MAXIMIZE; - getFullWindowSize(style, exStyle, - wndconfig->width, wndconfig->height, - &fullWidth, &fullHeight, - USER_DEFAULT_SCREEN_DPI); + AdjustWindowRectEx(&rect, style, FALSE, exStyle); + + if (wndconfig->xpos == GLFW_ANY_POSITION && wndconfig->ypos == GLFW_ANY_POSITION) + { + frameX = CW_USEDEFAULT; + frameY = CW_USEDEFAULT; + } + else + { + frameX = wndconfig->xpos + rect.left; + frameY = wndconfig->ypos + rect.top; + } + + frameWidth = rect.right - rect.left; + frameHeight = rect.bottom - rect.top; } wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title); @@ -1258,14 +1334,14 @@ static int createNativeWindow(_GLFWwindow* window, return GLFW_FALSE; window->win32.handle = CreateWindowExW(exStyle, - _GLFW_WNDCLASSNAME, + MAKEINTATOM(_glfw.win32.mainWindowClass), wideTitle, style, - xpos, ypos, - fullWidth, fullHeight, + frameX, frameY, + frameWidth, frameHeight, NULL, // No parent window NULL, // No window menu - GetModuleHandleW(NULL), + _glfw.win32.instance, (LPVOID) wndconfig); _glfw_free(wideTitle); @@ -1292,26 +1368,31 @@ static int createNativeWindow(_GLFWwindow* window, window->win32.scaleToMonitor = wndconfig->scaleToMonitor; window->win32.keymenu = wndconfig->win32.keymenu; - // Adjust window rect to account for DPI scaling of the window frame and - // (if enabled) DPI scaling of the content area - // This cannot be done until we know what monitor the window was placed on if (!window->monitor) { RECT rect = { 0, 0, wndconfig->width, wndconfig->height }; WINDOWPLACEMENT wp = { sizeof(wp) }; + const HMONITOR mh = MonitorFromWindow(window->win32.handle, + MONITOR_DEFAULTTONEAREST); + + // Adjust window rect to account for DPI scaling of the window frame and + // (if enabled) DPI scaling of the content area + // This cannot be done until we know what monitor the window was placed on + // Only update the restored window rect as the window may be maximized if (wndconfig->scaleToMonitor) { float xscale, yscale; - _glfwPlatformGetWindowContentScale(window, &xscale, &yscale); - rect.right = (int) (rect.right * xscale); - rect.bottom = (int) (rect.bottom * yscale); + _glfwGetHMONITORContentScaleWin32(mh, &xscale, &yscale); + + if (xscale > 0.f && yscale > 0.f) + { + rect.right = (int) (rect.right * xscale); + rect.bottom = (int) (rect.bottom * yscale); + } } - ClientToScreen(window->win32.handle, (POINT*) &rect.left); - ClientToScreen(window->win32.handle, (POINT*) &rect.right); - - if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32()) + if (_glfwIsWindows10Version1607OrGreaterWin32()) { AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, GetDpiForWindow(window->win32.handle)); @@ -1319,11 +1400,30 @@ static int createNativeWindow(_GLFWwindow* window, else AdjustWindowRectEx(&rect, style, FALSE, exStyle); - // Only update the restored window rect as the window may be maximized GetWindowPlacement(window->win32.handle, &wp); + OffsetRect(&rect, + wp.rcNormalPosition.left - rect.left, + wp.rcNormalPosition.top - rect.top); + wp.rcNormalPosition = rect; wp.showCmd = SW_HIDE; SetWindowPlacement(window->win32.handle, &wp); + + // Adjust rect of maximized undecorated window, because by default Windows will + // make such a window cover the whole monitor instead of its workarea + + if (wndconfig->maximized && !wndconfig->decorated) + { + MONITORINFO mi = { sizeof(mi) }; + GetMonitorInfoW(mh, &mi); + + SetWindowPos(window->win32.handle, HWND_TOP, + mi.rcWork.left, + mi.rcWork.top, + mi.rcWork.right - mi.rcWork.left, + mi.rcWork.bottom - mi.rcWork.top, + SWP_NOACTIVATE | SWP_NOZORDER); + } } DragAcceptFiles(window->win32.handle, TRUE); @@ -1334,68 +1434,15 @@ static int createNativeWindow(_GLFWwindow* window, window->win32.transparent = GLFW_TRUE; } - _glfwPlatformGetWindowSize(window, &window->win32.width, &window->win32.height); + _glfwGetWindowSizeWin32(window, &window->win32.width, &window->win32.height); return GLFW_TRUE; } - -////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// -////////////////////////////////////////////////////////////////////////// - -// Registers the GLFW window class -// -GLFWbool _glfwRegisterWindowClassWin32(void) -{ - WNDCLASSEXW wc; - - ZeroMemory(&wc, sizeof(wc)); - wc.cbSize = sizeof(wc); - wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; - wc.lpfnWndProc = (WNDPROC) windowProc; - wc.hInstance = GetModuleHandleW(NULL); - wc.hCursor = LoadCursorW(NULL, IDC_ARROW); - wc.lpszClassName = _GLFW_WNDCLASSNAME; - - // Load user-provided icon if available - wc.hIcon = LoadImageW(GetModuleHandleW(NULL), - L"GLFW_ICON", IMAGE_ICON, - 0, 0, LR_DEFAULTSIZE | LR_SHARED); - if (!wc.hIcon) - { - // No user-provided icon found, load default icon - wc.hIcon = LoadImageW(NULL, - IDI_APPLICATION, IMAGE_ICON, - 0, 0, LR_DEFAULTSIZE | LR_SHARED); - } - - if (!RegisterClassExW(&wc)) - { - _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to register window class"); - return GLFW_FALSE; - } - - return GLFW_TRUE; -} - -// Unregisters the GLFW window class -// -void _glfwUnregisterWindowClassWin32(void) -{ - UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL)); -} - - -////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// - -int _glfwPlatformCreateWindow(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig) +GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig) { if (!createNativeWindow(window, wndconfig, fbconfig)) return GLFW_FALSE; @@ -1423,20 +1470,38 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig)) return GLFW_FALSE; } + + if (!_glfwRefreshContextAttribs(window, ctxconfig)) + return GLFW_FALSE; } + if (wndconfig->mousePassthrough) + _glfwSetWindowMousePassthroughWin32(window, GLFW_TRUE); + if (window->monitor) { - _glfwPlatformShowWindow(window); - _glfwPlatformFocusWindow(window); + _glfwShowWindowWin32(window); + _glfwFocusWindowWin32(window); acquireMonitor(window); fitToMonitor(window); + + if (wndconfig->centerCursor) + _glfwCenterCursorInContentArea(window); + } + else + { + if (wndconfig->visible) + { + _glfwShowWindowWin32(window); + if (wndconfig->focused) + _glfwFocusWindowWin32(window); + } } return GLFW_TRUE; } -void _glfwPlatformDestroyWindow(_GLFWwindow* window) +void _glfwDestroyWindowWin32(_GLFWwindow* window) { if (window->monitor) releaseMonitor(window); @@ -1445,7 +1510,10 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) window->context.destroy(window); if (_glfw.win32.disabledCursorWindow == window) - _glfw.win32.disabledCursorWindow = NULL; + enableCursor(window); + + if (_glfw.win32.capturedCursorWindow == window) + releaseCursor(); if (window->win32.handle) { @@ -1461,7 +1529,7 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) DestroyIcon(window->win32.smallIcon); } -void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) +void _glfwSetWindowTitleWin32(_GLFWwindow* window, const char* title) { WCHAR* wideTitle = _glfwCreateWideStringFromUTF8Win32(title); if (!wideTitle) @@ -1471,8 +1539,7 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) _glfw_free(wideTitle); } -void _glfwPlatformSetWindowIcon(_GLFWwindow* window, - int count, const GLFWimage* images) +void _glfwSetWindowIconWin32(_GLFWwindow* window, int count, const GLFWimage* images) { HICON bigIcon = NULL, smallIcon = NULL; @@ -1494,8 +1561,8 @@ void _glfwPlatformSetWindowIcon(_GLFWwindow* window, smallIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICONSM); } - SendMessage(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon); - SendMessage(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon); + SendMessageW(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon); + SendMessageW(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon); if (window->win32.bigIcon) DestroyIcon(window->win32.bigIcon); @@ -1510,7 +1577,7 @@ void _glfwPlatformSetWindowIcon(_GLFWwindow* window, } } -void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) +void _glfwGetWindowPosWin32(_GLFWwindow* window, int* xpos, int* ypos) { POINT pos = { 0, 0 }; ClientToScreen(window->win32.handle, &pos); @@ -1521,11 +1588,11 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) *ypos = pos.y; } -void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) +void _glfwSetWindowPosWin32(_GLFWwindow* window, int xpos, int ypos) { RECT rect = { xpos, ypos, xpos, ypos }; - if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32()) + if (_glfwIsWindows10Version1607OrGreaterWin32()) { AdjustWindowRectExForDpi(&rect, getWindowStyle(window), FALSE, getWindowExStyle(window), @@ -1541,7 +1608,7 @@ void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE); } -void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) +void _glfwGetWindowSizeWin32(_GLFWwindow* window, int* width, int* height) { RECT area; GetClientRect(window->win32.handle, &area); @@ -1552,7 +1619,7 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) *height = area.bottom; } -void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) +void _glfwSetWindowSizeWin32(_GLFWwindow* window, int width, int height) { if (window->monitor) { @@ -1566,7 +1633,7 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) { RECT rect = { 0, 0, width, height }; - if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32()) + if (_glfwIsWindows10Version1607OrGreaterWin32()) { AdjustWindowRectExForDpi(&rect, getWindowStyle(window), FALSE, getWindowExStyle(window), @@ -1584,9 +1651,9 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) } } -void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, - int minwidth, int minheight, - int maxwidth, int maxheight) +void _glfwSetWindowSizeLimitsWin32(_GLFWwindow* window, + int minwidth, int minheight, + int maxwidth, int maxheight) { RECT area; @@ -1603,7 +1670,7 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, area.bottom - area.top, TRUE); } -void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom) +void _glfwSetWindowAspectRatioWin32(_GLFWwindow* window, int numer, int denom) { RECT area; @@ -1618,22 +1685,22 @@ void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom area.bottom - area.top, TRUE); } -void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) +void _glfwGetFramebufferSizeWin32(_GLFWwindow* window, int* width, int* height) { - _glfwPlatformGetWindowSize(window, width, height); + _glfwGetWindowSizeWin32(window, width, height); } -void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, - int* left, int* top, - int* right, int* bottom) +void _glfwGetWindowFrameSizeWin32(_GLFWwindow* window, + int* left, int* top, + int* right, int* bottom) { RECT rect; int width, height; - _glfwPlatformGetWindowSize(window, &width, &height); + _glfwGetWindowSizeWin32(window, &width, &height); SetRect(&rect, 0, 0, width, height); - if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32()) + if (_glfwIsWindows10Version1607OrGreaterWin32()) { AdjustWindowRectExForDpi(&rect, getWindowStyle(window), FALSE, getWindowExStyle(window), @@ -1655,56 +1722,58 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, *bottom = rect.bottom - height; } -void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, - float* xscale, float* yscale) +void _glfwGetWindowContentScaleWin32(_GLFWwindow* window, float* xscale, float* yscale) { const HANDLE handle = MonitorFromWindow(window->win32.handle, MONITOR_DEFAULTTONEAREST); - _glfwGetMonitorContentScaleWin32(handle, xscale, yscale); + _glfwGetHMONITORContentScaleWin32(handle, xscale, yscale); } -void _glfwPlatformIconifyWindow(_GLFWwindow* window) +void _glfwIconifyWindowWin32(_GLFWwindow* window) { ShowWindow(window->win32.handle, SW_MINIMIZE); } -void _glfwPlatformRestoreWindow(_GLFWwindow* window) +void _glfwRestoreWindowWin32(_GLFWwindow* window) { ShowWindow(window->win32.handle, SW_RESTORE); } -void _glfwPlatformMaximizeWindow(_GLFWwindow* window) +void _glfwMaximizeWindowWin32(_GLFWwindow* window) { - ShowWindow(window->win32.handle, SW_MAXIMIZE); + if (IsWindowVisible(window->win32.handle)) + ShowWindow(window->win32.handle, SW_MAXIMIZE); + else + maximizeWindowManually(window); } -void _glfwPlatformShowWindow(_GLFWwindow* window) +void _glfwShowWindowWin32(_GLFWwindow* window) { ShowWindow(window->win32.handle, SW_SHOWNA); } -void _glfwPlatformHideWindow(_GLFWwindow* window) +void _glfwHideWindowWin32(_GLFWwindow* window) { ShowWindow(window->win32.handle, SW_HIDE); } -void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) +void _glfwRequestWindowAttentionWin32(_GLFWwindow* window) { FlashWindow(window->win32.handle, TRUE); } -void _glfwPlatformFocusWindow(_GLFWwindow* window) +void _glfwFocusWindowWin32(_GLFWwindow* window) { BringWindowToTop(window->win32.handle); SetForegroundWindow(window->win32.handle); SetFocus(window->win32.handle); } -void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, - _GLFWmonitor* monitor, - int xpos, int ypos, - int width, int height, - int refreshRate) +void _glfwSetWindowMonitorWin32(_GLFWwindow* window, + _GLFWmonitor* monitor, + int xpos, int ypos, + int width, int height, + int refreshRate) { if (window->monitor == monitor) { @@ -1720,7 +1789,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, { RECT rect = { xpos, ypos, xpos + width, ypos + height }; - if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32()) + if (_glfwIsWindows10Version1607OrGreaterWin32()) { AdjustWindowRectExForDpi(&rect, getWindowStyle(window), FALSE, getWindowExStyle(window), @@ -1762,7 +1831,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, acquireMonitor(window); - GetMonitorInfo(window->monitor->win32.handle, &mi); + GetMonitorInfoW(window->monitor->win32.handle, &mi); SetWindowPos(window->win32.handle, HWND_TOPMOST, mi.rcMonitor.left, mi.rcMonitor.top, @@ -1791,7 +1860,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, else after = HWND_NOTOPMOST; - if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32()) + if (_glfwIsWindows10Version1607OrGreaterWin32()) { AdjustWindowRectExForDpi(&rect, getWindowStyle(window), FALSE, getWindowExStyle(window), @@ -1810,32 +1879,32 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, } } -int _glfwPlatformWindowFocused(_GLFWwindow* window) +GLFWbool _glfwWindowFocusedWin32(_GLFWwindow* window) { return window->win32.handle == GetActiveWindow(); } -int _glfwPlatformWindowIconified(_GLFWwindow* window) +GLFWbool _glfwWindowIconifiedWin32(_GLFWwindow* window) { return IsIconic(window->win32.handle); } -int _glfwPlatformWindowVisible(_GLFWwindow* window) +GLFWbool _glfwWindowVisibleWin32(_GLFWwindow* window) { return IsWindowVisible(window->win32.handle); } -int _glfwPlatformWindowMaximized(_GLFWwindow* window) +GLFWbool _glfwWindowMaximizedWin32(_GLFWwindow* window) { return IsZoomed(window->win32.handle); } -int _glfwPlatformWindowHovered(_GLFWwindow* window) +GLFWbool _glfwWindowHoveredWin32(_GLFWwindow* window) { return cursorInContentArea(window); } -int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) +GLFWbool _glfwFramebufferTransparentWin32(_GLFWwindow* window) { BOOL composition, opaque; DWORD color; @@ -1862,24 +1931,24 @@ int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) return GLFW_TRUE; } -void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowResizableWin32(_GLFWwindow* window, GLFWbool enabled) { updateWindowStyles(window); } -void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowDecoratedWin32(_GLFWwindow* window, GLFWbool enabled) { updateWindowStyles(window); } -void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowFloatingWin32(_GLFWwindow* window, GLFWbool enabled) { const HWND after = enabled ? HWND_TOPMOST : HWND_NOTOPMOST; SetWindowPos(window->win32.handle, after, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); } -void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowMousePassthroughWin32(_GLFWwindow* window, GLFWbool enabled) { COLORREF key = 0; BYTE alpha = 0; @@ -1909,7 +1978,7 @@ void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enable SetLayeredWindowAttributes(window->win32.handle, key, alpha, flags); } -float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) +float _glfwGetWindowOpacityWin32(_GLFWwindow* window) { BYTE alpha; DWORD flags; @@ -1924,7 +1993,7 @@ float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) return 1.f; } -void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) +void _glfwSetWindowOpacityWin32(_GLFWwindow* window, float opacity) { LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE); if (opacity < 1.f || (exStyle & WS_EX_TRANSPARENT)) @@ -1945,7 +2014,7 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) } } -void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled) +void _glfwSetRawMouseMotionWin32(_GLFWwindow *window, GLFWbool enabled) { if (_glfw.win32.disabledCursorWindow != window) return; @@ -1956,12 +2025,12 @@ void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled) disableRawMouseMotion(window); } -GLFWbool _glfwPlatformRawMouseMotionSupported(void) +GLFWbool _glfwRawMouseMotionSupportedWin32(void) { return GLFW_TRUE; } -void _glfwPlatformPollEvents(void) +void _glfwPollEventsWin32(void) { MSG msg; HWND handle; @@ -2031,38 +2100,38 @@ void _glfwPlatformPollEvents(void) if (window) { int width, height; - _glfwPlatformGetWindowSize(window, &width, &height); + _glfwGetWindowSizeWin32(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.lastCursorPosX != width / 2 || window->win32.lastCursorPosY != height / 2) { - _glfwPlatformSetCursorPos(window, width / 2, height / 2); + _glfwSetCursorPosWin32(window, width / 2, height / 2); } } } -void _glfwPlatformWaitEvents(void) +void _glfwWaitEventsWin32(void) { WaitMessage(); - _glfwPlatformPollEvents(); + _glfwPollEventsWin32(); } -void _glfwPlatformWaitEventsTimeout(double timeout) +void _glfwWaitEventsTimeoutWin32(double timeout) { MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLEVENTS); - _glfwPlatformPollEvents(); + _glfwPollEventsWin32(); } -void _glfwPlatformPostEmptyEvent(void) +void _glfwPostEmptyEventWin32(void) { - PostMessage(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0); + PostMessageW(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0); } -void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) +void _glfwGetCursorPosWin32(_GLFWwindow* window, double* xpos, double* ypos) { POINT pos; @@ -2077,7 +2146,7 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) } } -void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos) +void _glfwSetCursorPosWin32(_GLFWwindow* window, double xpos, double ypos) { POINT pos = { (int) xpos, (int) ypos }; @@ -2089,20 +2158,46 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos) SetCursorPos(pos.x, pos.y); } -void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) +void _glfwSetCursorModeWin32(_GLFWwindow* window, int mode) { - if (mode == GLFW_CURSOR_DISABLED) + if (_glfwWindowFocusedWin32(window)) { - if (_glfwPlatformWindowFocused(window)) - disableCursor(window); + if (mode == GLFW_CURSOR_DISABLED) + { + _glfwGetCursorPosWin32(window, + &_glfw.win32.restoreCursorPosX, + &_glfw.win32.restoreCursorPosY); + _glfwCenterCursorInContentArea(window); + if (window->rawMouseMotion) + enableRawMouseMotion(window); + } + else if (_glfw.win32.disabledCursorWindow == window) + { + if (window->rawMouseMotion) + disableRawMouseMotion(window); + } + + if (mode == GLFW_CURSOR_DISABLED || mode == GLFW_CURSOR_CAPTURED) + captureCursor(window); + else + releaseCursor(); + + if (mode == GLFW_CURSOR_DISABLED) + _glfw.win32.disabledCursorWindow = window; + else if (_glfw.win32.disabledCursorWindow == window) + { + _glfw.win32.disabledCursorWindow = NULL; + _glfwSetCursorPosWin32(window, + _glfw.win32.restoreCursorPosX, + _glfw.win32.restoreCursorPosY); + } } - else if (_glfw.win32.disabledCursorWindow == window) - enableCursor(window); - else if (cursorInContentArea(window)) + + if (cursorInContentArea(window)) updateCursorImage(window); } -const char* _glfwPlatformGetScancodeName(int scancode) +const char* _glfwGetScancodeNameWin32(int scancode) { if (scancode < 0 || scancode > (KF_EXTENDED | 0xff) || _glfw.win32.keycodes[scancode] == GLFW_KEY_UNKNOWN) @@ -2114,14 +2209,14 @@ const char* _glfwPlatformGetScancodeName(int scancode) return _glfw.win32.keynames[_glfw.win32.keycodes[scancode]]; } -int _glfwPlatformGetKeyScancode(int key) +int _glfwGetKeyScancodeWin32(int key) { return _glfw.win32.scancodes[key]; } -int _glfwPlatformCreateCursor(_GLFWcursor* cursor, - const GLFWimage* image, - int xhot, int yhot) +GLFWbool _glfwCreateCursorWin32(_GLFWcursor* cursor, + const GLFWimage* image, + int xhot, int yhot) { cursor->win32.handle = (HCURSOR) createIcon(image, xhot, yhot, GLFW_FALSE); if (!cursor->win32.handle) @@ -2130,7 +2225,7 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor, return GLFW_TRUE; } -int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) +GLFWbool _glfwCreateStandardCursorWin32(_GLFWcursor* cursor, int shape) { int id = 0; @@ -2184,19 +2279,19 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) return GLFW_TRUE; } -void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) +void _glfwDestroyCursorWin32(_GLFWcursor* cursor) { if (cursor->win32.handle) DestroyIcon((HICON) cursor->win32.handle); } -void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) +void _glfwSetCursorWin32(_GLFWwindow* window, _GLFWcursor* cursor) { if (cursorInContentArea(window)) updateCursorImage(window); } -void _glfwPlatformSetClipboardString(const char* string) +void _glfwSetClipboardStringWin32(const char* string) { int characterCount; HANDLE object; @@ -2239,7 +2334,7 @@ void _glfwPlatformSetClipboardString(const char* string) CloseClipboard(); } -const char* _glfwPlatformGetClipboardString(void) +const char* _glfwGetClipboardStringWin32(void) { HANDLE object; WCHAR* buffer; @@ -2278,7 +2373,7 @@ const char* _glfwPlatformGetClipboardString(void) return _glfw.win32.clipboardString; } -EGLenum _glfwPlatformGetEGLPlatform(EGLint** attribs) +EGLenum _glfwGetEGLPlatformWin32(EGLint** attribs) { if (_glfw.egl.ANGLE_platform_angle) { @@ -2319,17 +2414,17 @@ EGLenum _glfwPlatformGetEGLPlatform(EGLint** attribs) return 0; } -EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void) +EGLNativeDisplayType _glfwGetEGLNativeDisplayWin32(void) { return GetDC(_glfw.win32.helperWindowHandle); } -EGLNativeWindowType _glfwPlatformGetEGLNativeWindow(_GLFWwindow* window) +EGLNativeWindowType _glfwGetEGLNativeWindowWin32(_GLFWwindow* window) { return window->win32.handle; } -void _glfwPlatformGetRequiredInstanceExtensions(char** extensions) +void _glfwGetRequiredInstanceExtensionsWin32(char** extensions) { if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_win32_surface) return; @@ -2338,9 +2433,9 @@ void _glfwPlatformGetRequiredInstanceExtensions(char** extensions) extensions[1] = "VK_KHR_win32_surface"; } -int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, - VkPhysicalDevice device, - uint32_t queuefamily) +GLFWbool _glfwGetPhysicalDevicePresentationSupportWin32(VkInstance instance, + VkPhysicalDevice device, + uint32_t queuefamily) { PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR = @@ -2356,10 +2451,10 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, return vkGetPhysicalDeviceWin32PresentationSupportKHR(device, queuefamily); } -VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, - _GLFWwindow* window, - const VkAllocationCallbacks* allocator, - VkSurfaceKHR* surface) +VkResult _glfwCreateWindowSurfaceWin32(VkInstance instance, + _GLFWwindow* window, + const VkAllocationCallbacks* allocator, + VkSurfaceKHR* surface) { VkResult err; VkWin32SurfaceCreateInfoKHR sci; @@ -2376,7 +2471,7 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, memset(&sci, 0, sizeof(sci)); sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; - sci.hinstance = GetModuleHandle(NULL); + sci.hinstance = _glfw.win32.instance; sci.hwnd = window->win32.handle; err = vkCreateWin32SurfaceKHR(instance, &sci, allocator, surface); @@ -2390,15 +2485,20 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, return err; } - -////////////////////////////////////////////////////////////////////////// -////// GLFW native API ////// -////////////////////////////////////////////////////////////////////////// - GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + + if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32) + { + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, + "Win32: Platform not initialized"); + return NULL; + } + return window->win32.handle; } +#endif // _GLFW_WIN32 + diff --git a/src/window.c b/src/window.c index 64dbd54e..b709472d 100644 --- a/src/window.c +++ b/src/window.c @@ -35,32 +35,34 @@ #include #include - ////////////////////////////////////////////////////////////////////////// ////// GLFW event API ////// ////////////////////////////////////////////////////////////////////////// // Notifies shared code that a window has lost or received input focus // -void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) +void _glfwInputWindowFocus(_GLFWwindow *window, GLFWbool focused) { + assert(window != NULL); + assert(focused == GLFW_TRUE || focused == GLFW_FALSE); + if (window->callbacks.focus) - window->callbacks.focus((GLFWwindow*) window, focused); + window->callbacks.focus((GLFWwindow *)window, focused); if (!focused) { int key, button; - for (key = 0; key <= GLFW_KEY_LAST; key++) + for (key = 0; key <= GLFW_KEY_LAST; key++) { if (window->keys[key] == GLFW_PRESS) { - const int scancode = _glfwPlatformGetKeyScancode(key); + const int scancode = _glfw.platform.getKeyScancode(key); _glfwInputKey(window, key, scancode, GLFW_RELEASE, 0); } } - for (button = 0; button <= GLFW_MOUSE_BUTTON_LAST; button++) + for (button = 0; button <= GLFW_MOUSE_BUTTON_LAST; button++) { if (window->mouseButtons[button] == GLFW_PRESS) _glfwInputMouseClick(window, button, GLFW_RELEASE, 0); @@ -71,77 +73,104 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) // Notifies shared code that a window has moved // The position is specified in content area relative screen coordinates // -void _glfwInputWindowPos(_GLFWwindow* window, int x, int y) +void _glfwInputWindowPos(_GLFWwindow *window, int x, int y) { + assert(window != NULL); + if (window->callbacks.pos) - window->callbacks.pos((GLFWwindow*) window, x, y); + window->callbacks.pos((GLFWwindow *)window, x, y); } // Notifies shared code that a window has been resized // The size is specified in screen coordinates // -void _glfwInputWindowSize(_GLFWwindow* window, int width, int height) +void _glfwInputWindowSize(_GLFWwindow *window, int width, int height) { + assert(window != NULL); + assert(width >= 0); + assert(height >= 0); + if (window->callbacks.size) - window->callbacks.size((GLFWwindow*) window, width, height); + window->callbacks.size((GLFWwindow *)window, width, height); } // Notifies shared code that a window has been iconified or restored // -void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified) +void _glfwInputWindowIconify(_GLFWwindow *window, GLFWbool iconified) { + assert(window != NULL); + assert(iconified == GLFW_TRUE || iconified == GLFW_FALSE); + if (window->callbacks.iconify) - window->callbacks.iconify((GLFWwindow*) window, iconified); + window->callbacks.iconify((GLFWwindow *)window, iconified); } // Notifies shared code that a window has been maximized or restored // -void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized) +void _glfwInputWindowMaximize(_GLFWwindow *window, GLFWbool maximized) { + assert(window != NULL); + assert(maximized == GLFW_TRUE || maximized == GLFW_FALSE); + if (window->callbacks.maximize) - window->callbacks.maximize((GLFWwindow*) window, maximized); + window->callbacks.maximize((GLFWwindow *)window, maximized); } // Notifies shared code that a window framebuffer has been resized // The size is specified in pixels // -void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height) +void _glfwInputFramebufferSize(_GLFWwindow *window, int width, int height) { + assert(window != NULL); + assert(width >= 0); + assert(height >= 0); + if (window->callbacks.fbsize) - window->callbacks.fbsize((GLFWwindow*) window, width, height); + window->callbacks.fbsize((GLFWwindow *)window, width, height); } // Notifies shared code that a window content scale has changed // The scale is specified as the ratio between the current and default DPI // -void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale) +void _glfwInputWindowContentScale(_GLFWwindow *window, float xscale, float yscale) { + assert(window != NULL); + assert(xscale > 0.f); + assert(xscale < FLT_MAX); + assert(yscale > 0.f); + assert(yscale < FLT_MAX); + if (window->callbacks.scale) - window->callbacks.scale((GLFWwindow*) window, xscale, yscale); + window->callbacks.scale((GLFWwindow *)window, xscale, yscale); } // Notifies shared code that the window contents needs updating // -void _glfwInputWindowDamage(_GLFWwindow* window) +void _glfwInputWindowDamage(_GLFWwindow *window) { + assert(window != NULL); + if (window->callbacks.refresh) - window->callbacks.refresh((GLFWwindow*) window); + window->callbacks.refresh((GLFWwindow *)window); } // Notifies shared code that the user wishes to close a window // -void _glfwInputWindowCloseRequest(_GLFWwindow* window) +void _glfwInputWindowCloseRequest(_GLFWwindow *window) { + assert(window != NULL); + window->shouldClose = GLFW_TRUE; if (window->callbacks.close) - window->callbacks.close((GLFWwindow*) window); + window->callbacks.close((GLFWwindow *)window); } // Notifies shared code that a window has changed its desired monitor // -void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor) +void _glfwInputWindowMonitor(_GLFWwindow *window, _GLFWmonitor *monitor) { + assert(window != NULL); window->monitor = monitor; } @@ -149,15 +178,15 @@ void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor) ////// GLFW public API ////// ////////////////////////////////////////////////////////////////////////// -GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, - const char* title, - GLFWmonitor* monitor, - GLFWwindow* share) +GLFWAPI GLFWwindow *glfwCreateWindow(int width, int height, + const char *title, + GLFWmonitor *monitor, + GLFWwindow *share) { _GLFWfbconfig fbconfig; _GLFWctxconfig ctxconfig; _GLFWwndconfig wndconfig; - _GLFWwindow* window; + _GLFWwindow *window; assert(title != NULL); assert(width >= 0); @@ -174,14 +203,14 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, return NULL; } - fbconfig = _glfw.hints.framebuffer; + fbconfig = _glfw.hints.framebuffer; ctxconfig = _glfw.hints.context; wndconfig = _glfw.hints.window; - wndconfig.width = width; - wndconfig.height = height; - wndconfig.title = title; - ctxconfig.share = (_GLFWwindow*) share; + wndconfig.width = width; + wndconfig.height = height; + wndconfig.title = title; + ctxconfig.share = (_GLFWwindow *)share; if (!_glfwIsValidContextConfig(&ctxconfig)) return NULL; @@ -190,66 +219,38 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, window->next = _glfw.windowListHead; _glfw.windowListHead = window; - window->videoMode.width = width; - window->videoMode.height = height; - window->videoMode.redBits = fbconfig.redBits; - window->videoMode.greenBits = fbconfig.greenBits; - window->videoMode.blueBits = fbconfig.blueBits; + window->videoMode.width = width; + window->videoMode.height = height; + window->videoMode.redBits = fbconfig.redBits; + window->videoMode.greenBits = fbconfig.greenBits; + window->videoMode.blueBits = fbconfig.blueBits; window->videoMode.refreshRate = _glfw.hints.refreshRate; - window->monitor = (_GLFWmonitor*) monitor; - window->resizable = wndconfig.resizable; - window->decorated = wndconfig.decorated; - window->autoIconify = wndconfig.autoIconify; - window->floating = wndconfig.floating; - window->focusOnShow = wndconfig.focusOnShow; + window->monitor = (_GLFWmonitor *)monitor; + window->resizable = wndconfig.resizable; + window->decorated = wndconfig.decorated; + window->autoIconify = wndconfig.autoIconify; + window->floating = wndconfig.floating; + window->focusOnShow = wndconfig.focusOnShow; window->mousePassthrough = wndconfig.mousePassthrough; - window->cursorMode = GLFW_CURSOR_NORMAL; + window->cursorMode = GLFW_CURSOR_NORMAL; window->doublebuffer = fbconfig.doublebuffer; - window->minwidth = GLFW_DONT_CARE; - window->minheight = GLFW_DONT_CARE; - window->maxwidth = GLFW_DONT_CARE; - window->maxheight = GLFW_DONT_CARE; - window->numer = GLFW_DONT_CARE; - window->denom = GLFW_DONT_CARE; + window->minwidth = GLFW_DONT_CARE; + window->minheight = GLFW_DONT_CARE; + window->maxwidth = GLFW_DONT_CARE; + window->maxheight = GLFW_DONT_CARE; + window->numer = GLFW_DONT_CARE; + window->denom = GLFW_DONT_CARE; - // Open the actual window and create its context - if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig)) + if (!_glfw.platform.createWindow(window, &wndconfig, &ctxconfig, &fbconfig)) { - glfwDestroyWindow((GLFWwindow*) window); + glfwDestroyWindow((GLFWwindow *)window); return NULL; } - if (ctxconfig.client != GLFW_NO_API) - { - if (!_glfwRefreshContextAttribs(window, &ctxconfig)) - { - glfwDestroyWindow((GLFWwindow*) window); - return NULL; - } - } - - if (wndconfig.mousePassthrough) - _glfwPlatformSetWindowMousePassthrough(window, GLFW_TRUE); - - if (window->monitor) - { - if (wndconfig.centerCursor) - _glfwCenterCursorInContentArea(window); - } - else - { - if (wndconfig.visible) - { - _glfwPlatformShowWindow(window); - if (wndconfig.focused) - _glfwPlatformFocusWindow(window); - } - } - - return (GLFWwindow*) window; + return (GLFWwindow *)window; } void glfwDefaultWindowHints(void) @@ -260,28 +261,30 @@ void glfwDefaultWindowHints(void) memset(&_glfw.hints.context, 0, sizeof(_glfw.hints.context)); _glfw.hints.context.client = GLFW_OPENGL_API; _glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API; - _glfw.hints.context.major = 1; - _glfw.hints.context.minor = 0; + _glfw.hints.context.major = 1; + _glfw.hints.context.minor = 0; // The default is a focused, visible, resizable window with decorations memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window)); - _glfw.hints.window.resizable = GLFW_TRUE; - _glfw.hints.window.visible = GLFW_TRUE; - _glfw.hints.window.decorated = GLFW_TRUE; - _glfw.hints.window.focused = GLFW_TRUE; - _glfw.hints.window.autoIconify = GLFW_TRUE; + _glfw.hints.window.resizable = GLFW_TRUE; + _glfw.hints.window.visible = GLFW_TRUE; + _glfw.hints.window.decorated = GLFW_TRUE; + _glfw.hints.window.focused = GLFW_TRUE; + _glfw.hints.window.autoIconify = GLFW_TRUE; _glfw.hints.window.centerCursor = GLFW_TRUE; - _glfw.hints.window.focusOnShow = GLFW_TRUE; + _glfw.hints.window.focusOnShow = GLFW_TRUE; + _glfw.hints.window.xpos = GLFW_ANY_POSITION; + _glfw.hints.window.ypos = GLFW_ANY_POSITION; // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil, // double buffered memset(&_glfw.hints.framebuffer, 0, sizeof(_glfw.hints.framebuffer)); - _glfw.hints.framebuffer.redBits = 8; - _glfw.hints.framebuffer.greenBits = 8; - _glfw.hints.framebuffer.blueBits = 8; - _glfw.hints.framebuffer.alphaBits = 8; - _glfw.hints.framebuffer.depthBits = 24; - _glfw.hints.framebuffer.stencilBits = 8; + _glfw.hints.framebuffer.redBits = 8; + _glfw.hints.framebuffer.greenBits = 8; + _glfw.hints.framebuffer.blueBits = 8; + _glfw.hints.framebuffer.alphaBits = 8; + _glfw.hints.framebuffer.depthBits = 24; + _glfw.hints.framebuffer.stencilBits = 8; _glfw.hints.framebuffer.doublebuffer = GLFW_TRUE; // The default is to select the highest available refresh rate @@ -297,135 +300,141 @@ GLFWAPI void glfwWindowHint(int hint, int value) switch (hint) { - case GLFW_RED_BITS: - _glfw.hints.framebuffer.redBits = value; - return; - case GLFW_GREEN_BITS: - _glfw.hints.framebuffer.greenBits = value; - return; - case GLFW_BLUE_BITS: - _glfw.hints.framebuffer.blueBits = value; - return; - case GLFW_ALPHA_BITS: - _glfw.hints.framebuffer.alphaBits = value; - return; - case GLFW_DEPTH_BITS: - _glfw.hints.framebuffer.depthBits = value; - return; - case GLFW_STENCIL_BITS: - _glfw.hints.framebuffer.stencilBits = value; - return; - case GLFW_ACCUM_RED_BITS: - _glfw.hints.framebuffer.accumRedBits = value; - return; - case GLFW_ACCUM_GREEN_BITS: - _glfw.hints.framebuffer.accumGreenBits = value; - return; - case GLFW_ACCUM_BLUE_BITS: - _glfw.hints.framebuffer.accumBlueBits = value; - return; - case GLFW_ACCUM_ALPHA_BITS: - _glfw.hints.framebuffer.accumAlphaBits = value; - return; - case GLFW_AUX_BUFFERS: - _glfw.hints.framebuffer.auxBuffers = value; - return; - case GLFW_STEREO: - _glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_DOUBLEBUFFER: - _glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_TRANSPARENT_FRAMEBUFFER: - _glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_SAMPLES: - _glfw.hints.framebuffer.samples = value; - return; - case GLFW_SRGB_CAPABLE: - _glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_RESIZABLE: - _glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_DECORATED: - _glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_FOCUSED: - _glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_AUTO_ICONIFY: - _glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_FLOATING: - _glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_MAXIMIZED: - _glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_VISIBLE: - _glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_COCOA_RETINA_FRAMEBUFFER: - _glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_WIN32_KEYBOARD_MENU: - _glfw.hints.window.win32.keymenu = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_COCOA_GRAPHICS_SWITCHING: - _glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_SCALE_TO_MONITOR: - _glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_CENTER_CURSOR: - _glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_FOCUS_ON_SHOW: - _glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_MOUSE_PASSTHROUGH: - _glfw.hints.window.mousePassthrough = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_CLIENT_API: - _glfw.hints.context.client = value; - return; - case GLFW_CONTEXT_CREATION_API: - _glfw.hints.context.source = value; - return; - case GLFW_CONTEXT_VERSION_MAJOR: - _glfw.hints.context.major = value; - return; - case GLFW_CONTEXT_VERSION_MINOR: - _glfw.hints.context.minor = value; - return; - case GLFW_CONTEXT_ROBUSTNESS: - _glfw.hints.context.robustness = value; - return; - case GLFW_OPENGL_FORWARD_COMPAT: - _glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_CONTEXT_DEBUG: - _glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_CONTEXT_NO_ERROR: - _glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE; - return; - case GLFW_OPENGL_PROFILE: - _glfw.hints.context.profile = value; - return; - case GLFW_CONTEXT_RELEASE_BEHAVIOR: - _glfw.hints.context.release = value; - return; - case GLFW_REFRESH_RATE: - _glfw.hints.refreshRate = value; - return; + case GLFW_RED_BITS: + _glfw.hints.framebuffer.redBits = value; + return; + case GLFW_GREEN_BITS: + _glfw.hints.framebuffer.greenBits = value; + return; + case GLFW_BLUE_BITS: + _glfw.hints.framebuffer.blueBits = value; + return; + case GLFW_ALPHA_BITS: + _glfw.hints.framebuffer.alphaBits = value; + return; + case GLFW_DEPTH_BITS: + _glfw.hints.framebuffer.depthBits = value; + return; + case GLFW_STENCIL_BITS: + _glfw.hints.framebuffer.stencilBits = value; + return; + case GLFW_ACCUM_RED_BITS: + _glfw.hints.framebuffer.accumRedBits = value; + return; + case GLFW_ACCUM_GREEN_BITS: + _glfw.hints.framebuffer.accumGreenBits = value; + return; + case GLFW_ACCUM_BLUE_BITS: + _glfw.hints.framebuffer.accumBlueBits = value; + return; + case GLFW_ACCUM_ALPHA_BITS: + _glfw.hints.framebuffer.accumAlphaBits = value; + return; + case GLFW_AUX_BUFFERS: + _glfw.hints.framebuffer.auxBuffers = value; + return; + case GLFW_STEREO: + _glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_DOUBLEBUFFER: + _glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_TRANSPARENT_FRAMEBUFFER: + _glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_SAMPLES: + _glfw.hints.framebuffer.samples = value; + return; + case GLFW_SRGB_CAPABLE: + _glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_RESIZABLE: + _glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_DECORATED: + _glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_FOCUSED: + _glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_AUTO_ICONIFY: + _glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_FLOATING: + _glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_MAXIMIZED: + _glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_VISIBLE: + _glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_POSITION_X: + _glfw.hints.window.xpos = value; + return; + case GLFW_POSITION_Y: + _glfw.hints.window.ypos = value; + return; + case GLFW_COCOA_RETINA_FRAMEBUFFER: + _glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_WIN32_KEYBOARD_MENU: + _glfw.hints.window.win32.keymenu = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_COCOA_GRAPHICS_SWITCHING: + _glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_SCALE_TO_MONITOR: + _glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_CENTER_CURSOR: + _glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_FOCUS_ON_SHOW: + _glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_MOUSE_PASSTHROUGH: + _glfw.hints.window.mousePassthrough = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_CLIENT_API: + _glfw.hints.context.client = value; + return; + case GLFW_CONTEXT_CREATION_API: + _glfw.hints.context.source = value; + return; + case GLFW_CONTEXT_VERSION_MAJOR: + _glfw.hints.context.major = value; + return; + case GLFW_CONTEXT_VERSION_MINOR: + _glfw.hints.context.minor = value; + return; + case GLFW_CONTEXT_ROBUSTNESS: + _glfw.hints.context.robustness = value; + return; + case GLFW_OPENGL_FORWARD_COMPAT: + _glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_CONTEXT_DEBUG: + _glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_CONTEXT_NO_ERROR: + _glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE; + return; + case GLFW_OPENGL_PROFILE: + _glfw.hints.context.profile = value; + return; + case GLFW_CONTEXT_RELEASE_BEHAVIOR: + _glfw.hints.context.release = value; + return; + case GLFW_REFRESH_RATE: + _glfw.hints.refreshRate = value; + return; } _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint); } -GLFWAPI void glfwWindowHintString(int hint, const char* value) +GLFWAPI void glfwWindowHintString(int hint, const char *value) { assert(value != NULL); @@ -433,26 +442,30 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value) switch (hint) { - case GLFW_COCOA_FRAME_NAME: - strncpy(_glfw.hints.window.ns.frameName, value, - sizeof(_glfw.hints.window.ns.frameName) - 1); - return; - case GLFW_X11_CLASS_NAME: - strncpy(_glfw.hints.window.x11.className, value, - sizeof(_glfw.hints.window.x11.className) - 1); - return; - case GLFW_X11_INSTANCE_NAME: - strncpy(_glfw.hints.window.x11.instanceName, value, - sizeof(_glfw.hints.window.x11.instanceName) - 1); - return; + case GLFW_COCOA_FRAME_NAME: + strncpy(_glfw.hints.window.ns.frameName, value, + sizeof(_glfw.hints.window.ns.frameName) - 1); + return; + case GLFW_X11_CLASS_NAME: + strncpy(_glfw.hints.window.x11.className, value, + sizeof(_glfw.hints.window.x11.className) - 1); + return; + case GLFW_X11_INSTANCE_NAME: + strncpy(_glfw.hints.window.x11.instanceName, value, + sizeof(_glfw.hints.window.x11.instanceName) - 1); + return; + case GLFW_WAYLAND_APP_ID: + strncpy(_glfw.hints.window.wl.appId, value, + sizeof(_glfw.hints.window.wl.appId) - 1); + return; } _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint string 0x%08X", hint); } -GLFWAPI void glfwDestroyWindow(GLFWwindow* handle) +GLFWAPI void glfwDestroyWindow(GLFWwindow *handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; _GLFW_REQUIRE_INIT(); @@ -468,11 +481,11 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle) if (window == _glfwPlatformGetTls(&_glfw.contextSlot)) glfwMakeContextCurrent(NULL); - _glfwPlatformDestroyWindow(window); + _glfw.platform.destroyWindow(window); // Unlink window from global linked list { - _GLFWwindow** prev = &_glfw.windowListHead; + _GLFWwindow **prev = &_glfw.windowListHead; while (*prev != window) prev = &((*prev)->next); @@ -483,49 +496,70 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle) _glfw_free(window); } -GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle) +GLFWAPI int glfwWindowShouldClose(GLFWwindow *handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(0); return window->shouldClose; } -GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value) +GLFWAPI void glfwSetWindowShouldClose(GLFWwindow *handle, int value) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT(); window->shouldClose = value; } -GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title) +GLFWAPI void glfwSetWindowTitle(GLFWwindow *handle, const char *title) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); assert(title != NULL); _GLFW_REQUIRE_INIT(); - _glfwPlatformSetWindowTitle(window, title); + _glfw.platform.setWindowTitle(window, title); } -GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle, - int count, const GLFWimage* images) +GLFWAPI void glfwSetWindowIcon(GLFWwindow *handle, + int count, const GLFWimage *images) { - _GLFWwindow* window = (_GLFWwindow*) handle; + int i; + _GLFWwindow *window = (_GLFWwindow *)handle; + assert(window != NULL); assert(count >= 0); assert(count == 0 || images != NULL); _GLFW_REQUIRE_INIT(); - _glfwPlatformSetWindowIcon(window, count, images); + + if (count < 0) + { + _glfwInputError(GLFW_INVALID_VALUE, "Invalid image count for window icon"); + return; + } + + for (i = 0; i < count; i++) + { + assert(images[i].pixels != NULL); + + if (images[i].width <= 0 || images[i].height <= 0) + { + _glfwInputError(GLFW_INVALID_VALUE, + "Invalid image dimensions for window icon"); + return; + } + } + + _glfw.platform.setWindowIcon(window, count, images); } -GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos) +GLFWAPI void glfwGetWindowPos(GLFWwindow *handle, int *xpos, int *ypos) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); if (xpos) @@ -534,12 +568,12 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos) *ypos = 0; _GLFW_REQUIRE_INIT(); - _glfwPlatformGetWindowPos(window, xpos, ypos); + _glfw.platform.getWindowPos(window, xpos, ypos); } -GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos) +GLFWAPI void glfwSetWindowPos(GLFWwindow *handle, int xpos, int ypos) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT(); @@ -547,12 +581,12 @@ GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos) if (window->monitor) return; - _glfwPlatformSetWindowPos(window, xpos, ypos); + _glfw.platform.setWindowPos(window, xpos, ypos); } -GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height) +GLFWAPI void glfwGetWindowSize(GLFWwindow *handle, int *width, int *height) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); if (width) @@ -561,29 +595,29 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height) *height = 0; _GLFW_REQUIRE_INIT(); - _glfwPlatformGetWindowSize(window, width, height); + _glfw.platform.getWindowSize(window, width, height); } -GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height) +GLFWAPI void glfwSetWindowSize(GLFWwindow *handle, int width, int height) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); assert(width >= 0); assert(height >= 0); _GLFW_REQUIRE_INIT(); - window->videoMode.width = width; + window->videoMode.width = width; window->videoMode.height = height; - _glfwPlatformSetWindowSize(window, width, height); + _glfw.platform.setWindowSize(window, width, height); } -GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle, +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow *handle, int minwidth, int minheight, int maxwidth, int maxheight) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT(); @@ -611,22 +645,22 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle, } } - window->minwidth = minwidth; + window->minwidth = minwidth; window->minheight = minheight; - window->maxwidth = maxwidth; + window->maxwidth = maxwidth; window->maxheight = maxheight; if (window->monitor || !window->resizable) return; - _glfwPlatformSetWindowSizeLimits(window, - minwidth, minheight, - maxwidth, maxheight); + _glfw.platform.setWindowSizeLimits(window, + minwidth, minheight, + maxwidth, maxheight); } -GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom) +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow *handle, int numer, int denom) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); assert(numer != 0); assert(denom != 0); @@ -650,12 +684,12 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom) if (window->monitor || !window->resizable) return; - _glfwPlatformSetWindowAspectRatio(window, numer, denom); + _glfw.platform.setWindowAspectRatio(window, numer, denom); } -GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height) +GLFWAPI void glfwGetFramebufferSize(GLFWwindow *handle, int *width, int *height) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); if (width) @@ -664,14 +698,14 @@ GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height) *height = 0; _GLFW_REQUIRE_INIT(); - _glfwPlatformGetFramebufferSize(window, width, height); + _glfw.platform.getFramebufferSize(window, width, height); } -GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle, - int* left, int* top, - int* right, int* bottom) +GLFWAPI void glfwGetWindowFrameSize(GLFWwindow *handle, + int *left, int *top, + int *right, int *bottom) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); if (left) @@ -684,13 +718,13 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle, *bottom = 0; _GLFW_REQUIRE_INIT(); - _glfwPlatformGetWindowFrameSize(window, left, top, right, bottom); + _glfw.platform.getWindowFrameSize(window, left, top, right, bottom); } -GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle, - float* xscale, float* yscale) +GLFWAPI void glfwGetWindowContentScale(GLFWwindow *handle, + float *xscale, float *yscale) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); if (xscale) @@ -699,21 +733,21 @@ GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle, *yscale = 0.f; _GLFW_REQUIRE_INIT(); - _glfwPlatformGetWindowContentScale(window, xscale, yscale); + _glfw.platform.getWindowContentScale(window, xscale, yscale); } -GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle) +GLFWAPI float glfwGetWindowOpacity(GLFWwindow *handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(1.f); - return _glfwPlatformGetWindowOpacity(window); + return _glfw.platform.getWindowOpacity(window); } -GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity) +GLFWAPI void glfwSetWindowOpacity(GLFWwindow *handle, float opacity) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); assert(opacity == opacity); assert(opacity >= 0.f); @@ -727,30 +761,30 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity) return; } - _glfwPlatformSetWindowOpacity(window, opacity); + _glfw.platform.setWindowOpacity(window, opacity); } -GLFWAPI void glfwIconifyWindow(GLFWwindow* handle) +GLFWAPI void glfwIconifyWindow(GLFWwindow *handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT(); - _glfwPlatformIconifyWindow(window); + _glfw.platform.iconifyWindow(window); } -GLFWAPI void glfwRestoreWindow(GLFWwindow* handle) +GLFWAPI void glfwRestoreWindow(GLFWwindow *handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT(); - _glfwPlatformRestoreWindow(window); + _glfw.platform.restoreWindow(window); } -GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle) +GLFWAPI void glfwMaximizeWindow(GLFWwindow *handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT(); @@ -758,12 +792,12 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle) if (window->monitor) return; - _glfwPlatformMaximizeWindow(window); + _glfw.platform.maximizeWindow(window); } -GLFWAPI void glfwShowWindow(GLFWwindow* handle) +GLFWAPI void glfwShowWindow(GLFWwindow *handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT(); @@ -771,25 +805,25 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle) if (window->monitor) return; - _glfwPlatformShowWindow(window); + _glfw.platform.showWindow(window); if (window->focusOnShow) - _glfwPlatformFocusWindow(window); + _glfw.platform.focusWindow(window); } -GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle) +GLFWAPI void glfwRequestWindowAttention(GLFWwindow *handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT(); - _glfwPlatformRequestWindowAttention(window); + _glfw.platform.requestWindowAttention(window); } -GLFWAPI void glfwHideWindow(GLFWwindow* handle) +GLFWAPI void glfwHideWindow(GLFWwindow *handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT(); @@ -797,139 +831,145 @@ GLFWAPI void glfwHideWindow(GLFWwindow* handle) if (window->monitor) return; - _glfwPlatformHideWindow(window); + _glfw.platform.hideWindow(window); } -GLFWAPI void glfwFocusWindow(GLFWwindow* handle) +GLFWAPI void glfwFocusWindow(GLFWwindow *handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT(); - _glfwPlatformFocusWindow(window); + _glfw.platform.focusWindow(window); } -GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) +GLFWAPI int glfwGetWindowAttrib(GLFWwindow *handle, int attrib) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(0); switch (attrib) { - case GLFW_FOCUSED: - return _glfwPlatformWindowFocused(window); - case GLFW_ICONIFIED: - return _glfwPlatformWindowIconified(window); - case GLFW_VISIBLE: - return _glfwPlatformWindowVisible(window); - case GLFW_MAXIMIZED: - return _glfwPlatformWindowMaximized(window); - case GLFW_HOVERED: - return _glfwPlatformWindowHovered(window); - case GLFW_FOCUS_ON_SHOW: - return window->focusOnShow; - case GLFW_MOUSE_PASSTHROUGH: - return window->mousePassthrough; - case GLFW_TRANSPARENT_FRAMEBUFFER: - return _glfwPlatformFramebufferTransparent(window); - case GLFW_RESIZABLE: - return window->resizable; - case GLFW_DECORATED: - return window->decorated; - case GLFW_FLOATING: - return window->floating; - case GLFW_AUTO_ICONIFY: - return window->autoIconify; - case GLFW_DOUBLEBUFFER: - return window->doublebuffer; - case GLFW_CLIENT_API: - return window->context.client; - case GLFW_CONTEXT_CREATION_API: - return window->context.source; - case GLFW_CONTEXT_VERSION_MAJOR: - return window->context.major; - case GLFW_CONTEXT_VERSION_MINOR: - return window->context.minor; - case GLFW_CONTEXT_REVISION: - return window->context.revision; - case GLFW_CONTEXT_ROBUSTNESS: - return window->context.robustness; - case GLFW_OPENGL_FORWARD_COMPAT: - return window->context.forward; - case GLFW_CONTEXT_DEBUG: - return window->context.debug; - case GLFW_OPENGL_PROFILE: - return window->context.profile; - case GLFW_CONTEXT_RELEASE_BEHAVIOR: - return window->context.release; - case GLFW_CONTEXT_NO_ERROR: - return window->context.noerror; + case GLFW_FOCUSED: + return _glfw.platform.windowFocused(window); + case GLFW_ICONIFIED: + return _glfw.platform.windowIconified(window); + case GLFW_VISIBLE: + return _glfw.platform.windowVisible(window); + case GLFW_MAXIMIZED: + return _glfw.platform.windowMaximized(window); + case GLFW_HOVERED: + return _glfw.platform.windowHovered(window); + case GLFW_FOCUS_ON_SHOW: + return window->focusOnShow; + case GLFW_MOUSE_PASSTHROUGH: + return window->mousePassthrough; + case GLFW_TRANSPARENT_FRAMEBUFFER: + return _glfw.platform.framebufferTransparent(window); + case GLFW_RESIZABLE: + return window->resizable; + case GLFW_DECORATED: + return window->decorated; + case GLFW_FLOATING: + return window->floating; + case GLFW_AUTO_ICONIFY: + return window->autoIconify; + case GLFW_DOUBLEBUFFER: + return window->doublebuffer; + case GLFW_CLIENT_API: + return window->context.client; + case GLFW_CONTEXT_CREATION_API: + return window->context.source; + case GLFW_CONTEXT_VERSION_MAJOR: + return window->context.major; + case GLFW_CONTEXT_VERSION_MINOR: + return window->context.minor; + case GLFW_CONTEXT_REVISION: + return window->context.revision; + case GLFW_CONTEXT_ROBUSTNESS: + return window->context.robustness; + case GLFW_OPENGL_FORWARD_COMPAT: + return window->context.forward; + case GLFW_CONTEXT_DEBUG: + return window->context.debug; + case GLFW_OPENGL_PROFILE: + return window->context.profile; + case GLFW_CONTEXT_RELEASE_BEHAVIOR: + return window->context.release; + case GLFW_CONTEXT_NO_ERROR: + return window->context.noerror; } _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib); return 0; } -GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value) +GLFWAPI void glfwSetWindowAttrib(GLFWwindow *handle, int attrib, int value) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT(); value = value ? GLFW_TRUE : GLFW_FALSE; - if (attrib == GLFW_AUTO_ICONIFY) - window->autoIconify = value; - else if (attrib == GLFW_RESIZABLE) + switch (attrib) { + case GLFW_AUTO_ICONIFY: + window->autoIconify = value; + return; + + case GLFW_RESIZABLE: window->resizable = value; if (!window->monitor) - _glfwPlatformSetWindowResizable(window, value); - } - else if (attrib == GLFW_DECORATED) - { + _glfw.platform.setWindowResizable(window, value); + return; + + case GLFW_DECORATED: window->decorated = value; if (!window->monitor) - _glfwPlatformSetWindowDecorated(window, value); - } - else if (attrib == GLFW_FLOATING) - { + _glfw.platform.setWindowDecorated(window, value); + return; + + case GLFW_FLOATING: window->floating = value; if (!window->monitor) - _glfwPlatformSetWindowFloating(window, value); - } - else if (attrib == GLFW_FOCUS_ON_SHOW) + _glfw.platform.setWindowFloating(window, value); + return; + + case GLFW_FOCUS_ON_SHOW: window->focusOnShow = value; - else if (attrib == GLFW_MOUSE_PASSTHROUGH) - { + return; + + case GLFW_MOUSE_PASSTHROUGH: window->mousePassthrough = value; - _glfwPlatformSetWindowMousePassthrough(window, value); + _glfw.platform.setWindowMousePassthrough(window, value); + return; } - else - _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib); + + _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib); } -GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle) +GLFWAPI GLFWmonitor *glfwGetWindowMonitor(GLFWwindow *handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - return (GLFWmonitor*) window->monitor; + return (GLFWmonitor *)window->monitor; } -GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh, - GLFWmonitor* mh, +GLFWAPI void glfwSetWindowMonitor(GLFWwindow *wh, + GLFWmonitor *mh, int xpos, int ypos, int width, int height, int refreshRate) { - _GLFWwindow* window = (_GLFWwindow*) wh; - _GLFWmonitor* monitor = (_GLFWmonitor*) mh; + _GLFWwindow *window = (_GLFWwindow *)wh; + _GLFWmonitor *monitor = (_GLFWmonitor *)mh; assert(window != NULL); assert(width >= 0); assert(height >= 0); @@ -952,129 +992,129 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh, return; } - window->videoMode.width = width; - window->videoMode.height = height; + window->videoMode.width = width; + window->videoMode.height = height; window->videoMode.refreshRate = refreshRate; - _glfwPlatformSetWindowMonitor(window, monitor, - xpos, ypos, width, height, - refreshRate); + _glfw.platform.setWindowMonitor(window, monitor, + xpos, ypos, width, height, + refreshRate); } -GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer) +GLFWAPI void glfwSetWindowUserPointer(GLFWwindow *handle, void *pointer) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT(); window->userPointer = pointer; } -GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle) +GLFWAPI void *glfwGetWindowUserPointer(GLFWwindow *handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); return window->userPointer; } -GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle, +GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow *handle, GLFWwindowposfun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.pos, cbfun); + _GLFW_SWAP(GLFWwindowposfun, window->callbacks.pos, cbfun); return cbfun; } -GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle, +GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow *handle, GLFWwindowsizefun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.size, cbfun); + _GLFW_SWAP(GLFWwindowsizefun, window->callbacks.size, cbfun); return cbfun; } -GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle, +GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow *handle, GLFWwindowclosefun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.close, cbfun); + _GLFW_SWAP(GLFWwindowclosefun, window->callbacks.close, cbfun); return cbfun; } -GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle, +GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow *handle, GLFWwindowrefreshfun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.refresh, cbfun); + _GLFW_SWAP(GLFWwindowrefreshfun, window->callbacks.refresh, cbfun); return cbfun; } -GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle, +GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow *handle, GLFWwindowfocusfun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.focus, cbfun); + _GLFW_SWAP(GLFWwindowfocusfun, window->callbacks.focus, cbfun); return cbfun; } -GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle, +GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow *handle, GLFWwindowiconifyfun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.iconify, cbfun); + _GLFW_SWAP(GLFWwindowiconifyfun, window->callbacks.iconify, cbfun); return cbfun; } -GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle, +GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow *handle, GLFWwindowmaximizefun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.maximize, cbfun); + _GLFW_SWAP(GLFWwindowmaximizefun, window->callbacks.maximize, cbfun); return cbfun; } -GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle, +GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow *handle, GLFWframebuffersizefun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.fbsize, cbfun); + _GLFW_SWAP(GLFWframebuffersizefun, window->callbacks.fbsize, cbfun); return cbfun; } -GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle, +GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow *handle, GLFWwindowcontentscalefun cbfun) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _GLFW_SWAP_POINTERS(window->callbacks.scale, cbfun); + _GLFW_SWAP(GLFWwindowcontentscalefun, window->callbacks.scale, cbfun); return cbfun; } @@ -1082,14 +1122,14 @@ GLFWAPI void glfwPollEvents(void) { _GLFW_REQUIRE_INIT(); _glfwPollAllJoysticks(); - _glfwPlatformPollEvents(); + _glfw.platform.pollEvents(); } GLFWAPI void glfwWaitEvents(void) { _GLFW_REQUIRE_INIT(); _glfwPollAllJoysticks(); - _glfwPlatformWaitEvents(); + _glfw.platform.waitEvents(); } GLFWAPI void glfwWaitEventsTimeout(double timeout) @@ -1105,12 +1145,11 @@ GLFWAPI void glfwWaitEventsTimeout(double timeout) return; } - _glfwPlatformWaitEventsTimeout(timeout); + _glfw.platform.waitEventsTimeout(timeout); } GLFWAPI void glfwPostEmptyEvent(void) { _GLFW_REQUIRE_INIT(); - _glfwPlatformPostEmptyEvent(); + _glfw.platform.postEmptyEvent(); } - diff --git a/src/wl_init.c b/src/wl_init.c index 2c73a7a9..4e6b4294 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -28,7 +28,8 @@ #include "internal.h" -#include +#if defined(_GLFW_WAYLAND) + #include #include #include @@ -48,753 +49,52 @@ #include "wayland-pointer-constraints-unstable-v1-client-protocol.h" #include "wayland-idle-inhibit-unstable-v1-client-protocol.h" +// NOTE: Versions of wayland-scanner prior to 1.17.91 named every global array of +// wl_interface pointers 'types', making it impossible to combine several unmodified +// private-code files into a single compilation unit +// HACK: We override this name with a macro for each file, allowing them to coexist + +#define types _glfw_wayland_types #include "wayland-client-protocol-code.h" +#undef types + +#define types _glfw_xdg_shell_types #include "wayland-xdg-shell-client-protocol-code.h" +#undef types + +#define types _glfw_xdg_decoration_types #include "wayland-xdg-decoration-client-protocol-code.h" +#undef types + +#define types _glfw_viewporter_types #include "wayland-viewporter-client-protocol-code.h" +#undef types + +#define types _glfw_relative_pointer_types #include "wayland-relative-pointer-unstable-v1-client-protocol-code.h" +#undef types + +#define types _glfw_pointer_constraints_types #include "wayland-pointer-constraints-unstable-v1-client-protocol-code.h" +#undef types + +#define types _glfw_idle_inhibit_types #include "wayland-idle-inhibit-unstable-v1-client-protocol-code.h" +#undef types - -static inline int min(int n1, int n2) -{ - return n1 < n2 ? n1 : n2; -} - -static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface, - int* which) -{ - int focus; - _GLFWwindow* window = _glfw.windowListHead; - if (!which) - which = &focus; - while (window) - { - if (surface == window->wl.decorations.top.surface) - { - *which = topDecoration; - break; - } - if (surface == window->wl.decorations.left.surface) - { - *which = leftDecoration; - break; - } - if (surface == window->wl.decorations.right.surface) - { - *which = rightDecoration; - break; - } - if (surface == window->wl.decorations.bottom.surface) - { - *which = bottomDecoration; - break; - } - window = window->next; - } - return window; -} - -static void pointerHandleEnter(void* data, - struct wl_pointer* pointer, - uint32_t serial, - struct wl_surface* surface, - wl_fixed_t sx, - wl_fixed_t sy) -{ - // Happens in the case we just destroyed the surface. - if (!surface) - return; - - int focus = 0; - _GLFWwindow* window = wl_surface_get_user_data(surface); - if (!window) - { - window = findWindowFromDecorationSurface(surface, &focus); - if (!window) - return; - } - - window->wl.decorations.focus = focus; - _glfw.wl.serial = serial; - _glfw.wl.pointerEnterSerial = serial; - _glfw.wl.pointerFocus = window; - - window->wl.hovered = GLFW_TRUE; - - _glfwPlatformSetCursor(window, window->wl.currentCursor); - _glfwInputCursorEnter(window, GLFW_TRUE); -} - -static void pointerHandleLeave(void* data, - struct wl_pointer* pointer, - uint32_t serial, - struct wl_surface* surface) -{ - _GLFWwindow* window = _glfw.wl.pointerFocus; - - if (!window) - return; - - window->wl.hovered = GLFW_FALSE; - - _glfw.wl.serial = serial; - _glfw.wl.pointerFocus = NULL; - _glfwInputCursorEnter(window, GLFW_FALSE); - _glfw.wl.cursorPreviousName = NULL; -} - -static void setCursor(_GLFWwindow* window, const char* name) -{ - struct wl_buffer* buffer; - struct wl_cursor* cursor; - struct wl_cursor_image* image; - struct wl_surface* surface = _glfw.wl.cursorSurface; - struct wl_cursor_theme* theme = _glfw.wl.cursorTheme; - int scale = 1; - - if (window->wl.scale > 1 && _glfw.wl.cursorThemeHiDPI) - { - // We only support up to scale=2 for now, since libwayland-cursor - // requires us to load a different theme for each size. - scale = 2; - theme = _glfw.wl.cursorThemeHiDPI; - } - - cursor = wl_cursor_theme_get_cursor(theme, name); - if (!cursor) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Standard cursor not found"); - return; - } - // TODO: handle animated cursors too. - image = cursor->images[0]; - - if (!image) - return; - - buffer = wl_cursor_image_get_buffer(image); - if (!buffer) - return; - wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial, - surface, - image->hotspot_x / scale, - image->hotspot_y / scale); - wl_surface_set_buffer_scale(surface, scale); - wl_surface_attach(surface, buffer, 0, 0); - wl_surface_damage(surface, 0, 0, - image->width, image->height); - wl_surface_commit(surface); - _glfw.wl.cursorPreviousName = name; -} - -static void pointerHandleMotion(void* data, - struct wl_pointer* pointer, - uint32_t time, - wl_fixed_t sx, - wl_fixed_t sy) -{ - _GLFWwindow* window = _glfw.wl.pointerFocus; - const char* cursorName = NULL; - double x, y; - - if (!window) - return; - - if (window->cursorMode == GLFW_CURSOR_DISABLED) - return; - x = wl_fixed_to_double(sx); - y = wl_fixed_to_double(sy); - - switch (window->wl.decorations.focus) - { - case mainWindow: - window->wl.cursorPosX = x; - window->wl.cursorPosY = y; - _glfwInputCursorPos(window, x, y); - _glfw.wl.cursorPreviousName = NULL; - return; - case topDecoration: - if (y < _GLFW_DECORATION_WIDTH) - cursorName = "n-resize"; - else - cursorName = "left_ptr"; - break; - case leftDecoration: - if (y < _GLFW_DECORATION_WIDTH) - cursorName = "nw-resize"; - else - cursorName = "w-resize"; - break; - case rightDecoration: - if (y < _GLFW_DECORATION_WIDTH) - cursorName = "ne-resize"; - else - cursorName = "e-resize"; - break; - case bottomDecoration: - if (x < _GLFW_DECORATION_WIDTH) - cursorName = "sw-resize"; - else if (x > window->wl.width + _GLFW_DECORATION_WIDTH) - cursorName = "se-resize"; - else - cursorName = "s-resize"; - break; - default: - assert(0); - } - if (_glfw.wl.cursorPreviousName != cursorName) - setCursor(window, cursorName); -} - -static void pointerHandleButton(void* data, - struct wl_pointer* pointer, - uint32_t serial, - uint32_t time, - uint32_t button, - uint32_t state) -{ - _GLFWwindow* window = _glfw.wl.pointerFocus; - int glfwButton; - uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE; - - if (!window) - return; - if (button == BTN_LEFT) - { - switch (window->wl.decorations.focus) - { - case mainWindow: - break; - case topDecoration: - if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) - edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP; - else - { - xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial); - } - break; - case leftDecoration: - if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) - edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; - else - edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT; - break; - case rightDecoration: - if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) - edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; - else - edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; - break; - case bottomDecoration: - if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH) - edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; - else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH) - edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; - else - edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; - break; - default: - assert(0); - } - if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE) - { - xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat, - serial, edges); - } - } - else if (button == BTN_RIGHT) - { - if (window->wl.decorations.focus != mainWindow && window->wl.xdg.toplevel) - { - xdg_toplevel_show_window_menu(window->wl.xdg.toplevel, - _glfw.wl.seat, serial, - window->wl.cursorPosX, - window->wl.cursorPosY); - return; - } - } - - // Don’t pass the button to the user if it was related to a decoration. - if (window->wl.decorations.focus != mainWindow) - return; - - _glfw.wl.serial = serial; - - /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev - * codes. */ - glfwButton = button - BTN_LEFT; - - _glfwInputMouseClick(window, - glfwButton, - state == WL_POINTER_BUTTON_STATE_PRESSED - ? GLFW_PRESS - : GLFW_RELEASE, - _glfw.wl.xkb.modifiers); -} - -static void pointerHandleAxis(void* data, - struct wl_pointer* pointer, - uint32_t time, - uint32_t axis, - wl_fixed_t value) -{ - _GLFWwindow* window = _glfw.wl.pointerFocus; - double x = 0.0, y = 0.0; - // Wayland scroll events are in pointer motion coordinate space (think two - // finger scroll). The factor 10 is commonly used to convert to "scroll - // step means 1.0. - const double scrollFactor = 1.0 / 10.0; - - if (!window) - return; - - assert(axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL || - axis == WL_POINTER_AXIS_VERTICAL_SCROLL); - - if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) - x = -wl_fixed_to_double(value) * scrollFactor; - else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) - y = -wl_fixed_to_double(value) * scrollFactor; - - _glfwInputScroll(window, x, y); -} - -static const struct wl_pointer_listener pointerListener = { - pointerHandleEnter, - pointerHandleLeave, - pointerHandleMotion, - pointerHandleButton, - pointerHandleAxis, -}; - -static void keyboardHandleKeymap(void* data, - struct wl_keyboard* keyboard, - uint32_t format, - int fd, - uint32_t size) -{ - struct xkb_keymap* keymap; - struct xkb_state* state; - -#ifdef HAVE_XKBCOMMON_COMPOSE_H - struct xkb_compose_table* composeTable; - struct xkb_compose_state* composeState; -#endif - - char* mapStr; - const char* locale; - - if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) - { - close(fd); - return; - } - - mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); - if (mapStr == MAP_FAILED) { - close(fd); - return; - } - - keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context, - mapStr, - XKB_KEYMAP_FORMAT_TEXT_V1, - 0); - munmap(mapStr, size); - close(fd); - - if (!keymap) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Failed to compile keymap"); - return; - } - - state = xkb_state_new(keymap); - if (!state) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Failed to create XKB state"); - xkb_keymap_unref(keymap); - return; - } - - // Look up the preferred locale, falling back to "C" as default. - locale = getenv("LC_ALL"); - if (!locale) - locale = getenv("LC_CTYPE"); - if (!locale) - locale = getenv("LANG"); - if (!locale) - locale = "C"; - -#ifdef HAVE_XKBCOMMON_COMPOSE_H - composeTable = - xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale, - XKB_COMPOSE_COMPILE_NO_FLAGS); - if (composeTable) - { - composeState = - xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS); - xkb_compose_table_unref(composeTable); - if (composeState) - _glfw.wl.xkb.composeState = composeState; - else - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Failed to create XKB compose state"); - } - else - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Failed to create XKB compose table"); - } -#endif - - xkb_keymap_unref(_glfw.wl.xkb.keymap); - xkb_state_unref(_glfw.wl.xkb.state); - _glfw.wl.xkb.keymap = keymap; - _glfw.wl.xkb.state = state; - - _glfw.wl.xkb.controlMask = - 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control"); - _glfw.wl.xkb.altMask = - 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1"); - _glfw.wl.xkb.shiftMask = - 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift"); - _glfw.wl.xkb.superMask = - 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4"); - _glfw.wl.xkb.capsLockMask = - 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Lock"); - _glfw.wl.xkb.numLockMask = - 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod2"); -} - -static void keyboardHandleEnter(void* data, - struct wl_keyboard* keyboard, - uint32_t serial, - struct wl_surface* surface, - struct wl_array* keys) -{ - // Happens in the case we just destroyed the surface. - if (!surface) - return; - - _GLFWwindow* window = wl_surface_get_user_data(surface); - if (!window) - { - window = findWindowFromDecorationSurface(surface, NULL); - if (!window) - return; - } - - _glfw.wl.serial = serial; - _glfw.wl.keyboardFocus = window; - _glfwInputWindowFocus(window, GLFW_TRUE); -} - -static void keyboardHandleLeave(void* data, - struct wl_keyboard* keyboard, - uint32_t serial, - struct wl_surface* surface) -{ - _GLFWwindow* window = _glfw.wl.keyboardFocus; - - if (!window) - return; - - _glfw.wl.serial = serial; - _glfw.wl.keyboardFocus = NULL; - _glfwInputWindowFocus(window, GLFW_FALSE); -} - -static int toGLFWKeyCode(uint32_t key) -{ - if (key < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0])) - return _glfw.wl.keycodes[key]; - - return GLFW_KEY_UNKNOWN; -} - -#ifdef HAVE_XKBCOMMON_COMPOSE_H -static xkb_keysym_t composeSymbol(xkb_keysym_t sym) -{ - if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState) - return sym; - if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym) - != XKB_COMPOSE_FEED_ACCEPTED) - return sym; - switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState)) - { - case XKB_COMPOSE_COMPOSED: - return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState); - case XKB_COMPOSE_COMPOSING: - case XKB_COMPOSE_CANCELLED: - return XKB_KEY_NoSymbol; - case XKB_COMPOSE_NOTHING: - default: - return sym; - } -} -#endif - -static GLFWbool inputChar(_GLFWwindow* window, uint32_t key) -{ - uint32_t code, numSyms; - long cp; - const xkb_keysym_t *syms; - xkb_keysym_t sym; - - code = key + 8; - numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms); - - if (numSyms == 1) - { -#ifdef HAVE_XKBCOMMON_COMPOSE_H - sym = composeSymbol(syms[0]); -#else - sym = syms[0]; -#endif - cp = _glfwKeySym2Unicode(sym); - if (cp != -1) - { - const int mods = _glfw.wl.xkb.modifiers; - const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); - _glfwInputChar(window, cp, mods, plain); - } - } - - return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, code); -} - -static void keyboardHandleKey(void* data, - struct wl_keyboard* keyboard, - uint32_t serial, - uint32_t time, - uint32_t key, - uint32_t state) -{ - int keyCode; - int action; - _GLFWwindow* window = _glfw.wl.keyboardFocus; - GLFWbool shouldRepeat; - struct itimerspec timer = {}; - - if (!window) - return; - - keyCode = toGLFWKeyCode(key); - action = state == WL_KEYBOARD_KEY_STATE_PRESSED - ? GLFW_PRESS : GLFW_RELEASE; - - _glfw.wl.serial = serial; - _glfwInputKey(window, keyCode, key, action, - _glfw.wl.xkb.modifiers); - - if (action == GLFW_PRESS) - { - shouldRepeat = inputChar(window, key); - - if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0) - { - _glfw.wl.keyboardLastKey = keyCode; - _glfw.wl.keyboardLastScancode = key; - if (_glfw.wl.keyboardRepeatRate > 1) - timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyboardRepeatRate; - else - timer.it_interval.tv_sec = 1; - timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000; - timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000; - } - } - timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL); -} - -static void keyboardHandleModifiers(void* data, - struct wl_keyboard* keyboard, - uint32_t serial, - uint32_t modsDepressed, - uint32_t modsLatched, - uint32_t modsLocked, - uint32_t group) -{ - xkb_mod_mask_t mask; - unsigned int modifiers = 0; - - _glfw.wl.serial = serial; - - if (!_glfw.wl.xkb.keymap) - return; - - xkb_state_update_mask(_glfw.wl.xkb.state, - modsDepressed, - modsLatched, - modsLocked, - 0, - 0, - group); - - mask = xkb_state_serialize_mods(_glfw.wl.xkb.state, - XKB_STATE_MODS_DEPRESSED | - XKB_STATE_LAYOUT_DEPRESSED | - XKB_STATE_MODS_LATCHED | - XKB_STATE_LAYOUT_LATCHED); - if (mask & _glfw.wl.xkb.controlMask) - modifiers |= GLFW_MOD_CONTROL; - if (mask & _glfw.wl.xkb.altMask) - modifiers |= GLFW_MOD_ALT; - if (mask & _glfw.wl.xkb.shiftMask) - modifiers |= GLFW_MOD_SHIFT; - if (mask & _glfw.wl.xkb.superMask) - modifiers |= GLFW_MOD_SUPER; - if (mask & _glfw.wl.xkb.capsLockMask) - modifiers |= GLFW_MOD_CAPS_LOCK; - if (mask & _glfw.wl.xkb.numLockMask) - modifiers |= GLFW_MOD_NUM_LOCK; - _glfw.wl.xkb.modifiers = modifiers; -} - -#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION -static void keyboardHandleRepeatInfo(void* data, - struct wl_keyboard* keyboard, - int32_t rate, - int32_t delay) -{ - if (keyboard != _glfw.wl.keyboard) - return; - - _glfw.wl.keyboardRepeatRate = rate; - _glfw.wl.keyboardRepeatDelay = delay; -} -#endif - -static const struct wl_keyboard_listener keyboardListener = { - keyboardHandleKeymap, - keyboardHandleEnter, - keyboardHandleLeave, - keyboardHandleKey, - keyboardHandleModifiers, -#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION - keyboardHandleRepeatInfo, -#endif -}; - -static void seatHandleCapabilities(void* data, - struct wl_seat* seat, - enum wl_seat_capability caps) -{ - if ((caps & WL_SEAT_CAPABILITY_POINTER) && !_glfw.wl.pointer) - { - _glfw.wl.pointer = wl_seat_get_pointer(seat); - wl_pointer_add_listener(_glfw.wl.pointer, &pointerListener, NULL); - } - else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer) - { - wl_pointer_destroy(_glfw.wl.pointer); - _glfw.wl.pointer = NULL; - } - - if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !_glfw.wl.keyboard) - { - _glfw.wl.keyboard = wl_seat_get_keyboard(seat); - wl_keyboard_add_listener(_glfw.wl.keyboard, &keyboardListener, NULL); - } - else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard) - { - wl_keyboard_destroy(_glfw.wl.keyboard); - _glfw.wl.keyboard = NULL; - } -} - -static void seatHandleName(void* data, - struct wl_seat* seat, - const char* name) -{ -} - -static const struct wl_seat_listener seatListener = { - seatHandleCapabilities, - seatHandleName, -}; - -static void dataOfferHandleOffer(void* data, - struct wl_data_offer* dataOffer, - const char* mimeType) -{ -} - -static const struct wl_data_offer_listener dataOfferListener = { - dataOfferHandleOffer, -}; - -static void dataDeviceHandleDataOffer(void* data, - struct wl_data_device* dataDevice, - struct wl_data_offer* id) -{ - if (_glfw.wl.dataOffer) - wl_data_offer_destroy(_glfw.wl.dataOffer); - - _glfw.wl.dataOffer = id; - wl_data_offer_add_listener(_glfw.wl.dataOffer, &dataOfferListener, NULL); -} - -static void dataDeviceHandleEnter(void* data, - struct wl_data_device* dataDevice, - uint32_t serial, - struct wl_surface *surface, - wl_fixed_t x, - wl_fixed_t y, - struct wl_data_offer *id) -{ -} - -static void dataDeviceHandleLeave(void* data, - struct wl_data_device* dataDevice) -{ -} - -static void dataDeviceHandleMotion(void* data, - struct wl_data_device* dataDevice, - uint32_t time, - wl_fixed_t x, - wl_fixed_t y) -{ -} - -static void dataDeviceHandleDrop(void* data, - struct wl_data_device* dataDevice) -{ -} - -static void dataDeviceHandleSelection(void* data, - struct wl_data_device* dataDevice, - struct wl_data_offer* id) -{ -} - -static const struct wl_data_device_listener dataDeviceListener = { - dataDeviceHandleDataOffer, - dataDeviceHandleEnter, - dataDeviceHandleLeave, - dataDeviceHandleMotion, - dataDeviceHandleDrop, - dataDeviceHandleSelection, -}; - -static void wmBaseHandlePing(void* data, +static void wmBaseHandlePing(void* userData, struct xdg_wm_base* wmBase, uint32_t serial) { xdg_wm_base_pong(wmBase, serial); } -static const struct xdg_wm_base_listener wmBaseListener = { +static const struct xdg_wm_base_listener wmBaseListener = +{ wmBaseHandlePing }; -static void registryHandleGlobal(void* data, +static void registryHandleGlobal(void* userData, struct wl_registry* registry, uint32_t name, const char* interface, @@ -802,7 +102,7 @@ static void registryHandleGlobal(void* data, { if (strcmp(interface, "wl_compositor") == 0) { - _glfw.wl.compositorVersion = min(3, version); + _glfw.wl.compositorVersion = _glfw_min(3, version); _glfw.wl.compositor = wl_registry_bind(registry, name, &wl_compositor_interface, _glfw.wl.compositorVersion); @@ -825,11 +125,11 @@ static void registryHandleGlobal(void* data, { if (!_glfw.wl.seat) { - _glfw.wl.seatVersion = min(4, version); + _glfw.wl.seatVersion = _glfw_min(4, version); _glfw.wl.seat = wl_registry_bind(registry, name, &wl_seat_interface, _glfw.wl.seatVersion); - wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL); + _glfwAddSeatListenerWayland(_glfw.wl.seat); } } else if (strcmp(interface, "wl_data_device_manager") == 0) @@ -882,16 +182,13 @@ static void registryHandleGlobal(void* data, } } -static void registryHandleGlobalRemove(void *data, - struct wl_registry *registry, +static void registryHandleGlobalRemove(void* userData, + struct wl_registry* registry, uint32_t name) { - int i; - _GLFWmonitor* monitor; - - for (i = 0; i < _glfw.monitorCount; ++i) + for (int i = 0; i < _glfw.monitorCount; ++i) { - monitor = _glfw.monitors[i]; + _GLFWmonitor* monitor = _glfw.monitors[i]; if (monitor->wl.name == name) { _glfwInputMonitor(monitor, GLFW_DISCONNECTED, 0); @@ -901,7 +198,8 @@ static void registryHandleGlobalRemove(void *data, } -static const struct wl_registry_listener registryListener = { +static const struct wl_registry_listener registryListener = +{ registryHandleGlobal, registryHandleGlobalRemove }; @@ -910,8 +208,6 @@ static const struct wl_registry_listener registryListener = { // static void createKeyTables(void) { - int scancode; - memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes)); memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes)); @@ -973,7 +269,7 @@ static void createKeyTables(void) _glfw.wl.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT; _glfw.wl.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER; _glfw.wl.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER; - _glfw.wl.keycodes[KEY_MENU] = GLFW_KEY_MENU; + _glfw.wl.keycodes[KEY_COMPOSE] = GLFW_KEY_MENU; _glfw.wl.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK; _glfw.wl.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK; _glfw.wl.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN; @@ -1016,7 +312,7 @@ static void createKeyTables(void) _glfw.wl.keycodes[KEY_F23] = GLFW_KEY_F23; _glfw.wl.keycodes[KEY_F24] = GLFW_KEY_F24; _glfw.wl.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE; - _glfw.wl.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY; + _glfw.wl.keycodes[KEY_KPASTERISK] = GLFW_KEY_KP_MULTIPLY; _glfw.wl.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT; _glfw.wl.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD; _glfw.wl.keycodes[KEY_KP0] = GLFW_KEY_KP_0; @@ -1029,80 +325,229 @@ static void createKeyTables(void) _glfw.wl.keycodes[KEY_KP7] = GLFW_KEY_KP_7; _glfw.wl.keycodes[KEY_KP8] = GLFW_KEY_KP_8; _glfw.wl.keycodes[KEY_KP9] = GLFW_KEY_KP_9; - _glfw.wl.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL; + _glfw.wl.keycodes[KEY_KPDOT] = GLFW_KEY_KP_DECIMAL; _glfw.wl.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL; _glfw.wl.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER; + _glfw.wl.keycodes[KEY_102ND] = GLFW_KEY_WORLD_2; - for (scancode = 0; scancode < 256; scancode++) + for (int scancode = 0; scancode < 256; scancode++) { if (_glfw.wl.keycodes[scancode] > 0) _glfw.wl.scancodes[_glfw.wl.keycodes[scancode]] = scancode; } } +static GLFWbool loadCursorTheme(void) +{ + int cursorSize = 32; + + const char* sizeString = getenv("XCURSOR_SIZE"); + if (sizeString) + { + errno = 0; + const long cursorSizeLong = strtol(sizeString, NULL, 10); + if (errno == 0 && cursorSizeLong > 0 && cursorSizeLong < INT_MAX) + cursorSize = (int) cursorSizeLong; + } + + const char* themeName = getenv("XCURSOR_THEME"); + + _glfw.wl.cursorTheme = wl_cursor_theme_load(themeName, cursorSize, _glfw.wl.shm); + if (!_glfw.wl.cursorTheme) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to load default cursor theme"); + return GLFW_FALSE; + } + + // If this happens to be NULL, we just fallback to the scale=1 version. + _glfw.wl.cursorThemeHiDPI = + wl_cursor_theme_load(themeName, cursorSize * 2, _glfw.wl.shm); + + _glfw.wl.cursorSurface = wl_compositor_create_surface(_glfw.wl.compositor); + _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); + return GLFW_TRUE; +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -int _glfwPlatformInit(void) +GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform) { - const char *cursorTheme; - const char *cursorSizeStr; - char *cursorSizeEnd; - long cursorSizeLong; - int cursorSize; - - _glfw.wl.client.handle = _glfw_dlopen("libwayland-client.so.0"); - if (!_glfw.wl.client.handle) + const _GLFWplatform wayland = { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Failed to open libwayland-client"); + GLFW_PLATFORM_WAYLAND, + _glfwInitWayland, + _glfwTerminateWayland, + _glfwGetCursorPosWayland, + _glfwSetCursorPosWayland, + _glfwSetCursorModeWayland, + _glfwSetRawMouseMotionWayland, + _glfwRawMouseMotionSupportedWayland, + _glfwCreateCursorWayland, + _glfwCreateStandardCursorWayland, + _glfwDestroyCursorWayland, + _glfwSetCursorWayland, + _glfwGetScancodeNameWayland, + _glfwGetKeyScancodeWayland, + _glfwSetClipboardStringWayland, + _glfwGetClipboardStringWayland, +#if defined(_GLFW_LINUX_JOYSTICK) + _glfwInitJoysticksLinux, + _glfwTerminateJoysticksLinux, + _glfwPollJoystickLinux, + _glfwGetMappingNameLinux, + _glfwUpdateGamepadGUIDLinux, +#else + _glfwInitJoysticksNull, + _glfwTerminateJoysticksNull, + _glfwPollJoystickNull, + _glfwGetMappingNameNull, + _glfwUpdateGamepadGUIDNull, +#endif + _glfwFreeMonitorWayland, + _glfwGetMonitorPosWayland, + _glfwGetMonitorContentScaleWayland, + _glfwGetMonitorWorkareaWayland, + _glfwGetVideoModesWayland, + _glfwGetVideoModeWayland, + _glfwGetGammaRampWayland, + _glfwSetGammaRampWayland, + _glfwCreateWindowWayland, + _glfwDestroyWindowWayland, + _glfwSetWindowTitleWayland, + _glfwSetWindowIconWayland, + _glfwGetWindowPosWayland, + _glfwSetWindowPosWayland, + _glfwGetWindowSizeWayland, + _glfwSetWindowSizeWayland, + _glfwSetWindowSizeLimitsWayland, + _glfwSetWindowAspectRatioWayland, + _glfwGetFramebufferSizeWayland, + _glfwGetWindowFrameSizeWayland, + _glfwGetWindowContentScaleWayland, + _glfwIconifyWindowWayland, + _glfwRestoreWindowWayland, + _glfwMaximizeWindowWayland, + _glfwShowWindowWayland, + _glfwHideWindowWayland, + _glfwRequestWindowAttentionWayland, + _glfwFocusWindowWayland, + _glfwSetWindowMonitorWayland, + _glfwWindowFocusedWayland, + _glfwWindowIconifiedWayland, + _glfwWindowVisibleWayland, + _glfwWindowMaximizedWayland, + _glfwWindowHoveredWayland, + _glfwFramebufferTransparentWayland, + _glfwGetWindowOpacityWayland, + _glfwSetWindowResizableWayland, + _glfwSetWindowDecoratedWayland, + _glfwSetWindowFloatingWayland, + _glfwSetWindowOpacityWayland, + _glfwSetWindowMousePassthroughWayland, + _glfwPollEventsWayland, + _glfwWaitEventsWayland, + _glfwWaitEventsTimeoutWayland, + _glfwPostEmptyEventWayland, + _glfwGetEGLPlatformWayland, + _glfwGetEGLNativeDisplayWayland, + _glfwGetEGLNativeWindowWayland, + _glfwGetRequiredInstanceExtensionsWayland, + _glfwGetPhysicalDevicePresentationSupportWayland, + _glfwCreateWindowSurfaceWayland, + }; + + void* module = _glfwPlatformLoadModule("libwayland-client.so.0"); + if (!module) + { + if (platformID == GLFW_PLATFORM_WAYLAND) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to load libwayland-client"); + } + return GLFW_FALSE; } + PFN_wl_display_connect wl_display_connect = (PFN_wl_display_connect) + _glfwPlatformGetModuleSymbol(module, "wl_display_connect"); + if (!wl_display_connect) + { + if (platformID == GLFW_PLATFORM_WAYLAND) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to load libwayland-client entry point"); + } + + _glfwPlatformFreeModule(module); + return GLFW_FALSE; + } + + struct wl_display* display = wl_display_connect(NULL); + if (!display) + { + if (platformID == GLFW_PLATFORM_WAYLAND) + _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to connect to display"); + + _glfwPlatformFreeModule(module); + return GLFW_FALSE; + } + + _glfw.wl.display = display; + _glfw.wl.client.handle = module; + + *platform = wayland; + return GLFW_TRUE; +} + +int _glfwInitWayland(void) +{ + // These must be set before any failure checks + _glfw.wl.keyRepeatTimerfd = -1; + _glfw.wl.cursorTimerfd = -1; + _glfw.wl.client.display_flush = (PFN_wl_display_flush) - _glfw_dlsym(_glfw.wl.client.handle, "wl_display_flush"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_flush"); _glfw.wl.client.display_cancel_read = (PFN_wl_display_cancel_read) - _glfw_dlsym(_glfw.wl.client.handle, "wl_display_cancel_read"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_cancel_read"); _glfw.wl.client.display_dispatch_pending = (PFN_wl_display_dispatch_pending) - _glfw_dlsym(_glfw.wl.client.handle, "wl_display_dispatch_pending"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_dispatch_pending"); _glfw.wl.client.display_read_events = (PFN_wl_display_read_events) - _glfw_dlsym(_glfw.wl.client.handle, "wl_display_read_events"); - _glfw.wl.client.display_connect = (PFN_wl_display_connect) - _glfw_dlsym(_glfw.wl.client.handle, "wl_display_connect"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_read_events"); _glfw.wl.client.display_disconnect = (PFN_wl_display_disconnect) - _glfw_dlsym(_glfw.wl.client.handle, "wl_display_disconnect"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_disconnect"); _glfw.wl.client.display_roundtrip = (PFN_wl_display_roundtrip) - _glfw_dlsym(_glfw.wl.client.handle, "wl_display_roundtrip"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_roundtrip"); _glfw.wl.client.display_get_fd = (PFN_wl_display_get_fd) - _glfw_dlsym(_glfw.wl.client.handle, "wl_display_get_fd"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_get_fd"); _glfw.wl.client.display_prepare_read = (PFN_wl_display_prepare_read) - _glfw_dlsym(_glfw.wl.client.handle, "wl_display_prepare_read"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_prepare_read"); _glfw.wl.client.proxy_marshal = (PFN_wl_proxy_marshal) - _glfw_dlsym(_glfw.wl.client.handle, "wl_proxy_marshal"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_marshal"); _glfw.wl.client.proxy_add_listener = (PFN_wl_proxy_add_listener) - _glfw_dlsym(_glfw.wl.client.handle, "wl_proxy_add_listener"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_add_listener"); _glfw.wl.client.proxy_destroy = (PFN_wl_proxy_destroy) - _glfw_dlsym(_glfw.wl.client.handle, "wl_proxy_destroy"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_destroy"); _glfw.wl.client.proxy_marshal_constructor = (PFN_wl_proxy_marshal_constructor) - _glfw_dlsym(_glfw.wl.client.handle, "wl_proxy_marshal_constructor"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_marshal_constructor"); _glfw.wl.client.proxy_marshal_constructor_versioned = (PFN_wl_proxy_marshal_constructor_versioned) - _glfw_dlsym(_glfw.wl.client.handle, "wl_proxy_marshal_constructor_versioned"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_marshal_constructor_versioned"); _glfw.wl.client.proxy_get_user_data = (PFN_wl_proxy_get_user_data) - _glfw_dlsym(_glfw.wl.client.handle, "wl_proxy_get_user_data"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_user_data"); _glfw.wl.client.proxy_set_user_data = (PFN_wl_proxy_set_user_data) - _glfw_dlsym(_glfw.wl.client.handle, "wl_proxy_set_user_data"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_set_user_data"); _glfw.wl.client.proxy_get_version = (PFN_wl_proxy_get_version) - _glfw_dlsym(_glfw.wl.client.handle, "wl_proxy_get_version"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_version"); _glfw.wl.client.proxy_marshal_flags = (PFN_wl_proxy_marshal_flags) - _glfw_dlsym(_glfw.wl.client.handle, "wl_proxy_marshal_flags"); + _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_marshal_flags"); if (!_glfw.wl.client.display_flush || !_glfw.wl.client.display_cancel_read || !_glfw.wl.client.display_dispatch_pending || !_glfw.wl.client.display_read_events || - !_glfw.wl.client.display_connect || !_glfw.wl.client.display_disconnect || !_glfw.wl.client.display_roundtrip || !_glfw.wl.client.display_get_fd || @@ -1120,93 +565,86 @@ int _glfwPlatformInit(void) return GLFW_FALSE; } - _glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0"); + _glfw.wl.cursor.handle = _glfwPlatformLoadModule("libwayland-cursor.so.0"); if (!_glfw.wl.cursor.handle) { _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Failed to open libwayland-cursor"); + "Wayland: Failed to load libwayland-cursor"); return GLFW_FALSE; } _glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load) - _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_load"); + _glfwPlatformGetModuleSymbol(_glfw.wl.cursor.handle, "wl_cursor_theme_load"); _glfw.wl.cursor.theme_destroy = (PFN_wl_cursor_theme_destroy) - _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_destroy"); + _glfwPlatformGetModuleSymbol(_glfw.wl.cursor.handle, "wl_cursor_theme_destroy"); _glfw.wl.cursor.theme_get_cursor = (PFN_wl_cursor_theme_get_cursor) - _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor"); + _glfwPlatformGetModuleSymbol(_glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor"); _glfw.wl.cursor.image_get_buffer = (PFN_wl_cursor_image_get_buffer) - _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_image_get_buffer"); + _glfwPlatformGetModuleSymbol(_glfw.wl.cursor.handle, "wl_cursor_image_get_buffer"); - _glfw.wl.egl.handle = _glfw_dlopen("libwayland-egl.so.1"); + _glfw.wl.egl.handle = _glfwPlatformLoadModule("libwayland-egl.so.1"); if (!_glfw.wl.egl.handle) { _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Failed to open libwayland-egl"); + "Wayland: Failed to load libwayland-egl"); return GLFW_FALSE; } _glfw.wl.egl.window_create = (PFN_wl_egl_window_create) - _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_create"); + _glfwPlatformGetModuleSymbol(_glfw.wl.egl.handle, "wl_egl_window_create"); _glfw.wl.egl.window_destroy = (PFN_wl_egl_window_destroy) - _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_destroy"); + _glfwPlatformGetModuleSymbol(_glfw.wl.egl.handle, "wl_egl_window_destroy"); _glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize) - _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize"); + _glfwPlatformGetModuleSymbol(_glfw.wl.egl.handle, "wl_egl_window_resize"); - _glfw.wl.xkb.handle = _glfw_dlopen("libxkbcommon.so.0"); + _glfw.wl.xkb.handle = _glfwPlatformLoadModule("libxkbcommon.so.0"); if (!_glfw.wl.xkb.handle) { _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Failed to open libxkbcommon"); + "Wayland: Failed to load libxkbcommon"); return GLFW_FALSE; } _glfw.wl.xkb.context_new = (PFN_xkb_context_new) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_new"); + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_context_new"); _glfw.wl.xkb.context_unref = (PFN_xkb_context_unref) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_unref"); + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_context_unref"); _glfw.wl.xkb.keymap_new_from_string = (PFN_xkb_keymap_new_from_string) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string"); + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string"); _glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_unref"); + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_unref"); _glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index"); + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index"); _glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats"); + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats"); + _glfw.wl.xkb.keymap_key_get_syms_by_level = (PFN_xkb_keymap_key_get_syms_by_level) + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_key_get_syms_by_level"); _glfw.wl.xkb.state_new = (PFN_xkb_state_new) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new"); + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_new"); _glfw.wl.xkb.state_unref = (PFN_xkb_state_unref) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_unref"); + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_unref"); _glfw.wl.xkb.state_key_get_syms = (PFN_xkb_state_key_get_syms) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_syms"); + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_key_get_syms"); _glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask"); - _glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods"); - -#ifdef HAVE_XKBCOMMON_COMPOSE_H + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_update_mask"); + _glfw.wl.xkb.state_key_get_layout = (PFN_xkb_state_key_get_layout) + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_key_get_layout"); + _glfw.wl.xkb.state_mod_index_is_active = (PFN_xkb_state_mod_index_is_active) + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_mod_index_is_active"); _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale"); + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale"); _glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_unref"); + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_table_unref"); _glfw.wl.xkb.compose_state_new = (PFN_xkb_compose_state_new) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_new"); + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_new"); _glfw.wl.xkb.compose_state_unref = (PFN_xkb_compose_state_unref) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_unref"); + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_unref"); _glfw.wl.xkb.compose_state_feed = (PFN_xkb_compose_state_feed) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_feed"); + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_feed"); _glfw.wl.xkb.compose_state_get_status = (PFN_xkb_compose_state_get_status) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status"); + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_status"); _glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym) - _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym"); -#endif - - _glfw.wl.display = wl_display_connect(NULL); - if (!_glfw.wl.display) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Failed to connect to display"); - return GLFW_FALSE; - } + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym"); _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display); wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL); @@ -1227,11 +665,13 @@ int _glfwPlatformInit(void) // Sync so we got all initial output events wl_display_roundtrip(_glfw.wl.display); - _glfwInitTimerPOSIX(); - - _glfw.wl.timerfd = -1; - if (_glfw.wl.seatVersion >= 4) - _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); +#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION + if (_glfw.wl.seatVersion >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) + { + _glfw.wl.keyRepeatTimerfd = + timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); + } +#endif if (!_glfw.wl.wmBase) { @@ -1240,66 +680,40 @@ int _glfwPlatformInit(void) return GLFW_FALSE; } - if (_glfw.wl.pointer && _glfw.wl.shm) + if (!_glfw.wl.shm) { - cursorTheme = getenv("XCURSOR_THEME"); - cursorSizeStr = getenv("XCURSOR_SIZE"); - cursorSize = 32; - if (cursorSizeStr) - { - errno = 0; - cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10); - if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX) - cursorSize = (int)cursorSizeLong; - } - _glfw.wl.cursorTheme = - wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm); - if (!_glfw.wl.cursorTheme) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Unable to load default cursor theme"); - return GLFW_FALSE; - } - // If this happens to be NULL, we just fallback to the scale=1 version. - _glfw.wl.cursorThemeHiDPI = - wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm); - _glfw.wl.cursorSurface = - wl_compositor_create_surface(_glfw.wl.compositor); - _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to find wl_shm in your compositor"); + return GLFW_FALSE; } + if (!loadCursorTheme()) + return GLFW_FALSE; + if (_glfw.wl.seat && _glfw.wl.dataDeviceManager) { _glfw.wl.dataDevice = wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager, _glfw.wl.seat); - wl_data_device_add_listener(_glfw.wl.dataDevice, &dataDeviceListener, NULL); - _glfw.wl.clipboardString = _glfw_calloc(4096, 1); - if (!_glfw.wl.clipboardString) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Unable to allocate clipboard memory"); - return GLFW_FALSE; - } - _glfw.wl.clipboardSize = 4096; + _glfwAddDataDeviceListenerWayland(_glfw.wl.dataDevice); } return GLFW_TRUE; } -void _glfwPlatformTerminate(void) +void _glfwTerminateWayland(void) { _glfwTerminateEGL(); + _glfwTerminateOSMesa(); + if (_glfw.wl.egl.handle) { - _glfw_dlclose(_glfw.wl.egl.handle); + _glfwPlatformFreeModule(_glfw.wl.egl.handle); _glfw.wl.egl.handle = NULL; } -#ifdef HAVE_XKBCOMMON_COMPOSE_H if (_glfw.wl.xkb.composeState) xkb_compose_state_unref(_glfw.wl.xkb.composeState); -#endif if (_glfw.wl.xkb.keymap) xkb_keymap_unref(_glfw.wl.xkb.keymap); if (_glfw.wl.xkb.state) @@ -1308,7 +722,7 @@ void _glfwPlatformTerminate(void) xkb_context_unref(_glfw.wl.xkb.context); if (_glfw.wl.xkb.handle) { - _glfw_dlclose(_glfw.wl.xkb.handle); + _glfwPlatformFreeModule(_glfw.wl.xkb.handle); _glfw.wl.xkb.handle = NULL; } @@ -1318,10 +732,15 @@ void _glfwPlatformTerminate(void) wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI); if (_glfw.wl.cursor.handle) { - _glfw_dlclose(_glfw.wl.cursor.handle); + _glfwPlatformFreeModule(_glfw.wl.cursor.handle); _glfw.wl.cursor.handle = NULL; } + for (unsigned int i = 0; i < _glfw.wl.offerCount; i++) + wl_data_offer_destroy(_glfw.wl.offers[i].offer); + + _glfw_free(_glfw.wl.offers); + if (_glfw.wl.cursorSurface) wl_surface_destroy(_glfw.wl.cursorSurface); if (_glfw.wl.subcompositor) @@ -1336,12 +755,14 @@ void _glfwPlatformTerminate(void) zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager); if (_glfw.wl.wmBase) xdg_wm_base_destroy(_glfw.wl.wmBase); - if (_glfw.wl.dataSource) - wl_data_source_destroy(_glfw.wl.dataSource); + if (_glfw.wl.selectionOffer) + wl_data_offer_destroy(_glfw.wl.selectionOffer); + if (_glfw.wl.dragOffer) + wl_data_offer_destroy(_glfw.wl.dragOffer); + if (_glfw.wl.selectionSource) + wl_data_source_destroy(_glfw.wl.selectionSource); if (_glfw.wl.dataDevice) wl_data_device_destroy(_glfw.wl.dataDevice); - if (_glfw.wl.dataOffer) - wl_data_offer_destroy(_glfw.wl.dataOffer); if (_glfw.wl.dataDeviceManager) wl_data_device_manager_destroy(_glfw.wl.dataDeviceManager); if (_glfw.wl.pointer) @@ -1364,26 +785,13 @@ void _glfwPlatformTerminate(void) wl_display_disconnect(_glfw.wl.display); } - if (_glfw.wl.timerfd >= 0) - close(_glfw.wl.timerfd); + if (_glfw.wl.keyRepeatTimerfd >= 0) + close(_glfw.wl.keyRepeatTimerfd); if (_glfw.wl.cursorTimerfd >= 0) close(_glfw.wl.cursorTimerfd); - if (_glfw.wl.clipboardString) - _glfw_free(_glfw.wl.clipboardString); - if (_glfw.wl.clipboardSendString) - _glfw_free(_glfw.wl.clipboardSendString); + _glfw_free(_glfw.wl.clipboardString); } -const char* _glfwPlatformGetVersionString(void) -{ - return _GLFW_VERSION_NUMBER " Wayland EGL OSMesa" -#if defined(_POSIX_MONOTONIC_CLOCK) - " monotonic" -#endif - " evdev" -#if defined(_GLFW_BUILD_DLL) - " shared" -#endif - ; -} +#endif // _GLFW_WAYLAND + diff --git a/src/wl_monitor.c b/src/wl_monitor.c index 11f586ad..3d4fcbb8 100644 --- a/src/wl_monitor.c +++ b/src/wl_monitor.c @@ -28,6 +28,8 @@ #include "internal.h" +#if defined(_GLFW_WAYLAND) + #include #include #include @@ -37,7 +39,7 @@ #include "wayland-client-protocol.h" -static void outputHandleGeometry(void* data, +static void outputHandleGeometry(void* userData, struct wl_output* output, int32_t x, int32_t y, @@ -48,24 +50,25 @@ static void outputHandleGeometry(void* data, const char* model, int32_t transform) { - struct _GLFWmonitor *monitor = data; + struct _GLFWmonitor* monitor = userData; monitor->wl.x = x; monitor->wl.y = y; monitor->widthMM = physicalWidth; monitor->heightMM = physicalHeight; - snprintf(monitor->name, sizeof(monitor->name), "%s %s", make, model); + if (strlen(monitor->name) == 0) + snprintf(monitor->name, sizeof(monitor->name), "%s %s", make, model); } -static void outputHandleMode(void* data, +static void outputHandleMode(void* userData, struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { - struct _GLFWmonitor *monitor = data; + struct _GLFWmonitor* monitor = userData; GLFWvidmode mode; mode.width = width; @@ -84,9 +87,9 @@ static void outputHandleMode(void* data, monitor->wl.currentMode = monitor->modeCount - 1; } -static void outputHandleDone(void* data, struct wl_output* output) +static void outputHandleDone(void* userData, struct wl_output* output) { - struct _GLFWmonitor *monitor = data; + struct _GLFWmonitor* monitor = userData; if (monitor->widthMM <= 0 || monitor->heightMM <= 0) { @@ -96,23 +99,63 @@ static void outputHandleDone(void* data, struct wl_output* output) monitor->heightMM = (int) (mode->height * 25.4f / 96.f); } + for (int i = 0; i < _glfw.monitorCount; i++) + { + if (_glfw.monitors[i] == monitor) + return; + } + _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST); } -static void outputHandleScale(void* data, +static void outputHandleScale(void* userData, struct wl_output* output, int32_t factor) { - struct _GLFWmonitor *monitor = data; + struct _GLFWmonitor* monitor = userData; monitor->wl.scale = factor; + + for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next) + { + for (int i = 0; i < window->wl.monitorsCount; i++) + { + if (window->wl.monitors[i] == monitor) + { + _glfwUpdateContentScaleWayland(window); + break; + } + } + } } -static const struct wl_output_listener outputListener = { +#ifdef WL_OUTPUT_NAME_SINCE_VERSION + +void outputHandleName(void* userData, struct wl_output* wl_output, const char* name) +{ + struct _GLFWmonitor* monitor = userData; + + strncpy(monitor->name, name, sizeof(monitor->name) - 1); +} + +void outputHandleDescription(void* userData, + struct wl_output* wl_output, + const char* description) +{ +} + +#endif // WL_OUTPUT_NAME_SINCE_VERSION + +static const struct wl_output_listener outputListener = +{ outputHandleGeometry, outputHandleMode, outputHandleDone, outputHandleScale, +#ifdef WL_OUTPUT_NAME_SINCE_VERSION + outputHandleName, + outputHandleDescription, +#endif }; @@ -122,9 +165,6 @@ static const struct wl_output_listener outputListener = { void _glfwAddOutputWayland(uint32_t name, uint32_t version) { - _GLFWmonitor *monitor; - struct wl_output *output; - if (version < 2) { _glfwInputError(GLFW_PLATFORM_ERROR, @@ -132,19 +172,21 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version) return; } - // The actual name of this output will be set in the geometry handler. - monitor = _glfwAllocMonitor("", 0, 0); +#ifdef WL_OUTPUT_NAME_SINCE_VERSION + version = _glfw_min(version, WL_OUTPUT_NAME_SINCE_VERSION); +#else + version = 2; +#endif - output = wl_registry_bind(_glfw.wl.registry, - name, - &wl_output_interface, - 2); + struct wl_output* output = wl_registry_bind(_glfw.wl.registry, + name, + &wl_output_interface, + version); if (!output) - { - _glfwFreeMonitor(monitor); return; - } + // The actual name of this output will be set in the geometry handler + _GLFWmonitor* monitor = _glfwAllocMonitor("", 0, 0); monitor->wl.scale = 1; monitor->wl.output = output; monitor->wl.name = name; @@ -157,13 +199,13 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version) ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor) +void _glfwFreeMonitorWayland(_GLFWmonitor* monitor) { if (monitor->wl.output) wl_output_destroy(monitor->wl.output); } -void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) +void _glfwGetMonitorPosWayland(_GLFWmonitor* monitor, int* xpos, int* ypos) { if (xpos) *xpos = monitor->wl.x; @@ -171,8 +213,8 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) *ypos = monitor->wl.y; } -void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, - float* xscale, float* yscale) +void _glfwGetMonitorContentScaleWayland(_GLFWmonitor* monitor, + float* xscale, float* yscale) { if (xscale) *xscale = (float) monitor->wl.scale; @@ -180,9 +222,9 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, *yscale = (float) monitor->wl.scale; } -void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, - int* xpos, int* ypos, - int* width, int* height) +void _glfwGetMonitorWorkareaWayland(_GLFWmonitor* monitor, + int* xpos, int* ypos, + int* width, int* height) { if (xpos) *xpos = monitor->wl.x; @@ -194,26 +236,25 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, *height = monitor->modes[monitor->wl.currentMode].height; } -GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) +GLFWvidmode* _glfwGetVideoModesWayland(_GLFWmonitor* monitor, int* found) { *found = monitor->modeCount; return monitor->modes; } -void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) +void _glfwGetVideoModeWayland(_GLFWmonitor* monitor, GLFWvidmode* mode) { *mode = monitor->modes[monitor->wl.currentMode]; } -GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) +GLFWbool _glfwGetGammaRampWayland(_GLFWmonitor* monitor, GLFWgammaramp* ramp) { _glfwInputError(GLFW_FEATURE_UNAVAILABLE, "Wayland: Gamma ramp access is not available"); return GLFW_FALSE; } -void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, - const GLFWgammaramp* ramp) +void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) { _glfwInputError(GLFW_FEATURE_UNAVAILABLE, "Wayland: Gamma ramp access is not available"); @@ -231,3 +272,5 @@ GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle) return monitor->wl.output; } +#endif // _GLFW_WAYLAND + diff --git a/src/wl_platform.h b/src/wl_platform.h index d6017513..238e1ed4 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -26,10 +26,7 @@ #include #include -#ifdef HAVE_XKBCOMMON_COMPOSE_H #include -#endif -#include typedef VkFlags VkWaylandSurfaceCreateFlagsKHR; @@ -45,19 +42,13 @@ typedef struct VkWaylandSurfaceCreateInfoKHR typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWaylandSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*); typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*); -#include "posix_thread.h" -#include "posix_time.h" -#ifdef __linux__ -#include "linux_joystick.h" -#else -#include "null_joystick.h" -#endif #include "xkb_unicode.h" +#include "posix_poll.h" -typedef int (* PFN_wl_display_flush)(struct wl_display *display); -typedef void (* PFN_wl_display_cancel_read)(struct wl_display *display); -typedef int (* PFN_wl_display_dispatch_pending)(struct wl_display *display); -typedef int (* PFN_wl_display_read_events)(struct wl_display *display); +typedef int (* PFN_wl_display_flush)(struct wl_display* display); +typedef void (* PFN_wl_display_cancel_read)(struct wl_display* display); +typedef int (* PFN_wl_display_dispatch_pending)(struct wl_display* display); +typedef int (* PFN_wl_display_read_events)(struct wl_display* display); typedef struct wl_display* (* PFN_wl_display_connect)(const char*); typedef void (* PFN_wl_display_disconnect)(struct wl_display*); typedef int (* PFN_wl_display_roundtrip)(struct wl_display*); @@ -76,7 +67,6 @@ typedef struct wl_proxy* (* PFN_wl_proxy_marshal_flags)(struct wl_proxy*,uint32_ #define wl_display_cancel_read _glfw.wl.client.display_cancel_read #define wl_display_dispatch_pending _glfw.wl.client.display_dispatch_pending #define wl_display_read_events _glfw.wl.client.display_read_events -#define wl_display_connect _glfw.wl.client.display_connect #define wl_display_disconnect _glfw.wl.client.display_disconnect #define wl_display_roundtrip _glfw.wl.client.display_roundtrip #define wl_display_get_fd _glfw.wl.client.display_get_fd @@ -133,17 +123,10 @@ struct wl_shm; #define xdg_toplevel_interface _glfw_xdg_toplevel_interface #define xdg_wm_base_interface _glfw_xdg_wm_base_interface -#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) -#define _glfw_dlclose(handle) dlclose(handle) -#define _glfw_dlsym(handle, name) dlsym(handle, name) - -#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWayland wl -#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWayland wl -#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWayland wl -#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWayland wl - -#define _GLFW_PLATFORM_CONTEXT_STATE struct { int dummyContext; } -#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE struct { int dummyLibraryContext; } +#define GLFW_WAYLAND_WINDOW_STATE _GLFWwindowWayland wl; +#define GLFW_WAYLAND_LIBRARY_WINDOW_STATE _GLFWlibraryWayland wl; +#define GLFW_WAYLAND_MONITOR_STATE _GLFWmonitorWayland wl; +#define GLFW_WAYLAND_CURSOR_STATE _GLFWcursorWayland wl; struct wl_cursor_image { uint32_t width; @@ -179,24 +162,27 @@ typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*); typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*); typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t); +typedef int (* PFN_xkb_keymap_key_get_syms_by_level)(struct xkb_keymap*,xkb_keycode_t,xkb_layout_index_t,xkb_level_index_t,const xkb_keysym_t**); typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*); typedef void (* PFN_xkb_state_unref)(struct xkb_state*); typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**); typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t); -typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component); +typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xkb_keycode_t); +typedef int (* PFN_xkb_state_mod_index_is_active)(struct xkb_state*,xkb_mod_index_t,enum xkb_state_component); #define xkb_context_new _glfw.wl.xkb.context_new #define xkb_context_unref _glfw.wl.xkb.context_unref #define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string #define xkb_keymap_unref _glfw.wl.xkb.keymap_unref #define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index #define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats +#define xkb_keymap_key_get_syms_by_level _glfw.wl.xkb.keymap_key_get_syms_by_level #define xkb_state_new _glfw.wl.xkb.state_new #define xkb_state_unref _glfw.wl.xkb.state_unref #define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms #define xkb_state_update_mask _glfw.wl.xkb.state_update_mask -#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods +#define xkb_state_key_get_layout _glfw.wl.xkb.state_key_get_layout +#define xkb_state_mod_index_is_active _glfw.wl.xkb.state_mod_index_is_active -#ifdef HAVE_XKBCOMMON_COMPOSE_H typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags); typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*); typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags); @@ -211,12 +197,6 @@ typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_st #define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed #define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status #define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym -#endif - -#define _GLFW_DECORATION_WIDTH 4 -#define _GLFW_DECORATION_TOP 24 -#define _GLFW_DECORATION_VERTICAL (_GLFW_DECORATION_TOP + _GLFW_DECORATION_WIDTH) -#define _GLFW_DECORATION_HORIZONTAL (2 * _GLFW_DECORATION_WIDTH) typedef enum _GLFWdecorationSideWayland { @@ -225,7 +205,6 @@ typedef enum _GLFWdecorationSideWayland leftDecoration, rightDecoration, bottomDecoration, - } _GLFWdecorationSideWayland; typedef struct _GLFWdecorationWayland @@ -233,9 +212,15 @@ typedef struct _GLFWdecorationWayland struct wl_surface* surface; struct wl_subsurface* subsurface; struct wp_viewport* viewport; - } _GLFWdecorationWayland; +typedef struct _GLFWofferWayland +{ + struct wl_data_offer* offer; + GLFWbool text_plain_utf8; + GLFWbool text_uri_list; +} _GLFWofferWayland; + // Wayland-specific per-window data // typedef struct _GLFWwindowWayland @@ -243,22 +228,37 @@ typedef struct _GLFWwindowWayland int width, height; GLFWbool visible; GLFWbool maximized; + GLFWbool activated; + GLFWbool fullscreen; GLFWbool hovered; GLFWbool transparent; struct wl_surface* surface; - struct wl_egl_window* native; struct wl_callback* callback; + struct { + struct wl_egl_window* window; + } egl; + + struct { + int width, height; + GLFWbool maximized; + GLFWbool iconified; + GLFWbool activated; + GLFWbool fullscreen; + } pending; + struct { struct xdg_surface* surface; struct xdg_toplevel* toplevel; struct zxdg_toplevel_decoration_v1* decoration; + uint32_t decorationMode; } xdg; _GLFWcursor* currentCursor; double cursorPosX, cursorPosY; char* title; + char* appId; // We need to track the monitors the window spans on to calculate the // optimal scaling factor. @@ -267,22 +267,17 @@ typedef struct _GLFWwindowWayland int monitorsCount; int monitorsSize; - struct { - struct zwp_relative_pointer_v1* relativePointer; - struct zwp_locked_pointer_v1* lockedPointer; - } pointerLock; + struct zwp_relative_pointer_v1* relativePointer; + struct zwp_locked_pointer_v1* lockedPointer; + struct zwp_confined_pointer_v1* confinedPointer; struct zwp_idle_inhibitor_v1* idleInhibitor; - GLFWbool wasFullscreen; - struct { - GLFWbool serverSide; struct wl_buffer* buffer; _GLFWdecorationWayland top, left, right, bottom; - int focus; + _GLFWdecorationSideWayland focus; } decorations; - } _GLFWwindowWayland; // Wayland-specific global data @@ -299,8 +294,6 @@ typedef struct _GLFWlibraryWayland struct wl_keyboard* keyboard; struct wl_data_device_manager* dataDeviceManager; struct wl_data_device* dataDevice; - struct wl_data_offer* dataOffer; - struct wl_data_source* dataSource; struct xdg_wm_base* wmBase; struct zxdg_decoration_manager_v1* decorationManager; struct wp_viewporter* viewporter; @@ -308,6 +301,16 @@ typedef struct _GLFWlibraryWayland struct zwp_pointer_constraints_v1* pointerConstraints; struct zwp_idle_inhibit_manager_v1* idleInhibitManager; + _GLFWofferWayland* offers; + unsigned int offerCount; + + struct wl_data_offer* selectionOffer; + struct wl_data_source* selectionSource; + + struct wl_data_offer* dragOffer; + _GLFWwindow* dragFocus; + uint32_t dragSerial; + int compositorVersion; int seatVersion; @@ -319,17 +322,15 @@ typedef struct _GLFWlibraryWayland uint32_t serial; uint32_t pointerEnterSerial; - int32_t keyboardRepeatRate; - int32_t keyboardRepeatDelay; - int keyboardLastKey; - int keyboardLastScancode; + int keyRepeatTimerfd; + int32_t keyRepeatRate; + int32_t keyRepeatDelay; + int keyRepeatScancode; + char* clipboardString; - size_t clipboardSize; - char* clipboardSendString; - size_t clipboardSendSize; - int timerfd; short int keycodes[256]; short int scancodes[GLFW_KEY_LAST + 1]; + char keynames[GLFW_KEY_LAST + 1][5]; struct { void* handle; @@ -337,16 +338,14 @@ typedef struct _GLFWlibraryWayland struct xkb_keymap* keymap; struct xkb_state* state; -#ifdef HAVE_XKBCOMMON_COMPOSE_H struct xkb_compose_state* composeState; -#endif - xkb_mod_mask_t controlMask; - xkb_mod_mask_t altMask; - xkb_mod_mask_t shiftMask; - xkb_mod_mask_t superMask; - xkb_mod_mask_t capsLockMask; - xkb_mod_mask_t numLockMask; + xkb_mod_index_t controlIndex; + xkb_mod_index_t altIndex; + xkb_mod_index_t shiftIndex; + xkb_mod_index_t superIndex; + xkb_mod_index_t capsLockIndex; + xkb_mod_index_t numLockIndex; unsigned int modifiers; PFN_xkb_context_new context_new; @@ -355,13 +354,14 @@ typedef struct _GLFWlibraryWayland PFN_xkb_keymap_unref keymap_unref; PFN_xkb_keymap_mod_get_index keymap_mod_get_index; PFN_xkb_keymap_key_repeats keymap_key_repeats; + PFN_xkb_keymap_key_get_syms_by_level keymap_key_get_syms_by_level; PFN_xkb_state_new state_new; PFN_xkb_state_unref state_unref; PFN_xkb_state_key_get_syms state_key_get_syms; PFN_xkb_state_update_mask state_update_mask; - PFN_xkb_state_serialize_mods state_serialize_mods; + PFN_xkb_state_key_get_layout state_key_get_layout; + PFN_xkb_state_mod_index_is_active state_mod_index_is_active; -#ifdef HAVE_XKBCOMMON_COMPOSE_H PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale; PFN_xkb_compose_table_unref compose_table_unref; PFN_xkb_compose_state_new compose_state_new; @@ -369,7 +369,6 @@ typedef struct _GLFWlibraryWayland PFN_xkb_compose_state_feed compose_state_feed; PFN_xkb_compose_state_get_status compose_state_get_status; PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym; -#endif } xkb; _GLFWwindow* pointerFocus; @@ -381,7 +380,6 @@ typedef struct _GLFWlibraryWayland PFN_wl_display_cancel_read display_cancel_read; PFN_wl_display_dispatch_pending display_dispatch_pending; PFN_wl_display_read_events display_read_events; - PFN_wl_display_connect display_connect; PFN_wl_display_disconnect display_disconnect; PFN_wl_display_roundtrip display_roundtrip; PFN_wl_display_get_fd display_get_fd; @@ -413,7 +411,6 @@ typedef struct _GLFWlibraryWayland PFN_wl_egl_window_destroy window_destroy; PFN_wl_egl_window_resize window_resize; } egl; - } _GLFWlibraryWayland; // Wayland-specific per-monitor data @@ -427,7 +424,6 @@ typedef struct _GLFWmonitorWayland int x; int y; int scale; - } _GLFWmonitorWayland; // Wayland-specific per-cursor data @@ -442,6 +438,84 @@ typedef struct _GLFWcursorWayland int currentImage; } _GLFWcursorWayland; +GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform); +int _glfwInitWayland(void); +void _glfwTerminateWayland(void); + +GLFWbool _glfwCreateWindowWayland(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); +void _glfwDestroyWindowWayland(_GLFWwindow* window); +void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title); +void _glfwSetWindowIconWayland(_GLFWwindow* window, int count, const GLFWimage* images); +void _glfwGetWindowPosWayland(_GLFWwindow* window, int* xpos, int* ypos); +void _glfwSetWindowPosWayland(_GLFWwindow* window, int xpos, int ypos); +void _glfwGetWindowSizeWayland(_GLFWwindow* window, int* width, int* height); +void _glfwSetWindowSizeWayland(_GLFWwindow* window, int width, int height); +void _glfwSetWindowSizeLimitsWayland(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); +void _glfwSetWindowAspectRatioWayland(_GLFWwindow* window, int numer, int denom); +void _glfwGetFramebufferSizeWayland(_GLFWwindow* window, int* width, int* height); +void _glfwGetWindowFrameSizeWayland(_GLFWwindow* window, int* left, int* top, int* right, int* bottom); +void _glfwGetWindowContentScaleWayland(_GLFWwindow* window, float* xscale, float* yscale); +void _glfwIconifyWindowWayland(_GLFWwindow* window); +void _glfwRestoreWindowWayland(_GLFWwindow* window); +void _glfwMaximizeWindowWayland(_GLFWwindow* window); +void _glfwShowWindowWayland(_GLFWwindow* window); +void _glfwHideWindowWayland(_GLFWwindow* window); +void _glfwRequestWindowAttentionWayland(_GLFWwindow* window); +void _glfwFocusWindowWayland(_GLFWwindow* window); +void _glfwSetWindowMonitorWayland(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); +GLFWbool _glfwWindowFocusedWayland(_GLFWwindow* window); +GLFWbool _glfwWindowIconifiedWayland(_GLFWwindow* window); +GLFWbool _glfwWindowVisibleWayland(_GLFWwindow* window); +GLFWbool _glfwWindowMaximizedWayland(_GLFWwindow* window); +GLFWbool _glfwWindowHoveredWayland(_GLFWwindow* window); +GLFWbool _glfwFramebufferTransparentWayland(_GLFWwindow* window); +void _glfwSetWindowResizableWayland(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowDecoratedWayland(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowFloatingWayland(_GLFWwindow* window, GLFWbool enabled); +float _glfwGetWindowOpacityWayland(_GLFWwindow* window); +void _glfwSetWindowOpacityWayland(_GLFWwindow* window, float opacity); +void _glfwSetWindowMousePassthroughWayland(_GLFWwindow* window, GLFWbool enabled); + +void _glfwSetRawMouseMotionWayland(_GLFWwindow* window, GLFWbool enabled); +GLFWbool _glfwRawMouseMotionSupportedWayland(void); + +void _glfwPollEventsWayland(void); +void _glfwWaitEventsWayland(void); +void _glfwWaitEventsTimeoutWayland(double timeout); +void _glfwPostEmptyEventWayland(void); + +void _glfwGetCursorPosWayland(_GLFWwindow* window, double* xpos, double* ypos); +void _glfwSetCursorPosWayland(_GLFWwindow* window, double xpos, double ypos); +void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode); +const char* _glfwGetScancodeNameWayland(int scancode); +int _glfwGetKeyScancodeWayland(int key); +GLFWbool _glfwCreateCursorWayland(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot); +GLFWbool _glfwCreateStandardCursorWayland(_GLFWcursor* cursor, int shape); +void _glfwDestroyCursorWayland(_GLFWcursor* cursor); +void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* cursor); +void _glfwSetClipboardStringWayland(const char* string); +const char* _glfwGetClipboardStringWayland(void); + +EGLenum _glfwGetEGLPlatformWayland(EGLint** attribs); +EGLNativeDisplayType _glfwGetEGLNativeDisplayWayland(void); +EGLNativeWindowType _glfwGetEGLNativeWindowWayland(_GLFWwindow* window); + +void _glfwGetRequiredInstanceExtensionsWayland(char** extensions); +GLFWbool _glfwGetPhysicalDevicePresentationSupportWayland(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); +VkResult _glfwCreateWindowSurfaceWayland(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +void _glfwFreeMonitorWayland(_GLFWmonitor* monitor); +void _glfwGetMonitorPosWayland(_GLFWmonitor* monitor, int* xpos, int* ypos); +void _glfwGetMonitorContentScaleWayland(_GLFWmonitor* monitor, float* xscale, float* yscale); +void _glfwGetMonitorWorkareaWayland(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height); +GLFWvidmode* _glfwGetVideoModesWayland(_GLFWmonitor* monitor, int* count); +void _glfwGetVideoModeWayland(_GLFWmonitor* monitor, GLFWvidmode* mode); +GLFWbool _glfwGetGammaRampWayland(_GLFWmonitor* monitor, GLFWgammaramp* ramp); +void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp); void _glfwAddOutputWayland(uint32_t name, uint32_t version); +void _glfwUpdateContentScaleWayland(_GLFWwindow* window); + +void _glfwAddSeatListenerWayland(struct wl_seat* seat); +void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device); diff --git a/src/wl_window.c b/src/wl_window.c index 06cd7084..c4d097b7 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -30,9 +30,12 @@ #include "internal.h" +#if defined(_GLFW_WAYLAND) + #include #include #include +#include #include #include #include @@ -48,6 +51,8 @@ #include "wayland-pointer-constraints-unstable-v1-client-protocol.h" #include "wayland-idle-inhibit-unstable-v1-client-protocol.h" +#define GLFW_BORDER_SIZE 4 +#define GLFW_CAPTION_HEIGHT 24 static int createTmpfileCloexec(char* tmpname) { @@ -139,37 +144,34 @@ static int createAnonymousFile(off_t size) static struct wl_buffer* createShmBuffer(const GLFWimage* image) { - struct wl_shm_pool* pool; - struct wl_buffer* buffer; - int stride = image->width * 4; - int length = image->width * image->height * 4; - void* data; - int fd, i; + const int stride = image->width * 4; + const int length = image->width * image->height * 4; - fd = createAnonymousFile(length); + const int fd = createAnonymousFile(length); if (fd < 0) { _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Creating a buffer file for %d B failed: %s", + "Wayland: Failed to create buffer file of size %d: %s", length, strerror(errno)); return NULL; } - data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + void* data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (data == MAP_FAILED) { _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: mmap failed: %s", strerror(errno)); + "Wayland: Failed to map file: %s", strerror(errno)); close(fd); return NULL; } - pool = wl_shm_create_pool(_glfw.wl.shm, fd, length); + struct wl_shm_pool* pool = wl_shm_create_pool(_glfw.wl.shm, fd, length); close(fd); + unsigned char* source = (unsigned char*) image->pixels; unsigned char* target = data; - for (i = 0; i < image->width * image->height; i++, source += 4) + for (int i = 0; i < image->width * image->height; i++, source += 4) { unsigned int alpha = source[3]; @@ -179,7 +181,7 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image) *target++ = (unsigned char) alpha; } - buffer = + struct wl_buffer* buffer = wl_shm_pool_create_buffer(pool, 0, image->width, image->height, @@ -190,14 +192,12 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image) return buffer; } -static void createDecoration(_GLFWdecorationWayland* decoration, - struct wl_surface* parent, - struct wl_buffer* buffer, GLFWbool opaque, - int x, int y, - int width, int height) +static void createFallbackDecoration(_GLFWdecorationWayland* decoration, + struct wl_surface* parent, + struct wl_buffer* buffer, + int x, int y, + int width, int height) { - struct wl_region* region; - decoration->surface = wl_compositor_create_surface(_glfw.wl.compositor); decoration->subsurface = wl_subcompositor_get_subsurface(_glfw.wl.subcompositor, @@ -208,25 +208,19 @@ static void createDecoration(_GLFWdecorationWayland* decoration, wp_viewport_set_destination(decoration->viewport, width, height); wl_surface_attach(decoration->surface, buffer, 0, 0); - if (opaque) - { - region = wl_compositor_create_region(_glfw.wl.compositor); - wl_region_add(region, 0, 0, width, height); - wl_surface_set_opaque_region(decoration->surface, region); - wl_surface_commit(decoration->surface); - wl_region_destroy(region); - } - else - wl_surface_commit(decoration->surface); + struct wl_region* region = wl_compositor_create_region(_glfw.wl.compositor); + wl_region_add(region, 0, 0, width, height); + wl_surface_set_opaque_region(decoration->surface, region); + wl_surface_commit(decoration->surface); + wl_region_destroy(region); } -static void createDecorations(_GLFWwindow* window) +static void createFallbackDecorations(_GLFWwindow* window) { unsigned char data[] = { 224, 224, 224, 255 }; const GLFWimage image = { 1, 1, data }; - GLFWbool opaque = (data[3] == 255); - if (!_glfw.wl.viewporter || !window->decorated || window->wl.decorations.serverSide) + if (!_glfw.wl.viewporter) return; if (!window->wl.decorations.buffer) @@ -234,25 +228,25 @@ static void createDecorations(_GLFWwindow* window) if (!window->wl.decorations.buffer) return; - createDecoration(&window->wl.decorations.top, window->wl.surface, - window->wl.decorations.buffer, opaque, - 0, -_GLFW_DECORATION_TOP, - window->wl.width, _GLFW_DECORATION_TOP); - createDecoration(&window->wl.decorations.left, window->wl.surface, - window->wl.decorations.buffer, opaque, - -_GLFW_DECORATION_WIDTH, -_GLFW_DECORATION_TOP, - _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP); - createDecoration(&window->wl.decorations.right, window->wl.surface, - window->wl.decorations.buffer, opaque, - window->wl.width, -_GLFW_DECORATION_TOP, - _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP); - createDecoration(&window->wl.decorations.bottom, window->wl.surface, - window->wl.decorations.buffer, opaque, - -_GLFW_DECORATION_WIDTH, window->wl.height, - window->wl.width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH); + createFallbackDecoration(&window->wl.decorations.top, window->wl.surface, + window->wl.decorations.buffer, + 0, -GLFW_CAPTION_HEIGHT, + window->wl.width, GLFW_CAPTION_HEIGHT); + createFallbackDecoration(&window->wl.decorations.left, window->wl.surface, + window->wl.decorations.buffer, + -GLFW_BORDER_SIZE, -GLFW_CAPTION_HEIGHT, + GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT); + createFallbackDecoration(&window->wl.decorations.right, window->wl.surface, + window->wl.decorations.buffer, + window->wl.width, -GLFW_CAPTION_HEIGHT, + GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT); + createFallbackDecoration(&window->wl.decorations.bottom, window->wl.surface, + window->wl.decorations.buffer, + -GLFW_BORDER_SIZE, window->wl.height, + window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE); } -static void destroyDecoration(_GLFWdecorationWayland* decoration) +static void destroyFallbackDecoration(_GLFWdecorationWayland* decoration) { if (decoration->subsurface) wl_subsurface_destroy(decoration->subsurface); @@ -265,32 +259,38 @@ static void destroyDecoration(_GLFWdecorationWayland* decoration) decoration->viewport = NULL; } -static void destroyDecorations(_GLFWwindow* window) +static void destroyFallbackDecorations(_GLFWwindow* window) { - destroyDecoration(&window->wl.decorations.top); - destroyDecoration(&window->wl.decorations.left); - destroyDecoration(&window->wl.decorations.right); - destroyDecoration(&window->wl.decorations.bottom); + destroyFallbackDecoration(&window->wl.decorations.top); + destroyFallbackDecoration(&window->wl.decorations.left); + destroyFallbackDecoration(&window->wl.decorations.right); + destroyFallbackDecoration(&window->wl.decorations.bottom); } -static void xdgDecorationHandleConfigure(void* data, +static void xdgDecorationHandleConfigure(void* userData, struct zxdg_toplevel_decoration_v1* decoration, uint32_t mode) { - _GLFWwindow* window = data; + _GLFWwindow* window = userData; - window->wl.decorations.serverSide = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); + window->wl.xdg.decorationMode = mode; - if (!window->wl.decorations.serverSide) - createDecorations(window); + if (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE) + { + if (window->decorated && !window->monitor) + createFallbackDecorations(window); + } + else + destroyFallbackDecorations(window); } -static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener = { +static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener = +{ xdgDecorationHandleConfigure, }; // Makes the surface considered as XRGB instead of ARGB. -static void setOpaqueRegion(_GLFWwindow* window) +static void setContentAreaOpaque(_GLFWwindow* window) { struct wl_region* region; @@ -300,7 +300,6 @@ static void setOpaqueRegion(_GLFWwindow* window) wl_region_add(region, 0, 0, window->wl.width, window->wl.height); wl_surface_set_opaque_region(window->wl.surface, region); - wl_surface_commit(window->wl.surface); wl_region_destroy(region); } @@ -310,72 +309,63 @@ static void resizeWindow(_GLFWwindow* window) int scale = window->wl.scale; int scaledWidth = window->wl.width * scale; int scaledHeight = window->wl.height * scale; - wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0); + + if (window->wl.egl.window) + wl_egl_window_resize(window->wl.egl.window, scaledWidth, scaledHeight, 0, 0); if (!window->wl.transparent) - setOpaqueRegion(window); + setContentAreaOpaque(window); _glfwInputFramebufferSize(window, scaledWidth, scaledHeight); - _glfwInputWindowContentScale(window, scale, scale); if (!window->wl.decorations.top.surface) return; - // Top decoration. wp_viewport_set_destination(window->wl.decorations.top.viewport, - window->wl.width, _GLFW_DECORATION_TOP); + window->wl.width, GLFW_CAPTION_HEIGHT); wl_surface_commit(window->wl.decorations.top.surface); - // Left decoration. wp_viewport_set_destination(window->wl.decorations.left.viewport, - _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP); + GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT); wl_surface_commit(window->wl.decorations.left.surface); - // Right decoration. wl_subsurface_set_position(window->wl.decorations.right.subsurface, - window->wl.width, -_GLFW_DECORATION_TOP); + window->wl.width, -GLFW_CAPTION_HEIGHT); wp_viewport_set_destination(window->wl.decorations.right.viewport, - _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP); + GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT); wl_surface_commit(window->wl.decorations.right.surface); - // Bottom decoration. wl_subsurface_set_position(window->wl.decorations.bottom.subsurface, - -_GLFW_DECORATION_WIDTH, window->wl.height); + -GLFW_BORDER_SIZE, window->wl.height); wp_viewport_set_destination(window->wl.decorations.bottom.viewport, - window->wl.width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH); + window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE); wl_surface_commit(window->wl.decorations.bottom.surface); } -static void checkScaleChange(_GLFWwindow* window) +void _glfwUpdateContentScaleWayland(_GLFWwindow* window) { - int scale = 1; - int i; - int monitorScale; - - // Check if we will be able to set the buffer scale or not. - if (_glfw.wl.compositorVersion < 3) + if (_glfw.wl.compositorVersion < WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION) return; // Get the scale factor from the highest scale monitor. - for (i = 0; i < window->wl.monitorsCount; ++i) - { - monitorScale = window->wl.monitors[i]->wl.scale; - if (scale < monitorScale) - scale = monitorScale; - } + int maxScale = 1; + + for (int i = 0; i < window->wl.monitorsCount; i++) + maxScale = _glfw_max(window->wl.monitors[i]->wl.scale, maxScale); // Only change the framebuffer size if the scale changed. - if (scale != window->wl.scale) + if (window->wl.scale != maxScale) { - window->wl.scale = scale; - wl_surface_set_buffer_scale(window->wl.surface, scale); + window->wl.scale = maxScale; + wl_surface_set_buffer_scale(window->wl.surface, maxScale); + _glfwInputWindowContentScale(window, maxScale, maxScale); resizeWindow(window); } } -static void surfaceHandleEnter(void *data, - struct wl_surface *surface, - struct wl_output *output) +static void surfaceHandleEnter(void* userData, + struct wl_surface* surface, + struct wl_output* output) { - _GLFWwindow* window = data; + _GLFWwindow* window = userData; _GLFWmonitor* monitor = wl_output_get_user_data(output); if (window->wl.monitorsCount + 1 > window->wl.monitorsSize) @@ -388,19 +378,18 @@ static void surfaceHandleEnter(void *data, window->wl.monitors[window->wl.monitorsCount++] = monitor; - checkScaleChange(window); + _glfwUpdateContentScaleWayland(window); } -static void surfaceHandleLeave(void *data, - struct wl_surface *surface, - struct wl_output *output) +static void surfaceHandleLeave(void* userData, + struct wl_surface* surface, + struct wl_output* output) { - _GLFWwindow* window = data; + _GLFWwindow* window = userData; _GLFWmonitor* monitor = wl_output_get_user_data(output); - GLFWbool found; - int i; + GLFWbool found = GLFW_FALSE; - for (i = 0, found = GLFW_FALSE; i < window->wl.monitorsCount - 1; ++i) + for (int i = 0; i < window->wl.monitorsCount - 1; ++i) { if (monitor == window->wl.monitors[i]) found = GLFW_TRUE; @@ -409,10 +398,11 @@ static void surfaceHandleLeave(void *data, } window->wl.monitors[--window->wl.monitorsCount] = NULL; - checkScaleChange(window); + _glfwUpdateContentScaleWayland(window); } -static const struct wl_surface_listener surfaceListener = { +static const struct wl_surface_listener surfaceListener = +{ surfaceHandleEnter, surfaceHandleLeave }; @@ -426,7 +416,7 @@ static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable) _glfw.wl.idleInhibitManager, window->wl.surface); if (!window->wl.idleInhibitor) _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Idle inhibitor creation failed"); + "Wayland: Failed to create idle inhibitor"); } else if (!enable && window->wl.idleInhibitor) { @@ -435,211 +425,266 @@ static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable) } } -static GLFWbool createSurface(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig) -{ - window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor); - if (!window->wl.surface) - return GLFW_FALSE; - - wl_surface_add_listener(window->wl.surface, - &surfaceListener, - window); - - wl_surface_set_user_data(window->wl.surface, window); - - window->wl.native = wl_egl_window_create(window->wl.surface, - wndconfig->width, - wndconfig->height); - if (!window->wl.native) - return GLFW_FALSE; - - window->wl.width = wndconfig->width; - window->wl.height = wndconfig->height; - window->wl.scale = 1; - - if (!window->wl.transparent) - setOpaqueRegion(window); - - return GLFW_TRUE; -} - -static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor, - int refreshRate) +// Make the specified window and its video mode active on its monitor +// +static void acquireMonitor(_GLFWwindow* window) { if (window->wl.xdg.toplevel) { - xdg_toplevel_set_fullscreen( - window->wl.xdg.toplevel, - monitor->wl.output); + xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel, + window->monitor->wl.output); } + setIdleInhibitor(window, GLFW_TRUE); - if (!window->wl.decorations.serverSide) - destroyDecorations(window); + + if (window->wl.decorations.top.surface) + destroyFallbackDecorations(window); } -static void xdgToplevelHandleConfigure(void* data, +// Remove the window and restore the original video mode +// +static void releaseMonitor(_GLFWwindow* window) +{ + if (window->wl.xdg.toplevel) + xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel); + + setIdleInhibitor(window, GLFW_FALSE); + + if (window->wl.xdg.decorationMode != ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE) + { + if (window->decorated) + createFallbackDecorations(window); + } +} + +static void xdgToplevelHandleConfigure(void* userData, struct xdg_toplevel* toplevel, int32_t width, int32_t height, struct wl_array* states) { - _GLFWwindow* window = data; - float aspectRatio; - float targetRatio; + _GLFWwindow* window = userData; uint32_t* state; - GLFWbool maximized = GLFW_FALSE; - GLFWbool fullscreen = GLFW_FALSE; - GLFWbool activated = GLFW_FALSE; + + window->wl.pending.activated = GLFW_FALSE; + window->wl.pending.maximized = GLFW_FALSE; + window->wl.pending.fullscreen = GLFW_FALSE; wl_array_for_each(state, states) { switch (*state) { case XDG_TOPLEVEL_STATE_MAXIMIZED: - maximized = GLFW_TRUE; + window->wl.pending.maximized = GLFW_TRUE; break; case XDG_TOPLEVEL_STATE_FULLSCREEN: - fullscreen = GLFW_TRUE; + window->wl.pending.fullscreen = GLFW_TRUE; break; case XDG_TOPLEVEL_STATE_RESIZING: break; case XDG_TOPLEVEL_STATE_ACTIVATED: - activated = GLFW_TRUE; + window->wl.pending.activated = GLFW_TRUE; break; } } - if (width != 0 && height != 0) + if (width && height) { - if (!maximized && !fullscreen) + if (window->wl.decorations.top.surface) { - if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE) - { - aspectRatio = (float)width / (float)height; - targetRatio = (float)window->numer / (float)window->denom; - if (aspectRatio < targetRatio) - height = width / targetRatio; - else if (aspectRatio > targetRatio) - width = height * targetRatio; - } + window->wl.pending.width = _glfw_max(0, width - GLFW_BORDER_SIZE * 2); + window->wl.pending.height = + _glfw_max(0, height - GLFW_BORDER_SIZE - GLFW_CAPTION_HEIGHT); } - - _glfwInputWindowSize(window, width, height); - _glfwPlatformSetWindowSize(window, width, height); - _glfwInputWindowDamage(window); - } - - if (window->wl.wasFullscreen && window->autoIconify) - { - if (!activated || !fullscreen) + else { - _glfwPlatformIconifyWindow(window); - window->wl.wasFullscreen = GLFW_FALSE; + window->wl.pending.width = width; + window->wl.pending.height = height; } } - if (fullscreen && activated) - window->wl.wasFullscreen = GLFW_TRUE; - _glfwInputWindowFocus(window, activated); + else + { + window->wl.pending.width = window->wl.width; + window->wl.pending.height = window->wl.height; + } } -static void xdgToplevelHandleClose(void* data, +static void xdgToplevelHandleClose(void* userData, struct xdg_toplevel* toplevel) { - _GLFWwindow* window = data; + _GLFWwindow* window = userData; _glfwInputWindowCloseRequest(window); } -static const struct xdg_toplevel_listener xdgToplevelListener = { +static const struct xdg_toplevel_listener xdgToplevelListener = +{ xdgToplevelHandleConfigure, xdgToplevelHandleClose }; -static void xdgSurfaceHandleConfigure(void* data, +static void xdgSurfaceHandleConfigure(void* userData, struct xdg_surface* surface, uint32_t serial) { + _GLFWwindow* window = userData; + xdg_surface_ack_configure(surface, serial); + + if (window->wl.activated != window->wl.pending.activated) + { + window->wl.activated = window->wl.pending.activated; + if (!window->wl.activated) + { + if (window->monitor && window->autoIconify) + xdg_toplevel_set_minimized(window->wl.xdg.toplevel); + } + } + + if (window->wl.maximized != window->wl.pending.maximized) + { + window->wl.maximized = window->wl.pending.maximized; + _glfwInputWindowMaximize(window, window->wl.maximized); + } + + window->wl.fullscreen = window->wl.pending.fullscreen; + + int width = window->wl.pending.width; + int height = window->wl.pending.height; + + if (!window->wl.maximized && !window->wl.fullscreen) + { + if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE) + { + const float aspectRatio = (float) width / (float) height; + const float targetRatio = (float) window->numer / (float) window->denom; + if (aspectRatio < targetRatio) + height = width / targetRatio; + else if (aspectRatio > targetRatio) + width = height * targetRatio; + } + } + + if (width != window->wl.width || height != window->wl.height) + { + window->wl.width = width; + window->wl.height = height; + resizeWindow(window); + + _glfwInputWindowSize(window, width, height); + + if (window->wl.visible) + _glfwInputWindowDamage(window); + } + + if (!window->wl.visible) + { + // Allow the window to be mapped only if it either has no XDG + // decorations or they have already received a configure event + if (!window->wl.xdg.decoration || window->wl.xdg.decorationMode) + { + window->wl.visible = GLFW_TRUE; + _glfwInputWindowDamage(window); + } + } } -static const struct xdg_surface_listener xdgSurfaceListener = { +static const struct xdg_surface_listener xdgSurfaceListener = +{ xdgSurfaceHandleConfigure }; -static void setXdgDecorations(_GLFWwindow* window) -{ - if (_glfw.wl.decorationManager) - { - window->wl.xdg.decoration = - zxdg_decoration_manager_v1_get_toplevel_decoration( - _glfw.wl.decorationManager, window->wl.xdg.toplevel); - zxdg_toplevel_decoration_v1_add_listener(window->wl.xdg.decoration, - &xdgDecorationListener, - window); - zxdg_toplevel_decoration_v1_set_mode( - window->wl.xdg.decoration, - ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); - } - else - { - window->wl.decorations.serverSide = GLFW_FALSE; - createDecorations(window); - } -} - -static GLFWbool createXdgSurface(_GLFWwindow* window) +static GLFWbool createShellObjects(_GLFWwindow* window) { window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase, window->wl.surface); if (!window->wl.xdg.surface) { _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: xdg-surface creation failed"); + "Wayland: Failed to create xdg-surface for window"); return GLFW_FALSE; } - xdg_surface_add_listener(window->wl.xdg.surface, - &xdgSurfaceListener, - window); + xdg_surface_add_listener(window->wl.xdg.surface, &xdgSurfaceListener, window); window->wl.xdg.toplevel = xdg_surface_get_toplevel(window->wl.xdg.surface); if (!window->wl.xdg.toplevel) { _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: xdg-toplevel creation failed"); + "Wayland: Failed to create xdg-toplevel for window"); return GLFW_FALSE; } - xdg_toplevel_add_listener(window->wl.xdg.toplevel, - &xdgToplevelListener, - window); + xdg_toplevel_add_listener(window->wl.xdg.toplevel, &xdgToplevelListener, window); + + if (window->wl.appId) + xdg_toplevel_set_app_id(window->wl.xdg.toplevel, window->wl.appId); if (window->wl.title) xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title); - if (window->minwidth != GLFW_DONT_CARE && window->minheight != GLFW_DONT_CARE) - xdg_toplevel_set_min_size(window->wl.xdg.toplevel, - window->minwidth, window->minheight); - if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE) - xdg_toplevel_set_max_size(window->wl.xdg.toplevel, - window->maxwidth, window->maxheight); - if (window->monitor) { - xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel, - window->monitor->wl.output); + xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel, window->monitor->wl.output); setIdleInhibitor(window, GLFW_TRUE); } - else if (window->wl.maximized) - { - xdg_toplevel_set_maximized(window->wl.xdg.toplevel); - setIdleInhibitor(window, GLFW_FALSE); - setXdgDecorations(window); - } else { + if (window->wl.maximized) + xdg_toplevel_set_maximized(window->wl.xdg.toplevel); + setIdleInhibitor(window, GLFW_FALSE); - setXdgDecorations(window); + + if (_glfw.wl.decorationManager) + { + window->wl.xdg.decoration = + zxdg_decoration_manager_v1_get_toplevel_decoration( + _glfw.wl.decorationManager, window->wl.xdg.toplevel); + zxdg_toplevel_decoration_v1_add_listener(window->wl.xdg.decoration, + &xdgDecorationListener, + window); + + uint32_t mode; + + if (window->decorated) + mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE; + else + mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; + + zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, mode); + } + else + { + if (window->decorated) + createFallbackDecorations(window); + } + } + + if (window->minwidth != GLFW_DONT_CARE && window->minheight != GLFW_DONT_CARE) + { + int minwidth = window->minwidth; + int minheight = window->minheight; + + if (window->wl.decorations.top.surface) + { + minwidth += GLFW_BORDER_SIZE * 2; + minheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE; + } + + xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight); + } + + if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE) + { + int maxwidth = window->maxwidth; + int maxheight = window->maxheight; + + if (window->wl.decorations.top.surface) + { + maxwidth += GLFW_BORDER_SIZE * 2; + maxheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE; + } + + xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight); } wl_surface_commit(window->wl.surface); @@ -648,10 +693,61 @@ static GLFWbool createXdgSurface(_GLFWwindow* window) return GLFW_TRUE; } +static void destroyShellObjects(_GLFWwindow* window) +{ + destroyFallbackDecorations(window); + + if (window->wl.xdg.decoration) + zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration); + + if (window->wl.xdg.toplevel) + xdg_toplevel_destroy(window->wl.xdg.toplevel); + + if (window->wl.xdg.surface) + xdg_surface_destroy(window->wl.xdg.surface); + + window->wl.xdg.decoration = NULL; + window->wl.xdg.decorationMode = 0; + window->wl.xdg.toplevel = NULL; + window->wl.xdg.surface = NULL; +} + +static GLFWbool createNativeSurface(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) +{ + window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor); + if (!window->wl.surface) + { + _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to create window surface"); + return GLFW_FALSE; + } + + wl_surface_add_listener(window->wl.surface, + &surfaceListener, + window); + + wl_surface_set_user_data(window->wl.surface, window); + + window->wl.width = wndconfig->width; + window->wl.height = wndconfig->height; + window->wl.scale = 1; + window->wl.title = _glfw_strdup(wndconfig->title); + window->wl.appId = _glfw_strdup(wndconfig->wl.appId); + + window->wl.maximized = wndconfig->maximized; + + window->wl.transparent = fbconfig->transparent; + if (!window->wl.transparent) + setContentAreaOpaque(window); + + return GLFW_TRUE; +} + static void setCursorImage(_GLFWwindow* window, _GLFWcursorWayland* cursorWayland) { - struct itimerspec timer = {}; + struct itimerspec timer = {0}; struct wl_cursor* wlCursor = cursorWayland->cursor; struct wl_cursor_image* image; struct wl_buffer* buffer; @@ -710,93 +806,999 @@ static void incrementCursorImage(_GLFWwindow* window) } } -static void handleEvents(int timeout) +static GLFWbool flushDisplay(void) { - struct wl_display* display = _glfw.wl.display; - struct pollfd fds[] = { - { wl_display_get_fd(display), POLLIN }, - { _glfw.wl.timerfd, POLLIN }, - { _glfw.wl.cursorTimerfd, POLLIN }, - }; - ssize_t read_ret; - uint64_t repeats, i; - - 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) + while (wl_display_flush(_glfw.wl.display) == -1) { - _GLFWwindow* window = _glfw.windowListHead; - while (window) + if (errno != EAGAIN) + return GLFW_FALSE; + + struct pollfd fd = { wl_display_get_fd(_glfw.wl.display), POLLOUT }; + + while (poll(&fd, 1, -1) == -1) { - _glfwInputWindowCloseRequest(window); - window = window->next; + if (errno != EINTR && errno != EAGAIN) + return GLFW_FALSE; } - wl_display_cancel_read(display); - return; } - if (poll(fds, 3, timeout) > 0) + return GLFW_TRUE; +} + +static int translateKey(uint32_t scancode) +{ + if (scancode < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0])) + return _glfw.wl.keycodes[scancode]; + + return GLFW_KEY_UNKNOWN; +} + +static xkb_keysym_t composeSymbol(xkb_keysym_t sym) +{ + if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState) + return sym; + if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym) + != XKB_COMPOSE_FEED_ACCEPTED) + return sym; + switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState)) { + case XKB_COMPOSE_COMPOSED: + return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState); + case XKB_COMPOSE_COMPOSING: + case XKB_COMPOSE_CANCELLED: + return XKB_KEY_NoSymbol; + case XKB_COMPOSE_NOTHING: + default: + return sym; + } +} + +static void inputText(_GLFWwindow* window, uint32_t scancode) +{ + const xkb_keysym_t* keysyms; + const xkb_keycode_t keycode = scancode + 8; + + if (xkb_state_key_get_syms(_glfw.wl.xkb.state, keycode, &keysyms) == 1) + { + const xkb_keysym_t keysym = composeSymbol(keysyms[0]); + const uint32_t codepoint = _glfwKeySym2Unicode(keysym); + if (codepoint != GLFW_INVALID_CODEPOINT) + { + const int mods = _glfw.wl.xkb.modifiers; + const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); + _glfwInputChar(window, codepoint, mods, plain); + } + } +} + +static void handleEvents(double* timeout) +{ + GLFWbool event = GLFW_FALSE; + struct pollfd fds[] = + { + { wl_display_get_fd(_glfw.wl.display), POLLIN }, + { _glfw.wl.keyRepeatTimerfd, POLLIN }, + { _glfw.wl.cursorTimerfd, POLLIN }, + }; + + while (!event) + { + while (wl_display_prepare_read(_glfw.wl.display) != 0) + wl_display_dispatch_pending(_glfw.wl.display); + + // If an error other than EAGAIN happens, we have likely been disconnected + // from the Wayland session; try to handle that the best we can. + if (!flushDisplay()) + { + wl_display_cancel_read(_glfw.wl.display); + + _GLFWwindow* window = _glfw.windowListHead; + while (window) + { + _glfwInputWindowCloseRequest(window); + window = window->next; + } + + return; + } + + if (!_glfwPollPOSIX(fds, 3, timeout)) + { + wl_display_cancel_read(_glfw.wl.display); + return; + } + if (fds[0].revents & POLLIN) { - wl_display_read_events(display); - wl_display_dispatch_pending(display); + wl_display_read_events(_glfw.wl.display); + if (wl_display_dispatch_pending(_glfw.wl.display) > 0) + event = GLFW_TRUE; } else - { - wl_display_cancel_read(display); - } + wl_display_cancel_read(_glfw.wl.display); if (fds[1].revents & POLLIN) { - read_ret = read(_glfw.wl.timerfd, &repeats, sizeof(repeats)); - if (read_ret != 8) - return; + uint64_t repeats; - if (_glfw.wl.keyboardFocus) + if (read(_glfw.wl.keyRepeatTimerfd, &repeats, sizeof(repeats)) == 8) { - for (i = 0; i < repeats; ++i) + for (uint64_t i = 0; i < repeats; i++) { _glfwInputKey(_glfw.wl.keyboardFocus, - _glfw.wl.keyboardLastKey, - _glfw.wl.keyboardLastScancode, - GLFW_REPEAT, + translateKey(_glfw.wl.keyRepeatScancode), + _glfw.wl.keyRepeatScancode, + GLFW_PRESS, _glfw.wl.xkb.modifiers); + inputText(_glfw.wl.keyboardFocus, _glfw.wl.keyRepeatScancode); } + + event = GLFW_TRUE; } } if (fds[2].revents & POLLIN) { - read_ret = read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)); - if (read_ret != 8) - return; + uint64_t repeats; - incrementCursorImage(_glfw.wl.pointerFocus); + if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8) + { + incrementCursorImage(_glfw.wl.pointerFocus); + event = GLFW_TRUE; + } } } +} + +// Reads the specified data offer as the specified MIME type +// +static char* readDataOfferAsString(struct wl_data_offer* offer, const char* mimeType) +{ + int fds[2]; + + if (pipe2(fds, O_CLOEXEC) == -1) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to create pipe for data offer: %s", + strerror(errno)); + return NULL; + } + + wl_data_offer_receive(offer, mimeType, fds[1]); + flushDisplay(); + close(fds[1]); + + char* string = NULL; + size_t size = 0; + size_t length = 0; + + for (;;) + { + const size_t readSize = 4096; + const size_t requiredSize = length + readSize + 1; + if (requiredSize > size) + { + char* longer = _glfw_realloc(string, requiredSize); + if (!longer) + { + _glfwInputError(GLFW_OUT_OF_MEMORY, NULL); + close(fds[0]); + return NULL; + } + + string = longer; + size = requiredSize; + } + + const ssize_t result = read(fds[0], string + length, readSize); + if (result == 0) + break; + else if (result == -1) + { + if (errno == EINTR) + continue; + + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to read from data offer pipe: %s", + strerror(errno)); + close(fds[0]); + return NULL; + } + + length += result; + } + + close(fds[0]); + + string[length] = '\0'; + return string; +} + +static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface, + _GLFWdecorationSideWayland* which) +{ + _GLFWdecorationSideWayland focus; + _GLFWwindow* window = _glfw.windowListHead; + if (!which) + which = &focus; + while (window) + { + if (surface == window->wl.decorations.top.surface) + { + *which = topDecoration; + break; + } + if (surface == window->wl.decorations.left.surface) + { + *which = leftDecoration; + break; + } + if (surface == window->wl.decorations.right.surface) + { + *which = rightDecoration; + break; + } + if (surface == window->wl.decorations.bottom.surface) + { + *which = bottomDecoration; + break; + } + window = window->next; + } + return window; +} + +static void pointerHandleEnter(void* userData, + struct wl_pointer* pointer, + uint32_t serial, + struct wl_surface* surface, + wl_fixed_t sx, + wl_fixed_t sy) +{ + // Happens in the case we just destroyed the surface. + if (!surface) + return; + + _GLFWdecorationSideWayland focus = mainWindow; + _GLFWwindow* window = wl_surface_get_user_data(surface); + if (!window) + { + window = findWindowFromDecorationSurface(surface, &focus); + if (!window) + return; + } + + window->wl.decorations.focus = focus; + _glfw.wl.serial = serial; + _glfw.wl.pointerEnterSerial = serial; + _glfw.wl.pointerFocus = window; + + window->wl.hovered = GLFW_TRUE; + + _glfwSetCursorWayland(window, window->wl.currentCursor); + _glfwInputCursorEnter(window, GLFW_TRUE); +} + +static void pointerHandleLeave(void* userData, + struct wl_pointer* pointer, + uint32_t serial, + struct wl_surface* surface) +{ + _GLFWwindow* window = _glfw.wl.pointerFocus; + + if (!window) + return; + + window->wl.hovered = GLFW_FALSE; + + _glfw.wl.serial = serial; + _glfw.wl.pointerFocus = NULL; + _glfw.wl.cursorPreviousName = NULL; + _glfwInputCursorEnter(window, GLFW_FALSE); +} + +static void setCursor(_GLFWwindow* window, const char* name) +{ + struct wl_buffer* buffer; + struct wl_cursor* cursor; + struct wl_cursor_image* image; + struct wl_surface* surface = _glfw.wl.cursorSurface; + struct wl_cursor_theme* theme = _glfw.wl.cursorTheme; + int scale = 1; + + if (window->wl.scale > 1 && _glfw.wl.cursorThemeHiDPI) + { + // We only support up to scale=2 for now, since libwayland-cursor + // requires us to load a different theme for each size. + scale = 2; + theme = _glfw.wl.cursorThemeHiDPI; + } + + cursor = wl_cursor_theme_get_cursor(theme, name); + if (!cursor) + { + _glfwInputError(GLFW_CURSOR_UNAVAILABLE, + "Wayland: Standard cursor shape unavailable"); + return; + } + // TODO: handle animated cursors too. + image = cursor->images[0]; + + if (!image) + return; + + buffer = wl_cursor_image_get_buffer(image); + if (!buffer) + return; + wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial, + surface, + image->hotspot_x / scale, + image->hotspot_y / scale); + wl_surface_set_buffer_scale(surface, scale); + wl_surface_attach(surface, buffer, 0, 0); + wl_surface_damage(surface, 0, 0, + image->width, image->height); + wl_surface_commit(surface); + _glfw.wl.cursorPreviousName = name; +} + +static void pointerHandleMotion(void* userData, + struct wl_pointer* pointer, + uint32_t time, + wl_fixed_t sx, + wl_fixed_t sy) +{ + _GLFWwindow* window = _glfw.wl.pointerFocus; + const char* cursorName = NULL; + double x, y; + + if (!window) + return; + + if (window->cursorMode == GLFW_CURSOR_DISABLED) + return; + x = wl_fixed_to_double(sx); + y = wl_fixed_to_double(sy); + window->wl.cursorPosX = x; + window->wl.cursorPosY = y; + + switch (window->wl.decorations.focus) + { + case mainWindow: + _glfw.wl.cursorPreviousName = NULL; + _glfwInputCursorPos(window, x, y); + return; + case topDecoration: + if (y < GLFW_BORDER_SIZE) + cursorName = "n-resize"; + else + cursorName = "left_ptr"; + break; + case leftDecoration: + if (y < GLFW_BORDER_SIZE) + cursorName = "nw-resize"; + else + cursorName = "w-resize"; + break; + case rightDecoration: + if (y < GLFW_BORDER_SIZE) + cursorName = "ne-resize"; + else + cursorName = "e-resize"; + break; + case bottomDecoration: + if (x < GLFW_BORDER_SIZE) + cursorName = "sw-resize"; + else if (x > window->wl.width + GLFW_BORDER_SIZE) + cursorName = "se-resize"; + else + cursorName = "s-resize"; + break; + default: + assert(0); + } + if (_glfw.wl.cursorPreviousName != cursorName) + setCursor(window, cursorName); +} + +static void pointerHandleButton(void* userData, + struct wl_pointer* pointer, + uint32_t serial, + uint32_t time, + uint32_t button, + uint32_t state) +{ + _GLFWwindow* window = _glfw.wl.pointerFocus; + int glfwButton; + uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE; + + if (!window) + return; + if (button == BTN_LEFT) + { + switch (window->wl.decorations.focus) + { + case mainWindow: + break; + case topDecoration: + if (window->wl.cursorPosY < GLFW_BORDER_SIZE) + edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP; + else + xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial); + break; + case leftDecoration: + if (window->wl.cursorPosY < GLFW_BORDER_SIZE) + edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; + else + edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT; + break; + case rightDecoration: + if (window->wl.cursorPosY < GLFW_BORDER_SIZE) + edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; + else + edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; + break; + case bottomDecoration: + if (window->wl.cursorPosX < GLFW_BORDER_SIZE) + edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; + else if (window->wl.cursorPosX > window->wl.width + GLFW_BORDER_SIZE) + edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; + else + edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; + break; + default: + assert(0); + } + if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE) + { + xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat, + serial, edges); + return; + } + } + else if (button == BTN_RIGHT) + { + if (window->wl.decorations.focus != mainWindow && window->wl.xdg.toplevel) + { + xdg_toplevel_show_window_menu(window->wl.xdg.toplevel, + _glfw.wl.seat, serial, + window->wl.cursorPosX, + window->wl.cursorPosY); + return; + } + } + + // Don’t pass the button to the user if it was related to a decoration. + if (window->wl.decorations.focus != mainWindow) + return; + + _glfw.wl.serial = serial; + + /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev + * codes. */ + glfwButton = button - BTN_LEFT; + + _glfwInputMouseClick(window, + glfwButton, + state == WL_POINTER_BUTTON_STATE_PRESSED + ? GLFW_PRESS + : GLFW_RELEASE, + _glfw.wl.xkb.modifiers); +} + +static void pointerHandleAxis(void* userData, + struct wl_pointer* pointer, + uint32_t time, + uint32_t axis, + wl_fixed_t value) +{ + _GLFWwindow* window = _glfw.wl.pointerFocus; + double x = 0.0, y = 0.0; + // Wayland scroll events are in pointer motion coordinate space (think two + // finger scroll). The factor 10 is commonly used to convert to "scroll + // step means 1.0. + const double scrollFactor = 1.0 / 10.0; + + if (!window) + return; + + assert(axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL || + axis == WL_POINTER_AXIS_VERTICAL_SCROLL); + + if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) + x = -wl_fixed_to_double(value) * scrollFactor; + else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) + y = -wl_fixed_to_double(value) * scrollFactor; + + _glfwInputScroll(window, x, y); +} + +static const struct wl_pointer_listener pointerListener = +{ + pointerHandleEnter, + pointerHandleLeave, + pointerHandleMotion, + pointerHandleButton, + pointerHandleAxis, +}; + +static void keyboardHandleKeymap(void* userData, + struct wl_keyboard* keyboard, + uint32_t format, + int fd, + uint32_t size) +{ + struct xkb_keymap* keymap; + struct xkb_state* state; + struct xkb_compose_table* composeTable; + struct xkb_compose_state* composeState; + + char* mapStr; + const char* locale; + + if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) + { + close(fd); + return; + } + + mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (mapStr == MAP_FAILED) { + close(fd); + return; + } + + keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context, + mapStr, + XKB_KEYMAP_FORMAT_TEXT_V1, + 0); + munmap(mapStr, size); + close(fd); + + if (!keymap) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to compile keymap"); + return; + } + + state = xkb_state_new(keymap); + if (!state) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to create XKB state"); + xkb_keymap_unref(keymap); + return; + } + + // Look up the preferred locale, falling back to "C" as default. + locale = getenv("LC_ALL"); + if (!locale) + locale = getenv("LC_CTYPE"); + if (!locale) + locale = getenv("LANG"); + if (!locale) + locale = "C"; + + composeTable = + xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale, + XKB_COMPOSE_COMPILE_NO_FLAGS); + if (composeTable) + { + composeState = + xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS); + xkb_compose_table_unref(composeTable); + if (composeState) + _glfw.wl.xkb.composeState = composeState; + else + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to create XKB compose state"); + } else { - wl_display_cancel_read(display); + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to create XKB compose table"); + } + + xkb_keymap_unref(_glfw.wl.xkb.keymap); + xkb_state_unref(_glfw.wl.xkb.state); + _glfw.wl.xkb.keymap = keymap; + _glfw.wl.xkb.state = state; + + _glfw.wl.xkb.controlIndex = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control"); + _glfw.wl.xkb.altIndex = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1"); + _glfw.wl.xkb.shiftIndex = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift"); + _glfw.wl.xkb.superIndex = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4"); + _glfw.wl.xkb.capsLockIndex = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Lock"); + _glfw.wl.xkb.numLockIndex = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod2"); +} + +static void keyboardHandleEnter(void* userData, + struct wl_keyboard* keyboard, + uint32_t serial, + struct wl_surface* surface, + struct wl_array* keys) +{ + // Happens in the case we just destroyed the surface. + if (!surface) + return; + + _GLFWwindow* window = wl_surface_get_user_data(surface); + if (!window) + { + window = findWindowFromDecorationSurface(surface, NULL); + if (!window) + return; + } + + _glfw.wl.serial = serial; + _glfw.wl.keyboardFocus = window; + _glfwInputWindowFocus(window, GLFW_TRUE); +} + +static void keyboardHandleLeave(void* userData, + struct wl_keyboard* keyboard, + uint32_t serial, + struct wl_surface* surface) +{ + _GLFWwindow* window = _glfw.wl.keyboardFocus; + + if (!window) + return; + + struct itimerspec timer = {0}; + timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL); + + _glfw.wl.serial = serial; + _glfw.wl.keyboardFocus = NULL; + _glfwInputWindowFocus(window, GLFW_FALSE); +} + +static void keyboardHandleKey(void* userData, + struct wl_keyboard* keyboard, + uint32_t serial, + uint32_t time, + uint32_t scancode, + uint32_t state) +{ + _GLFWwindow* window = _glfw.wl.keyboardFocus; + if (!window) + return; + + const int key = translateKey(scancode); + const int action = + state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE; + + _glfw.wl.serial = serial; + + struct itimerspec timer = {0}; + + if (action == GLFW_PRESS) + { + const xkb_keycode_t keycode = scancode + 8; + + if (xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, keycode) && + _glfw.wl.keyRepeatRate > 0) + { + _glfw.wl.keyRepeatScancode = scancode; + if (_glfw.wl.keyRepeatRate > 1) + timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyRepeatRate; + else + timer.it_interval.tv_sec = 1; + + timer.it_value.tv_sec = _glfw.wl.keyRepeatDelay / 1000; + timer.it_value.tv_nsec = (_glfw.wl.keyRepeatDelay % 1000) * 1000000; + } + } + + timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL); + + _glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers); + + if (action == GLFW_PRESS) + inputText(window, scancode); +} + +static void keyboardHandleModifiers(void* userData, + struct wl_keyboard* keyboard, + uint32_t serial, + uint32_t modsDepressed, + uint32_t modsLatched, + uint32_t modsLocked, + uint32_t group) +{ + _glfw.wl.serial = serial; + + if (!_glfw.wl.xkb.keymap) + return; + + xkb_state_update_mask(_glfw.wl.xkb.state, + modsDepressed, + modsLatched, + modsLocked, + 0, + 0, + group); + + _glfw.wl.xkb.modifiers = 0; + + struct + { + xkb_mod_index_t index; + unsigned int bit; + } modifiers[] = + { + { _glfw.wl.xkb.controlIndex, GLFW_MOD_CONTROL }, + { _glfw.wl.xkb.altIndex, GLFW_MOD_ALT }, + { _glfw.wl.xkb.shiftIndex, GLFW_MOD_SHIFT }, + { _glfw.wl.xkb.superIndex, GLFW_MOD_SUPER }, + { _glfw.wl.xkb.capsLockIndex, GLFW_MOD_CAPS_LOCK }, + { _glfw.wl.xkb.numLockIndex, GLFW_MOD_NUM_LOCK } + }; + + for (size_t i = 0; i < sizeof(modifiers) / sizeof(modifiers[0]); i++) + { + if (xkb_state_mod_index_is_active(_glfw.wl.xkb.state, + modifiers[i].index, + XKB_STATE_MODS_EFFECTIVE) == 1) + { + _glfw.wl.xkb.modifiers |= modifiers[i].bit; + } } } +#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION +static void keyboardHandleRepeatInfo(void* userData, + struct wl_keyboard* keyboard, + int32_t rate, + int32_t delay) +{ + if (keyboard != _glfw.wl.keyboard) + return; + + _glfw.wl.keyRepeatRate = rate; + _glfw.wl.keyRepeatDelay = delay; +} +#endif + +static const struct wl_keyboard_listener keyboardListener = +{ + keyboardHandleKeymap, + keyboardHandleEnter, + keyboardHandleLeave, + keyboardHandleKey, + keyboardHandleModifiers, +#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION + keyboardHandleRepeatInfo, +#endif +}; + +static void seatHandleCapabilities(void* userData, + struct wl_seat* seat, + enum wl_seat_capability caps) +{ + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !_glfw.wl.pointer) + { + _glfw.wl.pointer = wl_seat_get_pointer(seat); + wl_pointer_add_listener(_glfw.wl.pointer, &pointerListener, NULL); + } + else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer) + { + wl_pointer_destroy(_glfw.wl.pointer); + _glfw.wl.pointer = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !_glfw.wl.keyboard) + { + _glfw.wl.keyboard = wl_seat_get_keyboard(seat); + wl_keyboard_add_listener(_glfw.wl.keyboard, &keyboardListener, NULL); + } + else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard) + { + wl_keyboard_destroy(_glfw.wl.keyboard); + _glfw.wl.keyboard = NULL; + } +} + +static void seatHandleName(void* userData, + struct wl_seat* seat, + const char* name) +{ +} + +static const struct wl_seat_listener seatListener = +{ + seatHandleCapabilities, + seatHandleName, +}; + +static void dataOfferHandleOffer(void* userData, + struct wl_data_offer* offer, + const char* mimeType) +{ + for (unsigned int i = 0; i < _glfw.wl.offerCount; i++) + { + if (_glfw.wl.offers[i].offer == offer) + { + if (strcmp(mimeType, "text/plain;charset=utf-8") == 0) + _glfw.wl.offers[i].text_plain_utf8 = GLFW_TRUE; + else if (strcmp(mimeType, "text/uri-list") == 0) + _glfw.wl.offers[i].text_uri_list = GLFW_TRUE; + + break; + } + } +} + +static const struct wl_data_offer_listener dataOfferListener = +{ + dataOfferHandleOffer +}; + +static void dataDeviceHandleDataOffer(void* userData, + struct wl_data_device* device, + struct wl_data_offer* offer) +{ + _GLFWofferWayland* offers = + _glfw_realloc(_glfw.wl.offers, _glfw.wl.offerCount + 1); + if (!offers) + { + _glfwInputError(GLFW_OUT_OF_MEMORY, NULL); + return; + } + + _glfw.wl.offers = offers; + _glfw.wl.offerCount++; + + _glfw.wl.offers[_glfw.wl.offerCount - 1] = (_GLFWofferWayland) { offer }; + wl_data_offer_add_listener(offer, &dataOfferListener, NULL); +} + +static void dataDeviceHandleEnter(void* userData, + struct wl_data_device* device, + uint32_t serial, + struct wl_surface* surface, + wl_fixed_t x, + wl_fixed_t y, + struct wl_data_offer* offer) +{ + if (_glfw.wl.dragOffer) + { + wl_data_offer_destroy(_glfw.wl.dragOffer); + _glfw.wl.dragOffer = NULL; + _glfw.wl.dragFocus = NULL; + } + + for (unsigned int i = 0; i < _glfw.wl.offerCount; i++) + { + if (_glfw.wl.offers[i].offer == offer) + { + _GLFWwindow* window = NULL; + + if (surface) + window = wl_surface_get_user_data(surface); + + if (window && _glfw.wl.offers[i].text_uri_list) + { + _glfw.wl.dragOffer = offer; + _glfw.wl.dragFocus = window; + _glfw.wl.dragSerial = serial; + } + + _glfw.wl.offers[i] = _glfw.wl.offers[_glfw.wl.offerCount - 1]; + _glfw.wl.offerCount--; + break; + } + } + + if (_glfw.wl.dragOffer) + wl_data_offer_accept(offer, serial, "text/uri-list"); + else + { + wl_data_offer_accept(offer, serial, NULL); + wl_data_offer_destroy(offer); + } +} + +static void dataDeviceHandleLeave(void* userData, + struct wl_data_device* device) +{ + if (_glfw.wl.dragOffer) + { + wl_data_offer_destroy(_glfw.wl.dragOffer); + _glfw.wl.dragOffer = NULL; + _glfw.wl.dragFocus = NULL; + } +} + +static void dataDeviceHandleMotion(void* userData, + struct wl_data_device* device, + uint32_t time, + wl_fixed_t x, + wl_fixed_t y) +{ +} + +static void dataDeviceHandleDrop(void* userData, + struct wl_data_device* device) +{ + if (!_glfw.wl.dragOffer) + return; + + char* string = readDataOfferAsString(_glfw.wl.dragOffer, "text/uri-list"); + if (string) + { + int count; + char** paths = _glfwParseUriList(string, &count); + if (paths) + _glfwInputDrop(_glfw.wl.dragFocus, count, (const char**) paths); + + for (int i = 0; i < count; i++) + _glfw_free(paths[i]); + + _glfw_free(paths); + } + + _glfw_free(string); +} + +static void dataDeviceHandleSelection(void* userData, + struct wl_data_device* device, + struct wl_data_offer* offer) +{ + if (_glfw.wl.selectionOffer) + { + wl_data_offer_destroy(_glfw.wl.selectionOffer); + _glfw.wl.selectionOffer = NULL; + } + + for (unsigned int i = 0; i < _glfw.wl.offerCount; i++) + { + if (_glfw.wl.offers[i].offer == offer) + { + if (_glfw.wl.offers[i].text_plain_utf8) + _glfw.wl.selectionOffer = offer; + else + wl_data_offer_destroy(offer); + + _glfw.wl.offers[i] = _glfw.wl.offers[_glfw.wl.offerCount - 1]; + _glfw.wl.offerCount--; + break; + } + } +} + +const struct wl_data_device_listener dataDeviceListener = +{ + dataDeviceHandleDataOffer, + dataDeviceHandleEnter, + dataDeviceHandleLeave, + dataDeviceHandleMotion, + dataDeviceHandleDrop, + dataDeviceHandleSelection, +}; + +void _glfwAddSeatListenerWayland(struct wl_seat* seat) +{ + wl_seat_add_listener(seat, &seatListener, NULL); +} + +void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device) +{ + wl_data_device_add_listener(device, &dataDeviceListener, NULL); +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -int _glfwPlatformCreateWindow(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig) +GLFWbool _glfwCreateWindowWayland(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig) { - window->wl.transparent = fbconfig->transparent; - - if (!createSurface(window, wndconfig)) + if (!createNativeSurface(window, wndconfig, fbconfig)) return GLFW_FALSE; if (ctxconfig->client != GLFW_NO_API) @@ -804,6 +1806,16 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, if (ctxconfig->source == GLFW_EGL_CONTEXT_API || ctxconfig->source == GLFW_NATIVE_CONTEXT_API) { + window->wl.egl.window = wl_egl_window_create(window->wl.surface, + wndconfig->width, + wndconfig->height); + if (!window->wl.egl.window) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to create EGL window"); + return GLFW_FALSE; + } + if (!_glfwInitEGL()) return GLFW_FALSE; if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) @@ -816,93 +1828,80 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig)) return GLFW_FALSE; } - } - if (wndconfig->title) - window->wl.title = _glfw_strdup(wndconfig->title); - - if (wndconfig->visible) - { - if (!createXdgSurface(window)) + if (!_glfwRefreshContextAttribs(window, ctxconfig)) return GLFW_FALSE; - - window->wl.visible = GLFW_TRUE; } - else + + if (wndconfig->mousePassthrough) + _glfwSetWindowMousePassthroughWayland(window, GLFW_TRUE); + + if (window->monitor || wndconfig->visible) { - window->wl.xdg.surface = NULL; - window->wl.xdg.toplevel = NULL; - window->wl.visible = GLFW_FALSE; + if (!createShellObjects(window)) + return GLFW_FALSE; } - window->wl.currentCursor = NULL; - - window->wl.monitors = _glfw_calloc(1, sizeof(_GLFWmonitor*)); - window->wl.monitorsCount = 0; - window->wl.monitorsSize = 1; - return GLFW_TRUE; } -void _glfwPlatformDestroyWindow(_GLFWwindow* window) +void _glfwDestroyWindowWayland(_GLFWwindow* window) { if (window == _glfw.wl.pointerFocus) - { _glfw.wl.pointerFocus = NULL; - _glfwInputCursorEnter(window, GLFW_FALSE); - } + if (window == _glfw.wl.keyboardFocus) - { _glfw.wl.keyboardFocus = NULL; - _glfwInputWindowFocus(window, GLFW_FALSE); - } if (window->wl.idleInhibitor) zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor); + if (window->wl.relativePointer) + zwp_relative_pointer_v1_destroy(window->wl.relativePointer); + + if (window->wl.lockedPointer) + zwp_locked_pointer_v1_destroy(window->wl.lockedPointer); + + if (window->wl.confinedPointer) + zwp_confined_pointer_v1_destroy(window->wl.confinedPointer); + if (window->context.destroy) window->context.destroy(window); - destroyDecorations(window); - if (window->wl.xdg.decoration) - zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration); + destroyShellObjects(window); if (window->wl.decorations.buffer) wl_buffer_destroy(window->wl.decorations.buffer); - if (window->wl.native) - wl_egl_window_destroy(window->wl.native); - - if (window->wl.xdg.toplevel) - xdg_toplevel_destroy(window->wl.xdg.toplevel); - - if (window->wl.xdg.surface) - xdg_surface_destroy(window->wl.xdg.surface); + if (window->wl.egl.window) + wl_egl_window_destroy(window->wl.egl.window); if (window->wl.surface) wl_surface_destroy(window->wl.surface); _glfw_free(window->wl.title); + _glfw_free(window->wl.appId); _glfw_free(window->wl.monitors); } -void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) +void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title) { - if (window->wl.title) - _glfw_free(window->wl.title); - window->wl.title = _glfw_strdup(title); + char* copy = _glfw_strdup(title); + _glfw_free(window->wl.title); + window->wl.title = copy; + if (window->wl.xdg.toplevel) xdg_toplevel_set_title(window->wl.xdg.toplevel, title); } -void _glfwPlatformSetWindowIcon(_GLFWwindow* window, - int count, const GLFWimage* images) +void _glfwSetWindowIconWayland(_GLFWwindow* window, + int count, const GLFWimage* images) { _glfwInputError(GLFW_FEATURE_UNAVAILABLE, "Wayland: The platform does not support setting the window icon"); } -void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) +void _glfwGetWindowPosWayland(_GLFWwindow* window, int* xpos, int* ypos) { // A Wayland client is not aware of its position, so just warn and leave it // as (0, 0) @@ -911,7 +1910,7 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) "Wayland: The platform does not provide the window position"); } -void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) +void _glfwSetWindowPosWayland(_GLFWwindow* window, int xpos, int ypos) { // A Wayland client can not set its position, so just warn @@ -919,7 +1918,7 @@ void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) "Wayland: The platform does not support setting the window position"); } -void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) +void _glfwGetWindowSizeWayland(_GLFWwindow* window, int* width, int* height) { if (width) *width = window->wl.width; @@ -927,67 +1926,100 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) *height = window->wl.height; } -void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) +void _glfwSetWindowSizeWayland(_GLFWwindow* window, int width, int height) { - window->wl.width = width; - window->wl.height = height; - resizeWindow(window); + if (window->monitor) + { + // Video mode setting is not available on Wayland + } + else + { + window->wl.width = width; + window->wl.height = height; + resizeWindow(window); + } } -void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, - int minwidth, int minheight, - int maxwidth, int maxheight) +void _glfwSetWindowSizeLimitsWayland(_GLFWwindow* window, + int minwidth, int minheight, + int maxwidth, int maxheight) { if (window->wl.xdg.toplevel) { if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE) minwidth = minheight = 0; + else + { + if (window->wl.decorations.top.surface) + { + minwidth += GLFW_BORDER_SIZE * 2; + minheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE; + } + } + if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE) maxwidth = maxheight = 0; + else + { + if (window->wl.decorations.top.surface) + { + maxwidth += GLFW_BORDER_SIZE * 2; + maxheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE; + } + } + xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight); xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight); wl_surface_commit(window->wl.surface); } } -void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, - int numer, int denom) +void _glfwSetWindowAspectRatioWayland(_GLFWwindow* window, int numer, int denom) { - // TODO: find out how to trigger a resize. - // The actual limits are checked in the xdg_toplevel::configure handler. - _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, - "Wayland: Window aspect ratio not yet implemented"); + if (window->wl.maximized || window->wl.fullscreen) + return; + + if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE) + { + const float aspectRatio = (float) window->wl.width / (float) window->wl.height; + const float targetRatio = (float) numer / (float) denom; + if (aspectRatio < targetRatio) + window->wl.height = window->wl.width / targetRatio; + else if (aspectRatio > targetRatio) + window->wl.width = window->wl.height * targetRatio; + + resizeWindow(window); + } } -void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, - int* width, int* height) +void _glfwGetFramebufferSizeWayland(_GLFWwindow* window, int* width, int* height) { - _glfwPlatformGetWindowSize(window, width, height); + _glfwGetWindowSizeWayland(window, width, height); if (width) *width *= window->wl.scale; if (height) *height *= window->wl.scale; } -void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, - int* left, int* top, - int* right, int* bottom) +void _glfwGetWindowFrameSizeWayland(_GLFWwindow* window, + int* left, int* top, + int* right, int* bottom) { - if (window->decorated && !window->monitor && !window->wl.decorations.serverSide) + if (window->decorated && !window->monitor && window->wl.decorations.top.surface) { if (top) - *top = _GLFW_DECORATION_TOP; + *top = GLFW_CAPTION_HEIGHT; if (left) - *left = _GLFW_DECORATION_WIDTH; + *left = GLFW_BORDER_SIZE; if (right) - *right = _GLFW_DECORATION_WIDTH; + *right = GLFW_BORDER_SIZE; if (bottom) - *bottom = _GLFW_DECORATION_WIDTH; + *bottom = GLFW_BORDER_SIZE; } } -void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, - float* xscale, float* yscale) +void _glfwGetWindowContentScaleWayland(_GLFWwindow* window, + float* xscale, float* yscale) { if (xscale) *xscale = (float) window->wl.scale; @@ -995,149 +2027,169 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, *yscale = (float) window->wl.scale; } -void _glfwPlatformIconifyWindow(_GLFWwindow* window) +void _glfwIconifyWindowWayland(_GLFWwindow* window) { if (window->wl.xdg.toplevel) xdg_toplevel_set_minimized(window->wl.xdg.toplevel); } -void _glfwPlatformRestoreWindow(_GLFWwindow* window) +void _glfwRestoreWindowWayland(_GLFWwindow* window) { - if (window->wl.xdg.toplevel) + if (window->monitor) { - if (window->monitor) - xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel); - if (window->wl.maximized) - xdg_toplevel_unset_maximized(window->wl.xdg.toplevel); // There is no way to unset minimized, or even to know if we are // minimized, so there is nothing to do in this case. } - _glfwInputWindowMonitor(window, NULL); - window->wl.maximized = GLFW_FALSE; + else + { + // We assume we are not minimized and act only on maximization + + if (window->wl.maximized) + { + if (window->wl.xdg.toplevel) + xdg_toplevel_unset_maximized(window->wl.xdg.toplevel); + else + window->wl.maximized = GLFW_FALSE; + } + } } -void _glfwPlatformMaximizeWindow(_GLFWwindow* window) +void _glfwMaximizeWindowWayland(_GLFWwindow* window) { if (window->wl.xdg.toplevel) - { xdg_toplevel_set_maximized(window->wl.xdg.toplevel); - } - window->wl.maximized = GLFW_TRUE; + else + window->wl.maximized = GLFW_TRUE; } -void _glfwPlatformShowWindow(_GLFWwindow* window) +void _glfwShowWindowWayland(_GLFWwindow* window) { - if (!window->wl.visible) + if (!window->wl.xdg.toplevel) { - createXdgSurface(window); - window->wl.visible = GLFW_TRUE; + // NOTE: The XDG surface and role are created here so command-line applications + // with off-screen windows do not appear in for example the Unity dock + createShellObjects(window); } } -void _glfwPlatformHideWindow(_GLFWwindow* window) +void _glfwHideWindowWayland(_GLFWwindow* window) { - if (window->wl.xdg.toplevel) + if (window->wl.visible) { - xdg_toplevel_destroy(window->wl.xdg.toplevel); - xdg_surface_destroy(window->wl.xdg.surface); - window->wl.xdg.toplevel = NULL; - window->wl.xdg.surface = NULL; + window->wl.visible = GLFW_FALSE; + destroyShellObjects(window); + + wl_surface_attach(window->wl.surface, NULL, 0, 0); + wl_surface_commit(window->wl.surface); } - window->wl.visible = GLFW_FALSE; } -void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) +void _glfwRequestWindowAttentionWayland(_GLFWwindow* window) { // TODO _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, "Wayland: Window attention request not implemented yet"); } -void _glfwPlatformFocusWindow(_GLFWwindow* window) +void _glfwFocusWindowWayland(_GLFWwindow* window) { _glfwInputError(GLFW_FEATURE_UNAVAILABLE, "Wayland: The platform does not support setting the input focus"); } -void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, - _GLFWmonitor* monitor, - int xpos, int ypos, - int width, int height, - int refreshRate) +void _glfwSetWindowMonitorWayland(_GLFWwindow* window, + _GLFWmonitor* monitor, + int xpos, int ypos, + int width, int height, + int refreshRate) { - if (monitor) + if (window->monitor == monitor) { - setFullscreen(window, monitor, refreshRate); - } - else - { - if (window->wl.xdg.toplevel) - xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel); - setIdleInhibitor(window, GLFW_FALSE); - if (!_glfw.wl.decorationManager) - createDecorations(window); + if (!monitor) + _glfwSetWindowSizeWayland(window, width, height); + + return; } + + if (window->monitor) + releaseMonitor(window); + _glfwInputWindowMonitor(window, monitor); + + if (window->monitor) + acquireMonitor(window); + else + _glfwSetWindowSizeWayland(window, width, height); } -int _glfwPlatformWindowFocused(_GLFWwindow* window) +GLFWbool _glfwWindowFocusedWayland(_GLFWwindow* window) { return _glfw.wl.keyboardFocus == window; } -int _glfwPlatformWindowIconified(_GLFWwindow* window) +GLFWbool _glfwWindowIconifiedWayland(_GLFWwindow* window) { // xdg-shell doesn’t give any way to request whether a surface is // iconified. return GLFW_FALSE; } -int _glfwPlatformWindowVisible(_GLFWwindow* window) +GLFWbool _glfwWindowVisibleWayland(_GLFWwindow* window) { return window->wl.visible; } -int _glfwPlatformWindowMaximized(_GLFWwindow* window) +GLFWbool _glfwWindowMaximizedWayland(_GLFWwindow* window) { return window->wl.maximized; } -int _glfwPlatformWindowHovered(_GLFWwindow* window) +GLFWbool _glfwWindowHoveredWayland(_GLFWwindow* window) { return window->wl.hovered; } -int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) +GLFWbool _glfwFramebufferTransparentWayland(_GLFWwindow* window) { return window->wl.transparent; } -void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowResizableWayland(_GLFWwindow* window, GLFWbool enabled) { // TODO _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, "Wayland: Window attribute setting not implemented yet"); } -void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowDecoratedWayland(_GLFWwindow* window, GLFWbool enabled) { - if (!window->monitor) + if (window->wl.xdg.decoration) + { + uint32_t mode; + + if (enabled) + mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE; + else + mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; + + zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, mode); + } + else { if (enabled) - createDecorations(window); + createFallbackDecorations(window); else - destroyDecorations(window); + destroyFallbackDecorations(window); } } -void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowFloatingWayland(_GLFWwindow* window, GLFWbool enabled) { - // TODO - _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, - "Wayland: Window attribute setting not implemented yet"); + _glfwInputError(GLFW_FEATURE_UNAVAILABLE, + "Wayland: Platform does not support making a window floating"); } -void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowMousePassthroughWayland(_GLFWwindow* window, GLFWbool enabled) { if (enabled) { @@ -1147,51 +2199,52 @@ void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enable } else wl_surface_set_input_region(window->wl.surface, 0); - wl_surface_commit(window->wl.surface); } -float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) +float _glfwGetWindowOpacityWayland(_GLFWwindow* window) { return 1.f; } -void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) +void _glfwSetWindowOpacityWayland(_GLFWwindow* window, float opacity) { _glfwInputError(GLFW_FEATURE_UNAVAILABLE, "Wayland: The platform does not support setting the window opacity"); } -void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled) +void _glfwSetRawMouseMotionWayland(_GLFWwindow* window, GLFWbool enabled) { // This is handled in relativePointerHandleRelativeMotion } -GLFWbool _glfwPlatformRawMouseMotionSupported(void) +GLFWbool _glfwRawMouseMotionSupportedWayland(void) { return GLFW_TRUE; } -void _glfwPlatformPollEvents(void) +void _glfwPollEventsWayland(void) { - handleEvents(0); + double timeout = 0.0; + handleEvents(&timeout); } -void _glfwPlatformWaitEvents(void) +void _glfwWaitEventsWayland(void) { - handleEvents(-1); + handleEvents(NULL); } -void _glfwPlatformWaitEventsTimeout(double timeout) +void _glfwWaitEventsTimeoutWayland(double timeout) { - handleEvents((int) (timeout * 1e3)); + handleEvents(&timeout); } -void _glfwPlatformPostEmptyEvent(void) +void _glfwPostEmptyEventWayland(void) { wl_display_sync(_glfw.wl.display); + flushDisplay(); } -void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) +void _glfwGetCursorPosWayland(_GLFWwindow* window, double* xpos, double* ypos) { if (xpos) *xpos = window->wl.cursorPosX; @@ -1199,40 +2252,80 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) *ypos = window->wl.cursorPosY; } -static GLFWbool isPointerLocked(_GLFWwindow* window); - -void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) +void _glfwSetCursorPosWayland(_GLFWwindow* window, double x, double y) { - if (isPointerLocked(window)) + _glfwInputError(GLFW_FEATURE_UNAVAILABLE, + "Wayland: The platform does not support setting the cursor position"); +} + +void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode) +{ + _glfwSetCursorWayland(window, window->wl.currentCursor); +} + +const char* _glfwGetScancodeNameWayland(int scancode) +{ + if (scancode < 0 || scancode > 255 || + _glfw.wl.keycodes[scancode] == GLFW_KEY_UNKNOWN) { - zwp_locked_pointer_v1_set_cursor_position_hint( - window->wl.pointerLock.lockedPointer, - wl_fixed_from_double(x), wl_fixed_from_double(y)); - wl_surface_commit(window->wl.surface); + _glfwInputError(GLFW_INVALID_VALUE, + "Wayland: Invalid scancode %i", + scancode); + return NULL; } + + const int key = _glfw.wl.keycodes[scancode]; + const xkb_keycode_t keycode = scancode + 8; + const xkb_layout_index_t layout = + xkb_state_key_get_layout(_glfw.wl.xkb.state, keycode); + if (layout == XKB_LAYOUT_INVALID) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to retrieve layout for key name"); + return NULL; + } + + const xkb_keysym_t* keysyms = NULL; + xkb_keymap_key_get_syms_by_level(_glfw.wl.xkb.keymap, + keycode, + layout, + 0, + &keysyms); + if (keysyms == NULL) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to retrieve keysym for key name"); + return NULL; + } + + const uint32_t codepoint = _glfwKeySym2Unicode(keysyms[0]); + if (codepoint == GLFW_INVALID_CODEPOINT) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to retrieve codepoint for key name"); + return NULL; + } + + const size_t count = _glfwEncodeUTF8(_glfw.wl.keynames[key], codepoint); + if (count == 0) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to encode codepoint for key name"); + return NULL; + } + + _glfw.wl.keynames[key][count] = '\0'; + return _glfw.wl.keynames[key]; } -void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) -{ - _glfwPlatformSetCursor(window, window->wl.currentCursor); -} - -const char* _glfwPlatformGetScancodeName(int scancode) -{ - // TODO - _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, - "Wayland: Key names not yet implemented"); - return NULL; -} - -int _glfwPlatformGetKeyScancode(int key) +int _glfwGetKeyScancodeWayland(int key) { return _glfw.wl.scancodes[key]; } -int _glfwPlatformCreateCursor(_GLFWcursor* cursor, - const GLFWimage* image, - int xhot, int yhot) +GLFWbool _glfwCreateCursorWayland(_GLFWcursor* cursor, + const GLFWimage* image, + int xhot, int yhot) { cursor->wl.buffer = createShmBuffer(image); if (!cursor->wl.buffer) @@ -1245,7 +2338,7 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor, return GLFW_TRUE; } -int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) +GLFWbool _glfwCreateStandardCursorWayland(_GLFWcursor* cursor, int shape) { const char* name = NULL; @@ -1327,7 +2420,7 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) cursor->wl.cursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme, name); if (!cursor->wl.cursor) { - _glfwInputError(GLFW_PLATFORM_ERROR, + _glfwInputError(GLFW_CURSOR_UNAVAILABLE, "Wayland: Failed to create standard cursor \"%s\"", name); return GLFW_FALSE; @@ -1346,7 +2439,7 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) return GLFW_TRUE; } -void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) +void _glfwDestroyCursorWayland(_GLFWcursor* cursor) { // If it's a standard cursor we don't need to do anything here if (cursor->wl.cursor) @@ -1356,7 +2449,7 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) wl_buffer_destroy(cursor->wl.buffer); } -static void relativePointerHandleRelativeMotion(void* data, +static void relativePointerHandleRelativeMotion(void* userData, struct zwp_relative_pointer_v1* pointer, uint32_t timeHi, uint32_t timeLo, @@ -1365,7 +2458,7 @@ static void relativePointerHandleRelativeMotion(void* data, wl_fixed_t dxUnaccel, wl_fixed_t dyUnaccel) { - _GLFWwindow* window = data; + _GLFWwindow* window = userData; double xpos = window->virtualCursorPosX; double ypos = window->virtualCursorPosY; @@ -1386,89 +2479,104 @@ static void relativePointerHandleRelativeMotion(void* data, _glfwInputCursorPos(window, xpos, ypos); } -static const struct zwp_relative_pointer_v1_listener relativePointerListener = { +static const struct zwp_relative_pointer_v1_listener relativePointerListener = +{ relativePointerHandleRelativeMotion }; -static void lockedPointerHandleLocked(void* data, +static void lockedPointerHandleLocked(void* userData, struct zwp_locked_pointer_v1* lockedPointer) { } -static void unlockPointer(_GLFWwindow* window) -{ - struct zwp_relative_pointer_v1* relativePointer = - window->wl.pointerLock.relativePointer; - struct zwp_locked_pointer_v1* lockedPointer = - window->wl.pointerLock.lockedPointer; - - zwp_relative_pointer_v1_destroy(relativePointer); - zwp_locked_pointer_v1_destroy(lockedPointer); - - window->wl.pointerLock.relativePointer = NULL; - window->wl.pointerLock.lockedPointer = NULL; -} - -static void lockPointer(_GLFWwindow* window); - -static void lockedPointerHandleUnlocked(void* data, +static void lockedPointerHandleUnlocked(void* userData, struct zwp_locked_pointer_v1* lockedPointer) { } -static const struct zwp_locked_pointer_v1_listener lockedPointerListener = { +static const struct zwp_locked_pointer_v1_listener lockedPointerListener = +{ lockedPointerHandleLocked, lockedPointerHandleUnlocked }; static void lockPointer(_GLFWwindow* window) { - struct zwp_relative_pointer_v1* relativePointer; - struct zwp_locked_pointer_v1* lockedPointer; - if (!_glfw.wl.relativePointerManager) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: no relative pointer manager"); + _glfwInputError(GLFW_FEATURE_UNAVAILABLE, + "Wayland: The compositor does not support pointer locking"); return; } - relativePointer = + window->wl.relativePointer = zwp_relative_pointer_manager_v1_get_relative_pointer( _glfw.wl.relativePointerManager, _glfw.wl.pointer); - zwp_relative_pointer_v1_add_listener(relativePointer, + zwp_relative_pointer_v1_add_listener(window->wl.relativePointer, &relativePointerListener, window); - lockedPointer = + window->wl.lockedPointer = zwp_pointer_constraints_v1_lock_pointer( _glfw.wl.pointerConstraints, window->wl.surface, _glfw.wl.pointer, NULL, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); - zwp_locked_pointer_v1_add_listener(lockedPointer, + zwp_locked_pointer_v1_add_listener(window->wl.lockedPointer, &lockedPointerListener, window); - - window->wl.pointerLock.relativePointer = relativePointer; - window->wl.pointerLock.lockedPointer = lockedPointer; - - wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial, - NULL, 0, 0); } -static GLFWbool isPointerLocked(_GLFWwindow* window) +static void unlockPointer(_GLFWwindow* window) { - return window->wl.pointerLock.lockedPointer != NULL; + zwp_relative_pointer_v1_destroy(window->wl.relativePointer); + window->wl.relativePointer = NULL; + + zwp_locked_pointer_v1_destroy(window->wl.lockedPointer); + window->wl.lockedPointer = NULL; } -void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) +static void confinedPointerHandleConfined(void* userData, + struct zwp_confined_pointer_v1* confinedPointer) { - struct wl_cursor* defaultCursor; - struct wl_cursor* defaultCursorHiDPI = NULL; +} +static void confinedPointerHandleUnconfined(void* userData, + struct zwp_confined_pointer_v1* confinedPointer) +{ +} + +static const struct zwp_confined_pointer_v1_listener confinedPointerListener = +{ + confinedPointerHandleConfined, + confinedPointerHandleUnconfined +}; + +static void confinePointer(_GLFWwindow* window) +{ + window->wl.confinedPointer = + zwp_pointer_constraints_v1_confine_pointer( + _glfw.wl.pointerConstraints, + window->wl.surface, + _glfw.wl.pointer, + NULL, + ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); + + zwp_confined_pointer_v1_add_listener(window->wl.confinedPointer, + &confinedPointerListener, + window); +} + +static void unconfinePointer(_GLFWwindow* window) +{ + zwp_confined_pointer_v1_destroy(window->wl.confinedPointer); + window->wl.confinedPointer = NULL; +} + +void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* cursor) +{ if (!_glfw.wl.pointer) return; @@ -1479,29 +2587,55 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) if (window != _glfw.wl.pointerFocus || window->wl.decorations.focus != mainWindow) return; - // Unlock possible pointer lock if no longer disabled. - if (window->cursorMode != GLFW_CURSOR_DISABLED && isPointerLocked(window)) - unlockPointer(window); + // Update pointer lock to match cursor mode + if (window->cursorMode == GLFW_CURSOR_DISABLED) + { + if (window->wl.confinedPointer) + unconfinePointer(window); + if (!window->wl.lockedPointer) + lockPointer(window); + } + else if (window->cursorMode == GLFW_CURSOR_CAPTURED) + { + if (window->wl.lockedPointer) + unlockPointer(window); + if (!window->wl.confinedPointer) + confinePointer(window); + } + else if (window->cursorMode == GLFW_CURSOR_NORMAL || + window->cursorMode == GLFW_CURSOR_HIDDEN) + { + if (window->wl.lockedPointer) + unlockPointer(window); + else if (window->wl.confinedPointer) + unconfinePointer(window); + } - if (window->cursorMode == GLFW_CURSOR_NORMAL) + if (window->cursorMode == GLFW_CURSOR_NORMAL || + window->cursorMode == GLFW_CURSOR_CAPTURED) { if (cursor) setCursorImage(window, &cursor->wl); else { - defaultCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme, - "left_ptr"); + struct wl_cursor* defaultCursor = + wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme, "left_ptr"); if (!defaultCursor) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Standard cursor not found"); return; } + + struct wl_cursor* defaultCursorHiDPI = NULL; if (_glfw.wl.cursorThemeHiDPI) + { defaultCursorHiDPI = - wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI, - "left_ptr"); - _GLFWcursorWayland cursorWayland = { + wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI, "left_ptr"); + } + + _GLFWcursorWayland cursorWayland = + { defaultCursor, defaultCursorHiDPI, NULL, @@ -1509,25 +2643,22 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) 0, 0, 0 }; + setCursorImage(window, &cursorWayland); } } - else if (window->cursorMode == GLFW_CURSOR_DISABLED) - { - if (!isPointerLocked(window)) - lockPointer(window); - } - else if (window->cursorMode == GLFW_CURSOR_HIDDEN) + else if (window->cursorMode == GLFW_CURSOR_HIDDEN || + window->cursorMode == GLFW_CURSOR_DISABLED) { wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial, NULL, 0, 0); } } -static void dataSourceHandleTarget(void* data, - struct wl_data_source* dataSource, +static void dataSourceHandleTarget(void* userData, + struct wl_data_source* source, const char* mimeType) { - if (_glfw.wl.dataSource != dataSource) + if (_glfw.wl.selectionSource != source) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Unknown clipboard data source"); @@ -1535,200 +2666,115 @@ static void dataSourceHandleTarget(void* data, } } -static void dataSourceHandleSend(void* data, - struct wl_data_source* dataSource, +static void dataSourceHandleSend(void* userData, + struct wl_data_source* source, const char* mimeType, int fd) { - const char* string = _glfw.wl.clipboardSendString; - size_t len = _glfw.wl.clipboardSendSize; - int ret; - - if (_glfw.wl.dataSource != dataSource) + // Ignore it if this is an outdated or invalid request + if (_glfw.wl.selectionSource != source || + strcmp(mimeType, "text/plain;charset=utf-8") != 0) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Unknown clipboard data source"); - return; - } - - if (!string) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Copy requested from an invalid string"); - return; - } - - if (strcmp(mimeType, "text/plain;charset=utf-8") != 0) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Wrong MIME type asked from clipboard"); close(fd); return; } - while (len > 0) + char* string = _glfw.wl.clipboardString; + size_t length = strlen(string); + + while (length > 0) { - ret = write(fd, string, len); - if (ret == -1 && errno == EINTR) - continue; - if (ret == -1) + const ssize_t result = write(fd, string, length); + if (result == -1) { - // TODO: also report errno maybe. + if (errno == EINTR) + continue; + _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Error while writing the clipboard"); - close(fd); - return; + "Wayland: Error while writing the clipboard: %s", + strerror(errno)); + break; } - len -= ret; + + length -= result; + string += result; } + close(fd); } -static void dataSourceHandleCancelled(void* data, - struct wl_data_source* dataSource) +static void dataSourceHandleCancelled(void* userData, + struct wl_data_source* source) { - wl_data_source_destroy(dataSource); + wl_data_source_destroy(source); - if (_glfw.wl.dataSource != dataSource) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Unknown clipboard data source"); + if (_glfw.wl.selectionSource != source) return; - } - _glfw.wl.dataSource = NULL; + _glfw.wl.selectionSource = NULL; } -static const struct wl_data_source_listener dataSourceListener = { +static const struct wl_data_source_listener dataSourceListener = +{ dataSourceHandleTarget, dataSourceHandleSend, dataSourceHandleCancelled, }; -void _glfwPlatformSetClipboardString(const char* string) +void _glfwSetClipboardStringWayland(const char* string) { - if (_glfw.wl.dataSource) + if (_glfw.wl.selectionSource) { - wl_data_source_destroy(_glfw.wl.dataSource); - _glfw.wl.dataSource = NULL; + wl_data_source_destroy(_glfw.wl.selectionSource); + _glfw.wl.selectionSource = NULL; } - if (_glfw.wl.clipboardSendString) + char* copy = _glfw_strdup(string); + if (!copy) { - _glfw_free(_glfw.wl.clipboardSendString); - _glfw.wl.clipboardSendString = NULL; - } - - _glfw.wl.clipboardSendString = _glfw_strdup(string); - if (!_glfw.wl.clipboardSendString) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Impossible to allocate clipboard string"); + _glfwInputError(GLFW_OUT_OF_MEMORY, NULL); return; } - _glfw.wl.clipboardSendSize = strlen(string); - _glfw.wl.dataSource = + + _glfw_free(_glfw.wl.clipboardString); + _glfw.wl.clipboardString = copy; + + _glfw.wl.selectionSource = wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager); - if (!_glfw.wl.dataSource) + if (!_glfw.wl.selectionSource) { _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Impossible to create clipboard source"); - _glfw_free(_glfw.wl.clipboardSendString); + "Wayland: Failed to create clipboard data source"); return; } - wl_data_source_add_listener(_glfw.wl.dataSource, + wl_data_source_add_listener(_glfw.wl.selectionSource, &dataSourceListener, NULL); - wl_data_source_offer(_glfw.wl.dataSource, "text/plain;charset=utf-8"); + wl_data_source_offer(_glfw.wl.selectionSource, "text/plain;charset=utf-8"); wl_data_device_set_selection(_glfw.wl.dataDevice, - _glfw.wl.dataSource, + _glfw.wl.selectionSource, _glfw.wl.serial); } -static GLFWbool growClipboardString(void) +const char* _glfwGetClipboardStringWayland(void) { - char* clipboard = _glfw.wl.clipboardString; - - clipboard = _glfw_realloc(clipboard, _glfw.wl.clipboardSize * 2); - if (!clipboard) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Impossible to grow clipboard string"); - return GLFW_FALSE; - } - _glfw.wl.clipboardString = clipboard; - _glfw.wl.clipboardSize = _glfw.wl.clipboardSize * 2; - return GLFW_TRUE; -} - -const char* _glfwPlatformGetClipboardString(void) -{ - int fds[2]; - int ret; - size_t len = 0; - - if (!_glfw.wl.dataOffer) + if (!_glfw.wl.selectionOffer) { _glfwInputError(GLFW_FORMAT_UNAVAILABLE, - "No clipboard data has been sent yet"); + "Wayland: No clipboard data available"); return NULL; } - ret = pipe2(fds, O_CLOEXEC); - if (ret < 0) - { - // TODO: also report errno maybe? - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Impossible to create clipboard pipe fds"); - return NULL; - } + if (_glfw.wl.selectionSource) + return _glfw.wl.clipboardString; - wl_data_offer_receive(_glfw.wl.dataOffer, "text/plain;charset=utf-8", fds[1]); - close(fds[1]); - - // XXX: this is a huge hack, this function shouldn’t be synchronous! - handleEvents(-1); - - while (1) - { - // Grow the clipboard if we need to paste something bigger, there is no - // shrink operation yet. - if (len + 4096 > _glfw.wl.clipboardSize) - { - if (!growClipboardString()) - { - close(fds[0]); - return NULL; - } - } - - // Then read from the fd to the clipboard, handling all known errors. - ret = read(fds[0], _glfw.wl.clipboardString + len, 4096); - if (ret == 0) - break; - if (ret == -1 && errno == EINTR) - continue; - if (ret == -1) - { - // TODO: also report errno maybe. - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Impossible to read from clipboard fd"); - close(fds[0]); - return NULL; - } - len += ret; - } - close(fds[0]); - if (len + 1 > _glfw.wl.clipboardSize) - { - if (!growClipboardString()) - return NULL; - } - _glfw.wl.clipboardString[len] = '\0'; + _glfw_free(_glfw.wl.clipboardString); + _glfw.wl.clipboardString = + readDataOfferAsString(_glfw.wl.selectionOffer, "text/plain;charset=utf-8"); return _glfw.wl.clipboardString; } -EGLenum _glfwPlatformGetEGLPlatform(EGLint** attribs) +EGLenum _glfwGetEGLPlatformWayland(EGLint** attribs) { if (_glfw.egl.EXT_platform_base && _glfw.egl.EXT_platform_wayland) return EGL_PLATFORM_WAYLAND_EXT; @@ -1736,17 +2782,17 @@ EGLenum _glfwPlatformGetEGLPlatform(EGLint** attribs) return 0; } -EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void) +EGLNativeDisplayType _glfwGetEGLNativeDisplayWayland(void) { return _glfw.wl.display; } -EGLNativeWindowType _glfwPlatformGetEGLNativeWindow(_GLFWwindow* window) +EGLNativeWindowType _glfwGetEGLNativeWindowWayland(_GLFWwindow* window) { - return window->wl.native; + return window->wl.egl.window; } -void _glfwPlatformGetRequiredInstanceExtensions(char** extensions) +void _glfwGetRequiredInstanceExtensionsWayland(char** extensions) { if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_wayland_surface) return; @@ -1755,9 +2801,9 @@ void _glfwPlatformGetRequiredInstanceExtensions(char** extensions) extensions[1] = "VK_KHR_wayland_surface"; } -int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, - VkPhysicalDevice device, - uint32_t queuefamily) +GLFWbool _glfwGetPhysicalDevicePresentationSupportWayland(VkInstance instance, + VkPhysicalDevice device, + uint32_t queuefamily) { PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR = @@ -1775,10 +2821,10 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, _glfw.wl.display); } -VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, - _GLFWwindow* window, - const VkAllocationCallbacks* allocator, - VkSurfaceKHR* surface) +VkResult _glfwCreateWindowSurfaceWayland(VkInstance instance, + _GLFWwindow* window, + const VkAllocationCallbacks* allocator, + VkSurfaceKHR* surface) { VkResult err; VkWaylandSurfaceCreateInfoKHR sci; @@ -1817,6 +2863,14 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, GLFWAPI struct wl_display* glfwGetWaylandDisplay(void) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + + if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND) + { + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, + "Wayland: Platform not initialized"); + return NULL; + } + return _glfw.wl.display; } @@ -1824,6 +2878,16 @@ GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + + if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND) + { + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, + "Wayland: Platform not initialized"); + return NULL; + } + return window->wl.surface; } +#endif // _GLFW_WAYLAND + diff --git a/src/x11_init.c b/src/x11_init.c index 5a5154cc..1c69c0f6 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -29,12 +29,17 @@ #include "internal.h" +#if defined(_GLFW_X11) + #include #include #include #include #include #include +#include +#include +#include // Translate the X11 KeySyms for a key to a GLFW key code @@ -209,7 +214,7 @@ static int translateKeySyms(const KeySym* keysyms, int width) // static void createKeyTables(void) { - int scancode, scancodeMin, scancodeMax; + int scancodeMin, scancodeMax; memset(_glfw.x11.keycodes, -1, sizeof(_glfw.x11.keycodes)); memset(_glfw.x11.scancodes, -1, sizeof(_glfw.x11.scancodes)); @@ -355,7 +360,7 @@ static void createKeyTables(void) }; // Find the X11 key code -> GLFW key code mapping - for (scancode = scancodeMin; scancode <= scancodeMax; scancode++) + for (int scancode = scancodeMin; scancode <= scancodeMax; scancode++) { int key = GLFW_KEY_UNKNOWN; @@ -414,7 +419,7 @@ static void createKeyTables(void) scancodeMax - scancodeMin + 1, &width); - for (scancode = scancodeMin; scancode <= scancodeMax; scancode++) + for (int scancode = scancodeMin; scancode <= scancodeMax; scancode++) { // Translate the un-translated key codes using traditional X11 KeySym // lookups @@ -601,17 +606,21 @@ static void detectEWMH(void) // static GLFWbool initExtensions(void) { - _glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1"); +#if defined(__OpenBSD__) || defined(__NetBSD__) + _glfw.x11.vidmode.handle = _glfwPlatformLoadModule("libXxf86vm.so"); +#else + _glfw.x11.vidmode.handle = _glfwPlatformLoadModule("libXxf86vm.so.1"); +#endif if (_glfw.x11.vidmode.handle) { _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension) - _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension"); + _glfwPlatformGetModuleSymbol(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension"); _glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp) - _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp"); + _glfwPlatformGetModuleSymbol(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp"); _glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp) - _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp"); + _glfwPlatformGetModuleSymbol(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp"); _glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize) - _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize"); + _glfwPlatformGetModuleSymbol(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize"); _glfw.x11.vidmode.available = XF86VidModeQueryExtension(_glfw.x11.display, @@ -620,16 +629,18 @@ static GLFWbool initExtensions(void) } #if defined(__CYGWIN__) - _glfw.x11.xi.handle = _glfw_dlopen("libXi-6.so"); + _glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi-6.so"); +#elif defined(__OpenBSD__) || defined(__NetBSD__) + _glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so"); #else - _glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6"); + _glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so.6"); #endif if (_glfw.x11.xi.handle) { _glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion) - _glfw_dlsym(_glfw.x11.xi.handle, "XIQueryVersion"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xi.handle, "XIQueryVersion"); _glfw.x11.xi.SelectEvents = (PFN_XISelectEvents) - _glfw_dlsym(_glfw.x11.xi.handle, "XISelectEvents"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xi.handle, "XISelectEvents"); if (XQueryExtension(_glfw.x11.display, "XInputExtension", @@ -650,48 +661,50 @@ static GLFWbool initExtensions(void) } #if defined(__CYGWIN__) - _glfw.x11.randr.handle = _glfw_dlopen("libXrandr-2.so"); + _glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr-2.so"); +#elif defined(__OpenBSD__) || defined(__NetBSD__) + _glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so"); #else - _glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2"); + _glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so.2"); #endif if (_glfw.x11.randr.handle) { _glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRAllocGamma"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRAllocGamma"); _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRFreeGamma"); _glfw.x11.randr.FreeCrtcInfo = (PFN_XRRFreeCrtcInfo) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRFreeCrtcInfo"); _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRFreeGamma"); _glfw.x11.randr.FreeOutputInfo = (PFN_XRRFreeOutputInfo) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRFreeOutputInfo"); _glfw.x11.randr.FreeScreenResources = (PFN_XRRFreeScreenResources) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRFreeScreenResources"); _glfw.x11.randr.GetCrtcGamma = (PFN_XRRGetCrtcGamma) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRGetCrtcGamma"); _glfw.x11.randr.GetCrtcGammaSize = (PFN_XRRGetCrtcGammaSize) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize"); _glfw.x11.randr.GetCrtcInfo = (PFN_XRRGetCrtcInfo) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRGetCrtcInfo"); _glfw.x11.randr.GetOutputInfo = (PFN_XRRGetOutputInfo) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRGetOutputInfo"); _glfw.x11.randr.GetOutputPrimary = (PFN_XRRGetOutputPrimary) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRGetOutputPrimary"); _glfw.x11.randr.GetScreenResourcesCurrent = (PFN_XRRGetScreenResourcesCurrent) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent"); _glfw.x11.randr.QueryExtension = (PFN_XRRQueryExtension) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryExtension"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRQueryExtension"); _glfw.x11.randr.QueryVersion = (PFN_XRRQueryVersion) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryVersion"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRQueryVersion"); _glfw.x11.randr.SelectInput = (PFN_XRRSelectInput) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRSelectInput"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRSelectInput"); _glfw.x11.randr.SetCrtcConfig = (PFN_XRRSetCrtcConfig) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRSetCrtcConfig"); _glfw.x11.randr.SetCrtcGamma = (PFN_XRRSetCrtcGamma) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRSetCrtcGamma"); _glfw.x11.randr.UpdateConfiguration = (PFN_XRRUpdateConfiguration) - _glfw_dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration"); + _glfwPlatformGetModuleSymbol(_glfw.x11.randr.handle, "XRRUpdateConfiguration"); if (XRRQueryExtension(_glfw.x11.display, &_glfw.x11.randr.eventBase, @@ -742,39 +755,43 @@ static GLFWbool initExtensions(void) } #if defined(__CYGWIN__) - _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor-1.so"); + _glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor-1.so"); +#elif defined(__OpenBSD__) || defined(__NetBSD__) + _glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so"); #else - _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1"); + _glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so.1"); #endif if (_glfw.x11.xcursor.handle) { _glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate) - _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xcursor.handle, "XcursorImageCreate"); _glfw.x11.xcursor.ImageDestroy = (PFN_XcursorImageDestroy) - _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xcursor.handle, "XcursorImageDestroy"); _glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor) - _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor"); _glfw.x11.xcursor.GetTheme = (PFN_XcursorGetTheme) - _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorGetTheme"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xcursor.handle, "XcursorGetTheme"); _glfw.x11.xcursor.GetDefaultSize = (PFN_XcursorGetDefaultSize) - _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorGetDefaultSize"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xcursor.handle, "XcursorGetDefaultSize"); _glfw.x11.xcursor.LibraryLoadImage = (PFN_XcursorLibraryLoadImage) - _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorLibraryLoadImage"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xcursor.handle, "XcursorLibraryLoadImage"); } #if defined(__CYGWIN__) - _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama-1.so"); + _glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama-1.so"); +#elif defined(__OpenBSD__) || defined(__NetBSD__) + _glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so"); #else - _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1"); + _glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so.1"); #endif if (_glfw.x11.xinerama.handle) { _glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive) - _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xinerama.handle, "XineramaIsActive"); _glfw.x11.xinerama.QueryExtension = (PFN_XineramaQueryExtension) - _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xinerama.handle, "XineramaQueryExtension"); _glfw.x11.xinerama.QueryScreens = (PFN_XineramaQueryScreens) - _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xinerama.handle, "XineramaQueryScreens"); if (XineramaQueryExtension(_glfw.x11.display, &_glfw.x11.xinerama.major, @@ -816,31 +833,35 @@ static GLFWbool initExtensions(void) if (_glfw.hints.init.x11.xcbVulkanSurface) { #if defined(__CYGWIN__) - _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb-1.so"); + _glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb-1.so"); +#elif defined(__OpenBSD__) || defined(__NetBSD__) + _glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so"); #else - _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1"); + _glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so.1"); #endif } if (_glfw.x11.x11xcb.handle) { _glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection) - _glfw_dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection"); + _glfwPlatformGetModuleSymbol(_glfw.x11.x11xcb.handle, "XGetXCBConnection"); } #if defined(__CYGWIN__) - _glfw.x11.xrender.handle = _glfw_dlopen("libXrender-1.so"); + _glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender-1.so"); +#elif defined(__OpenBSD__) || defined(__NetBSD__) + _glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so"); #else - _glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1"); + _glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so.1"); #endif if (_glfw.x11.xrender.handle) { _glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension) - _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xrender.handle, "XRenderQueryExtension"); _glfw.x11.xrender.QueryVersion = (PFN_XRenderQueryVersion) - _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xrender.handle, "XRenderQueryVersion"); _glfw.x11.xrender.FindVisualFormat = (PFN_XRenderFindVisualFormat) - _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xrender.handle, "XRenderFindVisualFormat"); if (XRenderQueryExtension(_glfw.x11.display, &_glfw.x11.xrender.errorBase, @@ -856,20 +877,22 @@ static GLFWbool initExtensions(void) } #if defined(__CYGWIN__) - _glfw.x11.xshape.handle = _glfw_dlopen("libXext-6.so"); + _glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext-6.so"); +#elif defined(__OpenBSD__) || defined(__NetBSD__) + _glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so"); #else - _glfw.x11.xshape.handle = _glfw_dlopen("libXext.so.6"); + _glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so.6"); #endif if (_glfw.x11.xshape.handle) { _glfw.x11.xshape.QueryExtension = (PFN_XShapeQueryExtension) - _glfw_dlsym(_glfw.x11.xshape.handle, "XShapeQueryExtension"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xshape.handle, "XShapeQueryExtension"); _glfw.x11.xshape.ShapeCombineRegion = (PFN_XShapeCombineRegion) - _glfw_dlsym(_glfw.x11.xshape.handle, "XShapeCombineRegion"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xshape.handle, "XShapeCombineRegion"); _glfw.x11.xshape.QueryVersion = (PFN_XShapeQueryVersion) - _glfw_dlsym(_glfw.x11.xshape.handle, "XShapeQueryVersion"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xshape.handle, "XShapeQueryVersion"); _glfw.x11.xshape.ShapeCombineMask = (PFN_XShapeCombineMask) - _glfw_dlsym(_glfw.x11.xshape.handle, "XShapeCombineMask"); + _glfwPlatformGetModuleSymbol(_glfw.x11.xshape.handle, "XShapeCombineMask"); if (XShapeQueryExtension(_glfw.x11.display, &_glfw.x11.xshape.errorBase, @@ -1007,7 +1030,7 @@ static Cursor createHiddenCursor(void) { unsigned char pixels[16 * 16 * 4] = { 0 }; GLFWimage image = { 16, 16, pixels }; - return _glfwCreateCursorX11(&image, 0, 0); + return _glfwCreateNativeCursorX11(&image, 0, 0); } // Create a helper window for IPC @@ -1024,6 +1047,37 @@ static Window createHelperWindow(void) CWEventMask, &wa); } +// Create the pipe for empty events without assumuing the OS has pipe2(2) +// +static GLFWbool createEmptyEventPipe(void) +{ + if (pipe(_glfw.x11.emptyEventPipe) != 0) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "X11: Failed to create empty event pipe: %s", + strerror(errno)); + return GLFW_FALSE; + } + + for (int i = 0; i < 2; i++) + { + const int sf = fcntl(_glfw.x11.emptyEventPipe[i], F_GETFL, 0); + const int df = fcntl(_glfw.x11.emptyEventPipe[i], F_GETFD, 0); + + if (sf == -1 || df == -1 || + fcntl(_glfw.x11.emptyEventPipe[i], F_SETFL, sf | O_NONBLOCK) == -1 || + fcntl(_glfw.x11.emptyEventPipe[i], F_SETFD, df | FD_CLOEXEC) == -1) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "X11: Failed to set flags for empty event pipe: %s", + strerror(errno)); + return GLFW_FALSE; + } + } + + return GLFW_TRUE; +} + // X error handler // static int errorHandler(Display *display, XErrorEvent* event) @@ -1044,8 +1098,9 @@ static int errorHandler(Display *display, XErrorEvent* event) // void _glfwGrabErrorHandlerX11(void) { + assert(_glfw.x11.errorHandler == NULL); _glfw.x11.errorCode = Success; - XSetErrorHandler(errorHandler); + _glfw.x11.errorHandler = XSetErrorHandler(errorHandler); } // Clears the X error handler callback @@ -1054,7 +1109,8 @@ void _glfwReleaseErrorHandlerX11(void) { // Synchronize to make sure all commands are processed XSync(_glfw.x11.display, False); - XSetErrorHandler(NULL); + XSetErrorHandler(_glfw.x11.errorHandler); + _glfw.x11.errorHandler = NULL; } // Reports the specified error, appending information about the last X error @@ -1070,9 +1126,8 @@ void _glfwInputErrorX11(int error, const char* message) // Creates a native cursor object from the specified image and hotspot // -Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot) +Cursor _glfwCreateNativeCursorX11(const GLFWimage* image, int xhot, int yhot) { - int i; Cursor cursor; if (!_glfw.x11.xcursor.handle) @@ -1088,7 +1143,7 @@ Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot) unsigned char* source = (unsigned char*) image->pixels; XcursorPixel* target = native->pixels; - for (i = 0; i < image->width * image->height; i++, target++, source += 4) + for (int i = 0; i < image->width * image->height; i++, target++, source += 4) { unsigned int alpha = source[3]; @@ -1109,8 +1164,92 @@ Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot) ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -int _glfwPlatformInit(void) +GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform) { + const _GLFWplatform x11 = + { + GLFW_PLATFORM_X11, + _glfwInitX11, + _glfwTerminateX11, + _glfwGetCursorPosX11, + _glfwSetCursorPosX11, + _glfwSetCursorModeX11, + _glfwSetRawMouseMotionX11, + _glfwRawMouseMotionSupportedX11, + _glfwCreateCursorX11, + _glfwCreateStandardCursorX11, + _glfwDestroyCursorX11, + _glfwSetCursorX11, + _glfwGetScancodeNameX11, + _glfwGetKeyScancodeX11, + _glfwSetClipboardStringX11, + _glfwGetClipboardStringX11, +#if defined(_GLFW_LINUX_JOYSTICK) + _glfwInitJoysticksLinux, + _glfwTerminateJoysticksLinux, + _glfwPollJoystickLinux, + _glfwGetMappingNameLinux, + _glfwUpdateGamepadGUIDLinux, +#else + _glfwInitJoysticksNull, + _glfwTerminateJoysticksNull, + _glfwPollJoystickNull, + _glfwGetMappingNameNull, + _glfwUpdateGamepadGUIDNull, +#endif + _glfwFreeMonitorX11, + _glfwGetMonitorPosX11, + _glfwGetMonitorContentScaleX11, + _glfwGetMonitorWorkareaX11, + _glfwGetVideoModesX11, + _glfwGetVideoModeX11, + _glfwGetGammaRampX11, + _glfwSetGammaRampX11, + _glfwCreateWindowX11, + _glfwDestroyWindowX11, + _glfwSetWindowTitleX11, + _glfwSetWindowIconX11, + _glfwGetWindowPosX11, + _glfwSetWindowPosX11, + _glfwGetWindowSizeX11, + _glfwSetWindowSizeX11, + _glfwSetWindowSizeLimitsX11, + _glfwSetWindowAspectRatioX11, + _glfwGetFramebufferSizeX11, + _glfwGetWindowFrameSizeX11, + _glfwGetWindowContentScaleX11, + _glfwIconifyWindowX11, + _glfwRestoreWindowX11, + _glfwMaximizeWindowX11, + _glfwShowWindowX11, + _glfwHideWindowX11, + _glfwRequestWindowAttentionX11, + _glfwFocusWindowX11, + _glfwSetWindowMonitorX11, + _glfwWindowFocusedX11, + _glfwWindowIconifiedX11, + _glfwWindowVisibleX11, + _glfwWindowMaximizedX11, + _glfwWindowHoveredX11, + _glfwFramebufferTransparentX11, + _glfwGetWindowOpacityX11, + _glfwSetWindowResizableX11, + _glfwSetWindowDecoratedX11, + _glfwSetWindowFloatingX11, + _glfwSetWindowOpacityX11, + _glfwSetWindowMousePassthroughX11, + _glfwPollEventsX11, + _glfwWaitEventsX11, + _glfwWaitEventsTimeoutX11, + _glfwPostEmptyEventX11, + _glfwGetEGLPlatformX11, + _glfwGetEGLNativeDisplayX11, + _glfwGetEGLNativeWindowX11, + _glfwGetRequiredInstanceExtensionsX11, + _glfwGetPhysicalDevicePresentationSupportX11, + _glfwCreateWindowSurfaceX11, + }; + // HACK: If the application has left the locale as "C" then both wide // character text input and explicit UTF-8 input via XIM will break // This sets the CTYPE part of the current locale from the environment @@ -1119,251 +1258,280 @@ int _glfwPlatformInit(void) setlocale(LC_CTYPE, ""); #if defined(__CYGWIN__) - _glfw.x11.xlib.handle = _glfw_dlopen("libX11-6.so"); + void* module = _glfwPlatformLoadModule("libX11-6.so"); +#elif defined(__OpenBSD__) || defined(__NetBSD__) + void* module = _glfwPlatformLoadModule("libX11.so"); #else - _glfw.x11.xlib.handle = _glfw_dlopen("libX11.so.6"); + void* module = _glfwPlatformLoadModule("libX11.so.6"); #endif - if (!_glfw.x11.xlib.handle) + if (!module) { - _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to load Xlib"); + if (platformID == GLFW_PLATFORM_X11) + _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to load Xlib"); + return GLFW_FALSE; } - _glfw.x11.xlib.AllocClassHint = (PFN_XAllocClassHint) - _glfw_dlsym(_glfw.x11.xlib.handle, "XAllocClassHint"); - _glfw.x11.xlib.AllocSizeHints = (PFN_XAllocSizeHints) - _glfw_dlsym(_glfw.x11.xlib.handle, "XAllocSizeHints"); - _glfw.x11.xlib.AllocWMHints = (PFN_XAllocWMHints) - _glfw_dlsym(_glfw.x11.xlib.handle, "XAllocWMHints"); - _glfw.x11.xlib.ChangeProperty = (PFN_XChangeProperty) - _glfw_dlsym(_glfw.x11.xlib.handle, "XChangeProperty"); - _glfw.x11.xlib.ChangeWindowAttributes = (PFN_XChangeWindowAttributes) - _glfw_dlsym(_glfw.x11.xlib.handle, "XChangeWindowAttributes"); - _glfw.x11.xlib.CheckIfEvent = (PFN_XCheckIfEvent) - _glfw_dlsym(_glfw.x11.xlib.handle, "XCheckIfEvent"); - _glfw.x11.xlib.CheckTypedWindowEvent = (PFN_XCheckTypedWindowEvent) - _glfw_dlsym(_glfw.x11.xlib.handle, "XCheckTypedWindowEvent"); - _glfw.x11.xlib.CloseDisplay = (PFN_XCloseDisplay) - _glfw_dlsym(_glfw.x11.xlib.handle, "XCloseDisplay"); - _glfw.x11.xlib.CloseIM = (PFN_XCloseIM) - _glfw_dlsym(_glfw.x11.xlib.handle, "XCloseIM"); - _glfw.x11.xlib.ConvertSelection = (PFN_XConvertSelection) - _glfw_dlsym(_glfw.x11.xlib.handle, "XConvertSelection"); - _glfw.x11.xlib.CreateColormap = (PFN_XCreateColormap) - _glfw_dlsym(_glfw.x11.xlib.handle, "XCreateColormap"); - _glfw.x11.xlib.CreateFontCursor = (PFN_XCreateFontCursor) - _glfw_dlsym(_glfw.x11.xlib.handle, "XCreateFontCursor"); - _glfw.x11.xlib.CreateIC = (PFN_XCreateIC) - _glfw_dlsym(_glfw.x11.xlib.handle, "XCreateIC"); - _glfw.x11.xlib.CreateRegion = (PFN_XCreateRegion) - _glfw_dlsym(_glfw.x11.xlib.handle, "XCreateRegion"); - _glfw.x11.xlib.CreateWindow = (PFN_XCreateWindow) - _glfw_dlsym(_glfw.x11.xlib.handle, "XCreateWindow"); - _glfw.x11.xlib.DefineCursor = (PFN_XDefineCursor) - _glfw_dlsym(_glfw.x11.xlib.handle, "XDefineCursor"); - _glfw.x11.xlib.DeleteContext = (PFN_XDeleteContext) - _glfw_dlsym(_glfw.x11.xlib.handle, "XDeleteContext"); - _glfw.x11.xlib.DeleteProperty = (PFN_XDeleteProperty) - _glfw_dlsym(_glfw.x11.xlib.handle, "XDeleteProperty"); - _glfw.x11.xlib.DestroyIC = (PFN_XDestroyIC) - _glfw_dlsym(_glfw.x11.xlib.handle, "XDestroyIC"); - _glfw.x11.xlib.DestroyRegion = (PFN_XDestroyRegion) - _glfw_dlsym(_glfw.x11.xlib.handle, "XDestroyRegion"); - _glfw.x11.xlib.DestroyWindow = (PFN_XDestroyWindow) - _glfw_dlsym(_glfw.x11.xlib.handle, "XDestroyWindow"); - _glfw.x11.xlib.DisplayKeycodes = (PFN_XDisplayKeycodes) - _glfw_dlsym(_glfw.x11.xlib.handle, "XDisplayKeycodes"); - _glfw.x11.xlib.EventsQueued = (PFN_XEventsQueued) - _glfw_dlsym(_glfw.x11.xlib.handle, "XEventsQueued"); - _glfw.x11.xlib.FilterEvent = (PFN_XFilterEvent) - _glfw_dlsym(_glfw.x11.xlib.handle, "XFilterEvent"); - _glfw.x11.xlib.FindContext = (PFN_XFindContext) - _glfw_dlsym(_glfw.x11.xlib.handle, "XFindContext"); - _glfw.x11.xlib.Flush = (PFN_XFlush) - _glfw_dlsym(_glfw.x11.xlib.handle, "XFlush"); - _glfw.x11.xlib.Free = (PFN_XFree) - _glfw_dlsym(_glfw.x11.xlib.handle, "XFree"); - _glfw.x11.xlib.FreeColormap = (PFN_XFreeColormap) - _glfw_dlsym(_glfw.x11.xlib.handle, "XFreeColormap"); - _glfw.x11.xlib.FreeCursor = (PFN_XFreeCursor) - _glfw_dlsym(_glfw.x11.xlib.handle, "XFreeCursor"); - _glfw.x11.xlib.FreeEventData = (PFN_XFreeEventData) - _glfw_dlsym(_glfw.x11.xlib.handle, "XFreeEventData"); - _glfw.x11.xlib.GetErrorText = (PFN_XGetErrorText) - _glfw_dlsym(_glfw.x11.xlib.handle, "XGetErrorText"); - _glfw.x11.xlib.GetEventData = (PFN_XGetEventData) - _glfw_dlsym(_glfw.x11.xlib.handle, "XGetEventData"); - _glfw.x11.xlib.GetICValues = (PFN_XGetICValues) - _glfw_dlsym(_glfw.x11.xlib.handle, "XGetICValues"); - _glfw.x11.xlib.GetIMValues = (PFN_XGetIMValues) - _glfw_dlsym(_glfw.x11.xlib.handle, "XGetIMValues"); - _glfw.x11.xlib.GetInputFocus = (PFN_XGetInputFocus) - _glfw_dlsym(_glfw.x11.xlib.handle, "XGetInputFocus"); - _glfw.x11.xlib.GetKeyboardMapping = (PFN_XGetKeyboardMapping) - _glfw_dlsym(_glfw.x11.xlib.handle, "XGetKeyboardMapping"); - _glfw.x11.xlib.GetScreenSaver = (PFN_XGetScreenSaver) - _glfw_dlsym(_glfw.x11.xlib.handle, "XGetScreenSaver"); - _glfw.x11.xlib.GetSelectionOwner = (PFN_XGetSelectionOwner) - _glfw_dlsym(_glfw.x11.xlib.handle, "XGetSelectionOwner"); - _glfw.x11.xlib.GetVisualInfo = (PFN_XGetVisualInfo) - _glfw_dlsym(_glfw.x11.xlib.handle, "XGetVisualInfo"); - _glfw.x11.xlib.GetWMNormalHints = (PFN_XGetWMNormalHints) - _glfw_dlsym(_glfw.x11.xlib.handle, "XGetWMNormalHints"); - _glfw.x11.xlib.GetWindowAttributes = (PFN_XGetWindowAttributes) - _glfw_dlsym(_glfw.x11.xlib.handle, "XGetWindowAttributes"); - _glfw.x11.xlib.GetWindowProperty = (PFN_XGetWindowProperty) - _glfw_dlsym(_glfw.x11.xlib.handle, "XGetWindowProperty"); - _glfw.x11.xlib.GrabPointer = (PFN_XGrabPointer) - _glfw_dlsym(_glfw.x11.xlib.handle, "XGrabPointer"); - _glfw.x11.xlib.IconifyWindow = (PFN_XIconifyWindow) - _glfw_dlsym(_glfw.x11.xlib.handle, "XIconifyWindow"); - _glfw.x11.xlib.InitThreads = (PFN_XInitThreads) - _glfw_dlsym(_glfw.x11.xlib.handle, "XInitThreads"); - _glfw.x11.xlib.InternAtom = (PFN_XInternAtom) - _glfw_dlsym(_glfw.x11.xlib.handle, "XInternAtom"); - _glfw.x11.xlib.LookupString = (PFN_XLookupString) - _glfw_dlsym(_glfw.x11.xlib.handle, "XLookupString"); - _glfw.x11.xlib.MapRaised = (PFN_XMapRaised) - _glfw_dlsym(_glfw.x11.xlib.handle, "XMapRaised"); - _glfw.x11.xlib.MapWindow = (PFN_XMapWindow) - _glfw_dlsym(_glfw.x11.xlib.handle, "XMapWindow"); - _glfw.x11.xlib.MoveResizeWindow = (PFN_XMoveResizeWindow) - _glfw_dlsym(_glfw.x11.xlib.handle, "XMoveResizeWindow"); - _glfw.x11.xlib.MoveWindow = (PFN_XMoveWindow) - _glfw_dlsym(_glfw.x11.xlib.handle, "XMoveWindow"); - _glfw.x11.xlib.NextEvent = (PFN_XNextEvent) - _glfw_dlsym(_glfw.x11.xlib.handle, "XNextEvent"); - _glfw.x11.xlib.OpenDisplay = (PFN_XOpenDisplay) - _glfw_dlsym(_glfw.x11.xlib.handle, "XOpenDisplay"); - _glfw.x11.xlib.OpenIM = (PFN_XOpenIM) - _glfw_dlsym(_glfw.x11.xlib.handle, "XOpenIM"); - _glfw.x11.xlib.PeekEvent = (PFN_XPeekEvent) - _glfw_dlsym(_glfw.x11.xlib.handle, "XPeekEvent"); - _glfw.x11.xlib.Pending = (PFN_XPending) - _glfw_dlsym(_glfw.x11.xlib.handle, "XPending"); - _glfw.x11.xlib.QueryExtension = (PFN_XQueryExtension) - _glfw_dlsym(_glfw.x11.xlib.handle, "XQueryExtension"); - _glfw.x11.xlib.QueryPointer = (PFN_XQueryPointer) - _glfw_dlsym(_glfw.x11.xlib.handle, "XQueryPointer"); - _glfw.x11.xlib.RaiseWindow = (PFN_XRaiseWindow) - _glfw_dlsym(_glfw.x11.xlib.handle, "XRaiseWindow"); - _glfw.x11.xlib.RegisterIMInstantiateCallback = (PFN_XRegisterIMInstantiateCallback) - _glfw_dlsym(_glfw.x11.xlib.handle, "XRegisterIMInstantiateCallback"); - _glfw.x11.xlib.ResizeWindow = (PFN_XResizeWindow) - _glfw_dlsym(_glfw.x11.xlib.handle, "XResizeWindow"); - _glfw.x11.xlib.ResourceManagerString = (PFN_XResourceManagerString) - _glfw_dlsym(_glfw.x11.xlib.handle, "XResourceManagerString"); - _glfw.x11.xlib.SaveContext = (PFN_XSaveContext) - _glfw_dlsym(_glfw.x11.xlib.handle, "XSaveContext"); - _glfw.x11.xlib.SelectInput = (PFN_XSelectInput) - _glfw_dlsym(_glfw.x11.xlib.handle, "XSelectInput"); - _glfw.x11.xlib.SendEvent = (PFN_XSendEvent) - _glfw_dlsym(_glfw.x11.xlib.handle, "XSendEvent"); - _glfw.x11.xlib.SetClassHint = (PFN_XSetClassHint) - _glfw_dlsym(_glfw.x11.xlib.handle, "XSetClassHint"); - _glfw.x11.xlib.SetErrorHandler = (PFN_XSetErrorHandler) - _glfw_dlsym(_glfw.x11.xlib.handle, "XSetErrorHandler"); - _glfw.x11.xlib.SetICFocus = (PFN_XSetICFocus) - _glfw_dlsym(_glfw.x11.xlib.handle, "XSetICFocus"); - _glfw.x11.xlib.SetIMValues = (PFN_XSetIMValues) - _glfw_dlsym(_glfw.x11.xlib.handle, "XSetIMValues"); - _glfw.x11.xlib.SetInputFocus = (PFN_XSetInputFocus) - _glfw_dlsym(_glfw.x11.xlib.handle, "XSetInputFocus"); - _glfw.x11.xlib.SetLocaleModifiers = (PFN_XSetLocaleModifiers) - _glfw_dlsym(_glfw.x11.xlib.handle, "XSetLocaleModifiers"); - _glfw.x11.xlib.SetScreenSaver = (PFN_XSetScreenSaver) - _glfw_dlsym(_glfw.x11.xlib.handle, "XSetScreenSaver"); - _glfw.x11.xlib.SetSelectionOwner = (PFN_XSetSelectionOwner) - _glfw_dlsym(_glfw.x11.xlib.handle, "XSetSelectionOwner"); - _glfw.x11.xlib.SetWMHints = (PFN_XSetWMHints) - _glfw_dlsym(_glfw.x11.xlib.handle, "XSetWMHints"); - _glfw.x11.xlib.SetWMNormalHints = (PFN_XSetWMNormalHints) - _glfw_dlsym(_glfw.x11.xlib.handle, "XSetWMNormalHints"); - _glfw.x11.xlib.SetWMProtocols = (PFN_XSetWMProtocols) - _glfw_dlsym(_glfw.x11.xlib.handle, "XSetWMProtocols"); - _glfw.x11.xlib.SupportsLocale = (PFN_XSupportsLocale) - _glfw_dlsym(_glfw.x11.xlib.handle, "XSupportsLocale"); - _glfw.x11.xlib.Sync = (PFN_XSync) - _glfw_dlsym(_glfw.x11.xlib.handle, "XSync"); - _glfw.x11.xlib.TranslateCoordinates = (PFN_XTranslateCoordinates) - _glfw_dlsym(_glfw.x11.xlib.handle, "XTranslateCoordinates"); - _glfw.x11.xlib.UndefineCursor = (PFN_XUndefineCursor) - _glfw_dlsym(_glfw.x11.xlib.handle, "XUndefineCursor"); - _glfw.x11.xlib.UngrabPointer = (PFN_XUngrabPointer) - _glfw_dlsym(_glfw.x11.xlib.handle, "XUngrabPointer"); - _glfw.x11.xlib.UnmapWindow = (PFN_XUnmapWindow) - _glfw_dlsym(_glfw.x11.xlib.handle, "XUnmapWindow"); - _glfw.x11.xlib.UnsetICFocus = (PFN_XUnsetICFocus) - _glfw_dlsym(_glfw.x11.xlib.handle, "XUnsetICFocus"); - _glfw.x11.xlib.VisualIDFromVisual = (PFN_XVisualIDFromVisual) - _glfw_dlsym(_glfw.x11.xlib.handle, "XVisualIDFromVisual"); - _glfw.x11.xlib.WarpPointer = (PFN_XWarpPointer) - _glfw_dlsym(_glfw.x11.xlib.handle, "XWarpPointer"); - _glfw.x11.xkb.FreeKeyboard = (PFN_XkbFreeKeyboard) - _glfw_dlsym(_glfw.x11.xlib.handle, "XkbFreeKeyboard"); - _glfw.x11.xkb.FreeNames = (PFN_XkbFreeNames) - _glfw_dlsym(_glfw.x11.xlib.handle, "XkbFreeNames"); - _glfw.x11.xkb.GetMap = (PFN_XkbGetMap) - _glfw_dlsym(_glfw.x11.xlib.handle, "XkbGetMap"); - _glfw.x11.xkb.GetNames = (PFN_XkbGetNames) - _glfw_dlsym(_glfw.x11.xlib.handle, "XkbGetNames"); - _glfw.x11.xkb.GetState = (PFN_XkbGetState) - _glfw_dlsym(_glfw.x11.xlib.handle, "XkbGetState"); - _glfw.x11.xkb.KeycodeToKeysym = (PFN_XkbKeycodeToKeysym) - _glfw_dlsym(_glfw.x11.xlib.handle, "XkbKeycodeToKeysym"); - _glfw.x11.xkb.QueryExtension = (PFN_XkbQueryExtension) - _glfw_dlsym(_glfw.x11.xlib.handle, "XkbQueryExtension"); - _glfw.x11.xkb.SelectEventDetails = (PFN_XkbSelectEventDetails) - _glfw_dlsym(_glfw.x11.xlib.handle, "XkbSelectEventDetails"); - _glfw.x11.xkb.SetDetectableAutoRepeat = (PFN_XkbSetDetectableAutoRepeat) - _glfw_dlsym(_glfw.x11.xlib.handle, "XkbSetDetectableAutoRepeat"); - _glfw.x11.xrm.DestroyDatabase = (PFN_XrmDestroyDatabase) - _glfw_dlsym(_glfw.x11.xlib.handle, "XrmDestroyDatabase"); - _glfw.x11.xrm.GetResource = (PFN_XrmGetResource) - _glfw_dlsym(_glfw.x11.xlib.handle, "XrmGetResource"); - _glfw.x11.xrm.GetStringDatabase = (PFN_XrmGetStringDatabase) - _glfw_dlsym(_glfw.x11.xlib.handle, "XrmGetStringDatabase"); - _glfw.x11.xrm.Initialize = (PFN_XrmInitialize) - _glfw_dlsym(_glfw.x11.xlib.handle, "XrmInitialize"); - _glfw.x11.xrm.UniqueQuark = (PFN_XrmUniqueQuark) - _glfw_dlsym(_glfw.x11.xlib.handle, "XrmUniqueQuark"); - _glfw.x11.xlib.UnregisterIMInstantiateCallback = (PFN_XUnregisterIMInstantiateCallback) - _glfw_dlsym(_glfw.x11.xlib.handle, "XUnregisterIMInstantiateCallback"); - _glfw.x11.xlib.utf8LookupString = (PFN_Xutf8LookupString) - _glfw_dlsym(_glfw.x11.xlib.handle, "Xutf8LookupString"); - _glfw.x11.xlib.utf8SetWMProperties = (PFN_Xutf8SetWMProperties) - _glfw_dlsym(_glfw.x11.xlib.handle, "Xutf8SetWMProperties"); + PFN_XInitThreads XInitThreads = (PFN_XInitThreads) + _glfwPlatformGetModuleSymbol(module, "XInitThreads"); + PFN_XrmInitialize XrmInitialize = (PFN_XrmInitialize) + _glfwPlatformGetModuleSymbol(module, "XrmInitialize"); + PFN_XOpenDisplay XOpenDisplay = (PFN_XOpenDisplay) + _glfwPlatformGetModuleSymbol(module, "XOpenDisplay"); + if (!XInitThreads || !XrmInitialize || !XOpenDisplay) + { + if (platformID == GLFW_PLATFORM_X11) + _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to load Xlib entry point"); - if (_glfw.x11.xlib.utf8LookupString && _glfw.x11.xlib.utf8SetWMProperties) - _glfw.x11.xlib.utf8 = GLFW_TRUE; + _glfwPlatformFreeModule(module); + return GLFW_FALSE; + } XInitThreads(); XrmInitialize(); - _glfw.x11.display = XOpenDisplay(NULL); - if (!_glfw.x11.display) + Display* display = XOpenDisplay(NULL); + if (!display) { - const char* display = getenv("DISPLAY"); - if (display) + if (platformID == GLFW_PLATFORM_X11) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "X11: Failed to open display %s", display); - } - else - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "X11: The DISPLAY environment variable is missing"); + const char* name = getenv("DISPLAY"); + if (name) + { + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, + "X11: Failed to open display %s", name); + } + else + { + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, + "X11: The DISPLAY environment variable is missing"); + } } + _glfwPlatformFreeModule(module); return GLFW_FALSE; } + _glfw.x11.display = display; + _glfw.x11.xlib.handle = module; + + *platform = x11; + return GLFW_TRUE; +} + +int _glfwInitX11(void) +{ + _glfw.x11.xlib.AllocClassHint = (PFN_XAllocClassHint) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XAllocClassHint"); + _glfw.x11.xlib.AllocSizeHints = (PFN_XAllocSizeHints) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XAllocSizeHints"); + _glfw.x11.xlib.AllocWMHints = (PFN_XAllocWMHints) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XAllocWMHints"); + _glfw.x11.xlib.ChangeProperty = (PFN_XChangeProperty) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XChangeProperty"); + _glfw.x11.xlib.ChangeWindowAttributes = (PFN_XChangeWindowAttributes) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XChangeWindowAttributes"); + _glfw.x11.xlib.CheckIfEvent = (PFN_XCheckIfEvent) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCheckIfEvent"); + _glfw.x11.xlib.CheckTypedWindowEvent = (PFN_XCheckTypedWindowEvent) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCheckTypedWindowEvent"); + _glfw.x11.xlib.CloseDisplay = (PFN_XCloseDisplay) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCloseDisplay"); + _glfw.x11.xlib.CloseIM = (PFN_XCloseIM) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCloseIM"); + _glfw.x11.xlib.ConvertSelection = (PFN_XConvertSelection) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XConvertSelection"); + _glfw.x11.xlib.CreateColormap = (PFN_XCreateColormap) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCreateColormap"); + _glfw.x11.xlib.CreateFontCursor = (PFN_XCreateFontCursor) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCreateFontCursor"); + _glfw.x11.xlib.CreateIC = (PFN_XCreateIC) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCreateIC"); + _glfw.x11.xlib.CreateRegion = (PFN_XCreateRegion) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCreateRegion"); + _glfw.x11.xlib.CreateWindow = (PFN_XCreateWindow) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XCreateWindow"); + _glfw.x11.xlib.DefineCursor = (PFN_XDefineCursor) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XDefineCursor"); + _glfw.x11.xlib.DeleteContext = (PFN_XDeleteContext) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XDeleteContext"); + _glfw.x11.xlib.DeleteProperty = (PFN_XDeleteProperty) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XDeleteProperty"); + _glfw.x11.xlib.DestroyIC = (PFN_XDestroyIC) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XDestroyIC"); + _glfw.x11.xlib.DestroyRegion = (PFN_XDestroyRegion) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XDestroyRegion"); + _glfw.x11.xlib.DestroyWindow = (PFN_XDestroyWindow) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XDestroyWindow"); + _glfw.x11.xlib.DisplayKeycodes = (PFN_XDisplayKeycodes) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XDisplayKeycodes"); + _glfw.x11.xlib.EventsQueued = (PFN_XEventsQueued) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XEventsQueued"); + _glfw.x11.xlib.FilterEvent = (PFN_XFilterEvent) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XFilterEvent"); + _glfw.x11.xlib.FindContext = (PFN_XFindContext) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XFindContext"); + _glfw.x11.xlib.Flush = (PFN_XFlush) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XFlush"); + _glfw.x11.xlib.Free = (PFN_XFree) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XFree"); + _glfw.x11.xlib.FreeColormap = (PFN_XFreeColormap) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XFreeColormap"); + _glfw.x11.xlib.FreeCursor = (PFN_XFreeCursor) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XFreeCursor"); + _glfw.x11.xlib.FreeEventData = (PFN_XFreeEventData) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XFreeEventData"); + _glfw.x11.xlib.GetErrorText = (PFN_XGetErrorText) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetErrorText"); + _glfw.x11.xlib.GetEventData = (PFN_XGetEventData) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetEventData"); + _glfw.x11.xlib.GetICValues = (PFN_XGetICValues) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetICValues"); + _glfw.x11.xlib.GetIMValues = (PFN_XGetIMValues) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetIMValues"); + _glfw.x11.xlib.GetInputFocus = (PFN_XGetInputFocus) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetInputFocus"); + _glfw.x11.xlib.GetKeyboardMapping = (PFN_XGetKeyboardMapping) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetKeyboardMapping"); + _glfw.x11.xlib.GetScreenSaver = (PFN_XGetScreenSaver) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetScreenSaver"); + _glfw.x11.xlib.GetSelectionOwner = (PFN_XGetSelectionOwner) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetSelectionOwner"); + _glfw.x11.xlib.GetVisualInfo = (PFN_XGetVisualInfo) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetVisualInfo"); + _glfw.x11.xlib.GetWMNormalHints = (PFN_XGetWMNormalHints) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetWMNormalHints"); + _glfw.x11.xlib.GetWindowAttributes = (PFN_XGetWindowAttributes) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetWindowAttributes"); + _glfw.x11.xlib.GetWindowProperty = (PFN_XGetWindowProperty) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGetWindowProperty"); + _glfw.x11.xlib.GrabPointer = (PFN_XGrabPointer) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XGrabPointer"); + _glfw.x11.xlib.IconifyWindow = (PFN_XIconifyWindow) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XIconifyWindow"); + _glfw.x11.xlib.InternAtom = (PFN_XInternAtom) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XInternAtom"); + _glfw.x11.xlib.LookupString = (PFN_XLookupString) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XLookupString"); + _glfw.x11.xlib.MapRaised = (PFN_XMapRaised) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XMapRaised"); + _glfw.x11.xlib.MapWindow = (PFN_XMapWindow) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XMapWindow"); + _glfw.x11.xlib.MoveResizeWindow = (PFN_XMoveResizeWindow) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XMoveResizeWindow"); + _glfw.x11.xlib.MoveWindow = (PFN_XMoveWindow) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XMoveWindow"); + _glfw.x11.xlib.NextEvent = (PFN_XNextEvent) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XNextEvent"); + _glfw.x11.xlib.OpenIM = (PFN_XOpenIM) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XOpenIM"); + _glfw.x11.xlib.PeekEvent = (PFN_XPeekEvent) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XPeekEvent"); + _glfw.x11.xlib.Pending = (PFN_XPending) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XPending"); + _glfw.x11.xlib.QueryExtension = (PFN_XQueryExtension) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XQueryExtension"); + _glfw.x11.xlib.QueryPointer = (PFN_XQueryPointer) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XQueryPointer"); + _glfw.x11.xlib.RaiseWindow = (PFN_XRaiseWindow) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XRaiseWindow"); + _glfw.x11.xlib.RegisterIMInstantiateCallback = (PFN_XRegisterIMInstantiateCallback) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XRegisterIMInstantiateCallback"); + _glfw.x11.xlib.ResizeWindow = (PFN_XResizeWindow) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XResizeWindow"); + _glfw.x11.xlib.ResourceManagerString = (PFN_XResourceManagerString) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XResourceManagerString"); + _glfw.x11.xlib.SaveContext = (PFN_XSaveContext) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSaveContext"); + _glfw.x11.xlib.SelectInput = (PFN_XSelectInput) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSelectInput"); + _glfw.x11.xlib.SendEvent = (PFN_XSendEvent) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSendEvent"); + _glfw.x11.xlib.SetClassHint = (PFN_XSetClassHint) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetClassHint"); + _glfw.x11.xlib.SetErrorHandler = (PFN_XSetErrorHandler) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetErrorHandler"); + _glfw.x11.xlib.SetICFocus = (PFN_XSetICFocus) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetICFocus"); + _glfw.x11.xlib.SetIMValues = (PFN_XSetIMValues) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetIMValues"); + _glfw.x11.xlib.SetInputFocus = (PFN_XSetInputFocus) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetInputFocus"); + _glfw.x11.xlib.SetLocaleModifiers = (PFN_XSetLocaleModifiers) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetLocaleModifiers"); + _glfw.x11.xlib.SetScreenSaver = (PFN_XSetScreenSaver) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetScreenSaver"); + _glfw.x11.xlib.SetSelectionOwner = (PFN_XSetSelectionOwner) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetSelectionOwner"); + _glfw.x11.xlib.SetWMHints = (PFN_XSetWMHints) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetWMHints"); + _glfw.x11.xlib.SetWMNormalHints = (PFN_XSetWMNormalHints) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetWMNormalHints"); + _glfw.x11.xlib.SetWMProtocols = (PFN_XSetWMProtocols) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSetWMProtocols"); + _glfw.x11.xlib.SupportsLocale = (PFN_XSupportsLocale) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSupportsLocale"); + _glfw.x11.xlib.Sync = (PFN_XSync) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XSync"); + _glfw.x11.xlib.TranslateCoordinates = (PFN_XTranslateCoordinates) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XTranslateCoordinates"); + _glfw.x11.xlib.UndefineCursor = (PFN_XUndefineCursor) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XUndefineCursor"); + _glfw.x11.xlib.UngrabPointer = (PFN_XUngrabPointer) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XUngrabPointer"); + _glfw.x11.xlib.UnmapWindow = (PFN_XUnmapWindow) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XUnmapWindow"); + _glfw.x11.xlib.UnsetICFocus = (PFN_XUnsetICFocus) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XUnsetICFocus"); + _glfw.x11.xlib.VisualIDFromVisual = (PFN_XVisualIDFromVisual) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XVisualIDFromVisual"); + _glfw.x11.xlib.WarpPointer = (PFN_XWarpPointer) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XWarpPointer"); + _glfw.x11.xkb.FreeKeyboard = (PFN_XkbFreeKeyboard) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbFreeKeyboard"); + _glfw.x11.xkb.FreeNames = (PFN_XkbFreeNames) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbFreeNames"); + _glfw.x11.xkb.GetMap = (PFN_XkbGetMap) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbGetMap"); + _glfw.x11.xkb.GetNames = (PFN_XkbGetNames) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbGetNames"); + _glfw.x11.xkb.GetState = (PFN_XkbGetState) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbGetState"); + _glfw.x11.xkb.KeycodeToKeysym = (PFN_XkbKeycodeToKeysym) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbKeycodeToKeysym"); + _glfw.x11.xkb.QueryExtension = (PFN_XkbQueryExtension) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbQueryExtension"); + _glfw.x11.xkb.SelectEventDetails = (PFN_XkbSelectEventDetails) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbSelectEventDetails"); + _glfw.x11.xkb.SetDetectableAutoRepeat = (PFN_XkbSetDetectableAutoRepeat) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XkbSetDetectableAutoRepeat"); + _glfw.x11.xrm.DestroyDatabase = (PFN_XrmDestroyDatabase) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XrmDestroyDatabase"); + _glfw.x11.xrm.GetResource = (PFN_XrmGetResource) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XrmGetResource"); + _glfw.x11.xrm.GetStringDatabase = (PFN_XrmGetStringDatabase) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XrmGetStringDatabase"); + _glfw.x11.xrm.UniqueQuark = (PFN_XrmUniqueQuark) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XrmUniqueQuark"); + _glfw.x11.xlib.UnregisterIMInstantiateCallback = (PFN_XUnregisterIMInstantiateCallback) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "XUnregisterIMInstantiateCallback"); + _glfw.x11.xlib.utf8LookupString = (PFN_Xutf8LookupString) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "Xutf8LookupString"); + _glfw.x11.xlib.utf8SetWMProperties = (PFN_Xutf8SetWMProperties) + _glfwPlatformGetModuleSymbol(_glfw.x11.xlib.handle, "Xutf8SetWMProperties"); + + if (_glfw.x11.xlib.utf8LookupString && _glfw.x11.xlib.utf8SetWMProperties) + _glfw.x11.xlib.utf8 = GLFW_TRUE; + _glfw.x11.screen = DefaultScreen(_glfw.x11.display); _glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen); _glfw.x11.context = XUniqueContext(); getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY); + if (!createEmptyEventPipe()) + return GLFW_FALSE; + if (!initExtensions()) return GLFW_FALSE; @@ -1381,13 +1549,11 @@ int _glfwPlatformInit(void) NULL); } - _glfwInitTimerPOSIX(); - _glfwPollMonitorsX11(); return GLFW_TRUE; } -void _glfwPlatformTerminate(void) +void _glfwTerminateX11(void) { if (_glfw.x11.helperWindowHandle) { @@ -1429,46 +1595,47 @@ void _glfwPlatformTerminate(void) if (_glfw.x11.x11xcb.handle) { - _glfw_dlclose(_glfw.x11.x11xcb.handle); + _glfwPlatformFreeModule(_glfw.x11.x11xcb.handle); _glfw.x11.x11xcb.handle = NULL; } if (_glfw.x11.xcursor.handle) { - _glfw_dlclose(_glfw.x11.xcursor.handle); + _glfwPlatformFreeModule(_glfw.x11.xcursor.handle); _glfw.x11.xcursor.handle = NULL; } if (_glfw.x11.randr.handle) { - _glfw_dlclose(_glfw.x11.randr.handle); + _glfwPlatformFreeModule(_glfw.x11.randr.handle); _glfw.x11.randr.handle = NULL; } if (_glfw.x11.xinerama.handle) { - _glfw_dlclose(_glfw.x11.xinerama.handle); + _glfwPlatformFreeModule(_glfw.x11.xinerama.handle); _glfw.x11.xinerama.handle = NULL; } if (_glfw.x11.xrender.handle) { - _glfw_dlclose(_glfw.x11.xrender.handle); + _glfwPlatformFreeModule(_glfw.x11.xrender.handle); _glfw.x11.xrender.handle = NULL; } if (_glfw.x11.vidmode.handle) { - _glfw_dlclose(_glfw.x11.vidmode.handle); + _glfwPlatformFreeModule(_glfw.x11.vidmode.handle); _glfw.x11.vidmode.handle = NULL; } if (_glfw.x11.xi.handle) { - _glfw_dlclose(_glfw.x11.xi.handle); + _glfwPlatformFreeModule(_glfw.x11.xi.handle); _glfw.x11.xi.handle = NULL; } + _glfwTerminateOSMesa(); // NOTE: These need to be unloaded after XCloseDisplay, as they register // cleanup callbacks that get called by that function _glfwTerminateEGL(); @@ -1476,23 +1643,16 @@ void _glfwPlatformTerminate(void) if (_glfw.x11.xlib.handle) { - _glfw_dlclose(_glfw.x11.xlib.handle); + _glfwPlatformFreeModule(_glfw.x11.xlib.handle); _glfw.x11.xlib.handle = NULL; } + + if (_glfw.x11.emptyEventPipe[0] || _glfw.x11.emptyEventPipe[1]) + { + close(_glfw.x11.emptyEventPipe[0]); + close(_glfw.x11.emptyEventPipe[1]); + } } -const char* _glfwPlatformGetVersionString(void) -{ - return _GLFW_VERSION_NUMBER " X11 GLX EGL OSMesa" -#if defined(_POSIX_MONOTONIC_CLOCK) - " monotonic" -#endif -#if defined(__linux__) - " evdev" -#endif -#if defined(_GLFW_BUILD_DLL) - " shared" -#endif - ; -} +#endif // _GLFW_X11 diff --git a/src/x11_monitor.c b/src/x11_monitor.c index 97da48db..3183630b 100644 --- a/src/x11_monitor.c +++ b/src/x11_monitor.c @@ -29,6 +29,8 @@ #include "internal.h" +#if defined(_GLFW_X11) + #include #include #include @@ -232,7 +234,7 @@ void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired) RRMode native = None; const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired); - _glfwPlatformGetVideoMode(monitor, ¤t); + _glfwGetVideoModeX11(monitor, ¤t); if (_glfwCompareVideoModes(¤t, best) == 0) return; @@ -310,11 +312,11 @@ void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor) ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor) +void _glfwFreeMonitorX11(_GLFWmonitor* monitor) { } -void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) +void _glfwGetMonitorPosX11(_GLFWmonitor* monitor, int* xpos, int* ypos) { if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) { @@ -336,8 +338,8 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) } } -void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, - float* xscale, float* yscale) +void _glfwGetMonitorContentScaleX11(_GLFWmonitor* monitor, + float* xscale, float* yscale) { if (xscale) *xscale = _glfw.x11.contentScaleX; @@ -345,7 +347,9 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, *yscale = _glfw.x11.contentScaleY; } -void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height) +void _glfwGetMonitorWorkareaX11(_GLFWmonitor* monitor, + int* xpos, int* ypos, + int* width, int* height) { int areaX = 0, areaY = 0, areaWidth = 0, areaHeight = 0; @@ -437,7 +441,7 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos *height = areaHeight; } -GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) +GLFWvidmode* _glfwGetVideoModesX11(_GLFWmonitor* monitor, int* count) { GLFWvidmode* result; @@ -483,13 +487,13 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) { *count = 1; result = _glfw_calloc(1, sizeof(GLFWvidmode)); - _glfwPlatformGetVideoMode(monitor, result); + _glfwGetVideoModeX11(monitor, result); } return result; } -void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) +void _glfwGetVideoModeX11(_GLFWmonitor* monitor, GLFWvidmode* mode) { if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) { @@ -519,7 +523,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) } } -GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) +GLFWbool _glfwGetGammaRampX11(_GLFWmonitor* monitor, GLFWgammaramp* ramp) { if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken) { @@ -557,7 +561,7 @@ GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) } } -void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) +void _glfwSetGammaRampX11(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) { if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken) { @@ -612,3 +616,5 @@ GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* handle) return monitor->x11.output; } +#endif // _GLFW_X11 + diff --git a/src/x11_platform.h b/src/x11_platform.h index c5137bc3..cdea3957 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -51,6 +50,53 @@ // The Shape extension provides custom window shapes #include +#define GLX_VENDOR 1 +#define GLX_RGBA_BIT 0x00000001 +#define GLX_WINDOW_BIT 0x00000001 +#define GLX_DRAWABLE_TYPE 0x8010 +#define GLX_RENDER_TYPE 0x8011 +#define GLX_RGBA_TYPE 0x8014 +#define GLX_DOUBLEBUFFER 5 +#define GLX_STEREO 6 +#define GLX_AUX_BUFFERS 7 +#define GLX_RED_SIZE 8 +#define GLX_GREEN_SIZE 9 +#define GLX_BLUE_SIZE 10 +#define GLX_ALPHA_SIZE 11 +#define GLX_DEPTH_SIZE 12 +#define GLX_STENCIL_SIZE 13 +#define GLX_ACCUM_RED_SIZE 14 +#define GLX_ACCUM_GREEN_SIZE 15 +#define GLX_ACCUM_BLUE_SIZE 16 +#define GLX_ACCUM_ALPHA_SIZE 17 +#define GLX_SAMPLES 0x186a1 +#define GLX_VISUAL_ID 0x800b + +#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20b2 +#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001 +#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 +#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define GLX_CONTEXT_FLAGS_ARB 0x2094 +#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 +#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261 +#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097 +#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0 +#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 +#define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3 + +typedef XID GLXWindow; +typedef XID GLXDrawable; +typedef struct __GLXFBConfig* GLXFBConfig; +typedef struct __GLXcontext* GLXContext; +typedef void (*__GLXextproc)(void); + typedef XClassHint* (* PFN_XAllocClassHint)(void); typedef XSizeHints* (* PFN_XAllocSizeHints)(void); typedef XWMHints* (* PFN_XAllocWMHints)(void); @@ -197,7 +243,6 @@ typedef void (* PFN_Xutf8SetWMProperties)(Display*,Window,const char*,const char #define XGetWindowProperty _glfw.x11.xlib.GetWindowProperty #define XGrabPointer _glfw.x11.xlib.GrabPointer #define XIconifyWindow _glfw.x11.xlib.IconifyWindow -#define XInitThreads _glfw.x11.xlib.InitThreads #define XInternAtom _glfw.x11.xlib.InternAtom #define XLookupString _glfw.x11.xlib.LookupString #define XMapRaised _glfw.x11.xlib.MapRaised @@ -205,7 +250,6 @@ typedef void (* PFN_Xutf8SetWMProperties)(Display*,Window,const char*,const char #define XMoveResizeWindow _glfw.x11.xlib.MoveResizeWindow #define XMoveWindow _glfw.x11.xlib.MoveWindow #define XNextEvent _glfw.x11.xlib.NextEvent -#define XOpenDisplay _glfw.x11.xlib.OpenDisplay #define XOpenIM _glfw.x11.xlib.OpenIM #define XPeekEvent _glfw.x11.xlib.PeekEvent #define XPending _glfw.x11.xlib.Pending @@ -250,7 +294,6 @@ typedef void (* PFN_Xutf8SetWMProperties)(Display*,Window,const char*,const char #define XrmDestroyDatabase _glfw.x11.xrm.DestroyDatabase #define XrmGetResource _glfw.x11.xrm.GetResource #define XrmGetStringDatabase _glfw.x11.xrm.GetStringDatabase -#define XrmInitialize _glfw.x11.xrm.Initialize #define XrmUniqueQuark _glfw.x11.xrm.UniqueQuark #define XUnregisterIMInstantiateCallback _glfw.x11.xlib.UnregisterIMInstantiateCallback #define Xutf8LookupString _glfw.x11.xlib.utf8LookupString @@ -348,6 +391,41 @@ typedef void (* PFN_XShapeCombineMask)(Display*,Window,int,int,int,Pixmap,int); #define XShapeCombineRegion _glfw.x11.xshape.ShapeCombineRegion #define XShapeCombineMask _glfw.x11.xshape.ShapeCombineMask +typedef int (*PFNGLXGETFBCONFIGATTRIBPROC)(Display*,GLXFBConfig,int,int*); +typedef const char* (*PFNGLXGETCLIENTSTRINGPROC)(Display*,int); +typedef Bool (*PFNGLXQUERYEXTENSIONPROC)(Display*,int*,int*); +typedef Bool (*PFNGLXQUERYVERSIONPROC)(Display*,int*,int*); +typedef void (*PFNGLXDESTROYCONTEXTPROC)(Display*,GLXContext); +typedef Bool (*PFNGLXMAKECURRENTPROC)(Display*,GLXDrawable,GLXContext); +typedef void (*PFNGLXSWAPBUFFERSPROC)(Display*,GLXDrawable); +typedef const char* (*PFNGLXQUERYEXTENSIONSSTRINGPROC)(Display*,int); +typedef GLXFBConfig* (*PFNGLXGETFBCONFIGSPROC)(Display*,int,int*); +typedef GLXContext (*PFNGLXCREATENEWCONTEXTPROC)(Display*,GLXFBConfig,int,GLXContext,Bool); +typedef __GLXextproc (* PFNGLXGETPROCADDRESSPROC)(const GLubyte *procName); +typedef void (*PFNGLXSWAPINTERVALEXTPROC)(Display*,GLXDrawable,int); +typedef XVisualInfo* (*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display*,GLXFBConfig); +typedef GLXWindow (*PFNGLXCREATEWINDOWPROC)(Display*,GLXFBConfig,Window,const int*); +typedef void (*PFNGLXDESTROYWINDOWPROC)(Display*,GLXWindow); + +typedef int (*PFNGLXSWAPINTERVALMESAPROC)(int); +typedef int (*PFNGLXSWAPINTERVALSGIPROC)(int); +typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLXContext,Bool,const int*); + +// libGL.so function pointer typedefs +#define glXGetFBConfigs _glfw.glx.GetFBConfigs +#define glXGetFBConfigAttrib _glfw.glx.GetFBConfigAttrib +#define glXGetClientString _glfw.glx.GetClientString +#define glXQueryExtension _glfw.glx.QueryExtension +#define glXQueryVersion _glfw.glx.QueryVersion +#define glXDestroyContext _glfw.glx.DestroyContext +#define glXMakeCurrent _glfw.glx.MakeCurrent +#define glXSwapBuffers _glfw.glx.SwapBuffers +#define glXQueryExtensionsString _glfw.glx.QueryExtensionsString +#define glXCreateNewContext _glfw.glx.CreateNewContext +#define glXGetVisualFromFBConfig _glfw.glx.GetVisualFromFBConfig +#define glXCreateWindow _glfw.glx.CreateWindow +#define glXDestroyWindow _glfw.glx.DestroyWindow + typedef VkFlags VkXlibSurfaceCreateFlagsKHR; typedef VkFlags VkXcbSurfaceCreateFlagsKHR; @@ -374,26 +452,72 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(V typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*); typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t); -#include "posix_thread.h" -#include "posix_time.h" #include "xkb_unicode.h" -#include "glx_context.h" -#if defined(__linux__) -#include "linux_joystick.h" -#else -#include "null_joystick.h" -#endif +#include "posix_poll.h" -#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) -#define _glfw_dlclose(handle) dlclose(handle) -#define _glfw_dlsym(handle, name) dlsym(handle, name) +#define GLFW_X11_WINDOW_STATE _GLFWwindowX11 x11; +#define GLFW_X11_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11; +#define GLFW_X11_MONITOR_STATE _GLFWmonitorX11 x11; +#define GLFW_X11_CURSOR_STATE _GLFWcursorX11 x11; -#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11 -#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11 -#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11 -#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorX11 x11 +#define GLFW_GLX_CONTEXT_STATE _GLFWcontextGLX glx; +#define GLFW_GLX_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx; +// GLX-specific per-context data +// +typedef struct _GLFWcontextGLX +{ + GLXContext handle; + GLXWindow window; +} _GLFWcontextGLX; + +// GLX-specific global data +// +typedef struct _GLFWlibraryGLX +{ + int major, minor; + int eventBase; + int errorBase; + + void* handle; + + // GLX 1.3 functions + PFNGLXGETFBCONFIGSPROC GetFBConfigs; + PFNGLXGETFBCONFIGATTRIBPROC GetFBConfigAttrib; + PFNGLXGETCLIENTSTRINGPROC GetClientString; + PFNGLXQUERYEXTENSIONPROC QueryExtension; + PFNGLXQUERYVERSIONPROC QueryVersion; + PFNGLXDESTROYCONTEXTPROC DestroyContext; + PFNGLXMAKECURRENTPROC MakeCurrent; + PFNGLXSWAPBUFFERSPROC SwapBuffers; + PFNGLXQUERYEXTENSIONSSTRINGPROC QueryExtensionsString; + PFNGLXCREATENEWCONTEXTPROC CreateNewContext; + PFNGLXGETVISUALFROMFBCONFIGPROC GetVisualFromFBConfig; + PFNGLXCREATEWINDOWPROC CreateWindow; + PFNGLXDESTROYWINDOWPROC DestroyWindow; + + // GLX 1.4 and extension functions + PFNGLXGETPROCADDRESSPROC GetProcAddress; + PFNGLXGETPROCADDRESSPROC GetProcAddressARB; + PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI; + PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT; + PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA; + PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; + GLFWbool SGI_swap_control; + GLFWbool EXT_swap_control; + GLFWbool MESA_swap_control; + GLFWbool ARB_multisample; + GLFWbool ARB_framebuffer_sRGB; + GLFWbool EXT_framebuffer_sRGB; + GLFWbool ARB_create_context; + GLFWbool ARB_create_context_profile; + GLFWbool ARB_create_context_robustness; + GLFWbool EXT_create_context_es2_profile; + GLFWbool ARB_create_context_no_error; + GLFWbool ARB_context_flush_control; +} _GLFWlibraryGLX; + // X11-specific per-window data // typedef struct _GLFWwindowX11 @@ -422,7 +546,6 @@ typedef struct _GLFWwindowX11 // The time of the last KeyPress event per keycode, for discarding // duplicate key events generated for some keys by ibus Time keyPressTimes[256]; - } _GLFWwindowX11; // X11-specific global data @@ -443,6 +566,8 @@ typedef struct _GLFWlibraryX11 XContext context; // XIM input method XIM im; + // The previous X error handler, to be restored later + XErrorHandler errorHandler; // Most recent error code received by X error handler int errorCode; // Primary selection string (while the primary selection is owned) @@ -459,6 +584,7 @@ typedef struct _GLFWlibraryX11 double restoreCursorPosX, restoreCursorPosY; // The window whose disabled cursor mode is active _GLFWwindow* disabledCursorWindow; + int emptyEventPipe[2]; // Window manager atoms Atom NET_SUPPORTED; @@ -563,7 +689,6 @@ typedef struct _GLFWlibraryX11 PFN_XGetWindowProperty GetWindowProperty; PFN_XGrabPointer GrabPointer; PFN_XIconifyWindow IconifyWindow; - PFN_XInitThreads InitThreads; PFN_XInternAtom InternAtom; PFN_XLookupString LookupString; PFN_XMapRaised MapRaised; @@ -571,7 +696,6 @@ typedef struct _GLFWlibraryX11 PFN_XMoveResizeWindow MoveResizeWindow; PFN_XMoveWindow MoveWindow; PFN_XNextEvent NextEvent; - PFN_XOpenDisplay OpenDisplay; PFN_XOpenIM OpenIM; PFN_XPeekEvent PeekEvent; PFN_XPending Pending; @@ -613,7 +737,6 @@ typedef struct _GLFWlibraryX11 PFN_XrmDestroyDatabase DestroyDatabase; PFN_XrmGetResource GetResource; PFN_XrmGetStringDatabase GetStringDatabase; - PFN_XrmInitialize Initialize; PFN_XrmUniqueQuark UniqueQuark; } xrm; @@ -751,7 +874,6 @@ typedef struct _GLFWlibraryX11 PFN_XShapeQueryVersion QueryVersion; PFN_XShapeCombineMask ShapeCombineMask; } xshape; - } _GLFWlibraryX11; // X11-specific per-monitor data @@ -765,7 +887,6 @@ typedef struct _GLFWmonitorX11 // Index of corresponding Xinerama screen, // for EWMH full screen window placement int index; - } _GLFWmonitorX11; // X11-specific per-cursor data @@ -773,15 +894,89 @@ typedef struct _GLFWmonitorX11 typedef struct _GLFWcursorX11 { Cursor handle; - } _GLFWcursorX11; +GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform); +int _glfwInitX11(void); +void _glfwTerminateX11(void); + +GLFWbool _glfwCreateWindowX11(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); +void _glfwDestroyWindowX11(_GLFWwindow* window); +void _glfwSetWindowTitleX11(_GLFWwindow* window, const char* title); +void _glfwSetWindowIconX11(_GLFWwindow* window, int count, const GLFWimage* images); +void _glfwGetWindowPosX11(_GLFWwindow* window, int* xpos, int* ypos); +void _glfwSetWindowPosX11(_GLFWwindow* window, int xpos, int ypos); +void _glfwGetWindowSizeX11(_GLFWwindow* window, int* width, int* height); +void _glfwSetWindowSizeX11(_GLFWwindow* window, int width, int height); +void _glfwSetWindowSizeLimitsX11(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); +void _glfwSetWindowAspectRatioX11(_GLFWwindow* window, int numer, int denom); +void _glfwGetFramebufferSizeX11(_GLFWwindow* window, int* width, int* height); +void _glfwGetWindowFrameSizeX11(_GLFWwindow* window, int* left, int* top, int* right, int* bottom); +void _glfwGetWindowContentScaleX11(_GLFWwindow* window, float* xscale, float* yscale); +void _glfwIconifyWindowX11(_GLFWwindow* window); +void _glfwRestoreWindowX11(_GLFWwindow* window); +void _glfwMaximizeWindowX11(_GLFWwindow* window); +void _glfwShowWindowX11(_GLFWwindow* window); +void _glfwHideWindowX11(_GLFWwindow* window); +void _glfwRequestWindowAttentionX11(_GLFWwindow* window); +void _glfwFocusWindowX11(_GLFWwindow* window); +void _glfwSetWindowMonitorX11(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); +GLFWbool _glfwWindowFocusedX11(_GLFWwindow* window); +GLFWbool _glfwWindowIconifiedX11(_GLFWwindow* window); +GLFWbool _glfwWindowVisibleX11(_GLFWwindow* window); +GLFWbool _glfwWindowMaximizedX11(_GLFWwindow* window); +GLFWbool _glfwWindowHoveredX11(_GLFWwindow* window); +GLFWbool _glfwFramebufferTransparentX11(_GLFWwindow* window); +void _glfwSetWindowResizableX11(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowDecoratedX11(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowFloatingX11(_GLFWwindow* window, GLFWbool enabled); +float _glfwGetWindowOpacityX11(_GLFWwindow* window); +void _glfwSetWindowOpacityX11(_GLFWwindow* window, float opacity); +void _glfwSetWindowMousePassthroughX11(_GLFWwindow* window, GLFWbool enabled); + +void _glfwSetRawMouseMotionX11(_GLFWwindow *window, GLFWbool enabled); +GLFWbool _glfwRawMouseMotionSupportedX11(void); + +void _glfwPollEventsX11(void); +void _glfwWaitEventsX11(void); +void _glfwWaitEventsTimeoutX11(double timeout); +void _glfwPostEmptyEventX11(void); + +void _glfwGetCursorPosX11(_GLFWwindow* window, double* xpos, double* ypos); +void _glfwSetCursorPosX11(_GLFWwindow* window, double xpos, double ypos); +void _glfwSetCursorModeX11(_GLFWwindow* window, int mode); +const char* _glfwGetScancodeNameX11(int scancode); +int _glfwGetKeyScancodeX11(int key); +GLFWbool _glfwCreateCursorX11(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot); +GLFWbool _glfwCreateStandardCursorX11(_GLFWcursor* cursor, int shape); +void _glfwDestroyCursorX11(_GLFWcursor* cursor); +void _glfwSetCursorX11(_GLFWwindow* window, _GLFWcursor* cursor); +void _glfwSetClipboardStringX11(const char* string); +const char* _glfwGetClipboardStringX11(void); + +EGLenum _glfwGetEGLPlatformX11(EGLint** attribs); +EGLNativeDisplayType _glfwGetEGLNativeDisplayX11(void); +EGLNativeWindowType _glfwGetEGLNativeWindowX11(_GLFWwindow* window); + +void _glfwGetRequiredInstanceExtensionsX11(char** extensions); +GLFWbool _glfwGetPhysicalDevicePresentationSupportX11(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); +VkResult _glfwCreateWindowSurfaceX11(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +void _glfwFreeMonitorX11(_GLFWmonitor* monitor); +void _glfwGetMonitorPosX11(_GLFWmonitor* monitor, int* xpos, int* ypos); +void _glfwGetMonitorContentScaleX11(_GLFWmonitor* monitor, float* xscale, float* yscale); +void _glfwGetMonitorWorkareaX11(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height); +GLFWvidmode* _glfwGetVideoModesX11(_GLFWmonitor* monitor, int* count); +void _glfwGetVideoModeX11(_GLFWmonitor* monitor, GLFWvidmode* mode); +GLFWbool _glfwGetGammaRampX11(_GLFWmonitor* monitor, GLFWgammaramp* ramp); +void _glfwSetGammaRampX11(_GLFWmonitor* monitor, const GLFWgammaramp* ramp); + void _glfwPollMonitorsX11(void); void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired); void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor); -Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot); +Cursor _glfwCreateNativeCursorX11(const GLFWimage* image, int xhot, int yhot); unsigned long _glfwGetWindowPropertyX11(Window window, Atom property, @@ -796,3 +991,14 @@ void _glfwInputErrorX11(int error, const char* message); void _glfwPushSelectionToManagerX11(void); void _glfwCreateInputContextX11(_GLFWwindow* window); +GLFWbool _glfwInitGLX(void); +void _glfwTerminateGLX(void); +GLFWbool _glfwCreateContextGLX(_GLFWwindow* window, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig); +void _glfwDestroyContextGLX(_GLFWwindow* window); +GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig, + Visual** visual, int* depth); + diff --git a/src/x11_window.c b/src/x11_window.c index 7ab8d9df..d7ce8e80 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -29,10 +29,12 @@ #include "internal.h" +#if defined(_GLFW_X11) + #include #include -#include +#include #include #include @@ -42,82 +44,99 @@ #include // Action for EWMH client messages -#define _NET_WM_STATE_REMOVE 0 -#define _NET_WM_STATE_ADD 1 -#define _NET_WM_STATE_TOGGLE 2 +#define _NET_WM_STATE_REMOVE 0 +#define _NET_WM_STATE_ADD 1 +#define _NET_WM_STATE_TOGGLE 2 // Additional mouse button names for XButtonEvent -#define Button6 6 -#define Button7 7 +#define Button6 6 +#define Button7 7 // Motif WM hints flags -#define MWM_HINTS_DECORATIONS 2 -#define MWM_DECOR_ALL 1 +#define MWM_HINTS_DECORATIONS 2 +#define MWM_DECOR_ALL 1 #define _GLFW_XDND_VERSION 5 - -// Wait for data to arrive using select +// Wait for event data to arrive on the X11 display socket // This avoids blocking other threads via the per-display Xlib lock that also // covers GLX functions // -static GLFWbool waitForEvent(double* timeout) +static GLFWbool waitForX11Event(double *timeout) +{ + struct pollfd fd = {ConnectionNumber(_glfw.x11.display), POLLIN}; + + while (!XPending(_glfw.x11.display)) + { + if (!_glfwPollPOSIX(&fd, 1, timeout)) + return GLFW_FALSE; + } + + return GLFW_TRUE; +} + +// Wait for event data to arrive on any event file descriptor +// This avoids blocking other threads via the per-display Xlib lock that also +// covers GLX functions +// +static GLFWbool waitForAnyEvent(double *timeout) +{ + nfds_t count = 2; + struct pollfd fds[3] = + { + {ConnectionNumber(_glfw.x11.display), POLLIN}, + {_glfw.x11.emptyEventPipe[0], POLLIN}}; + +#if defined(_GLFW_LINUX_JOYSTICK) + if (_glfw.joysticksInitialized) + fds[count++] = (struct pollfd){_glfw.linjs.inotify, POLLIN}; +#endif + + while (!XPending(_glfw.x11.display)) + { + if (!_glfwPollPOSIX(fds, count, timeout)) + return GLFW_FALSE; + + for (int i = 1; i < count; i++) + { + if (fds[i].revents & POLLIN) + return GLFW_TRUE; + } + } + + return GLFW_TRUE; +} + +// Writes a byte to the empty event pipe +// +static void writeEmptyEvent(void) { - fd_set fds; - const int fd = ConnectionNumber(_glfw.x11.display); for (;;) { - int count = fd + 1; - FD_ZERO(&fds); - FD_SET(fd, &fds); + const char byte = 0; + const ssize_t result = write(_glfw.x11.emptyEventPipe[1], &byte, 1); + if (result == 1 || (result == -1 && errno != EINTR)) + break; + } +} -#if defined(__linux__) - if (_glfw.linjs.inotify > 0) - { - if (_glfw.linjs.inotify >= count ) - count = _glfw.linjs.inotify + 1; - - FD_SET(_glfw.linjs.inotify, &fds); - } - - for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) - { - if (_glfw.joysticks[jid].present) { - if (_glfw.joysticks[jid].linjs.fd >= count) - count = _glfw.joysticks[jid].linjs.fd + 1; - - FD_SET(_glfw.joysticks[jid].linjs.fd, &fds); - } - } - -#endif - if (timeout) - { - const long seconds = (long) *timeout; - const long microseconds = (long) ((*timeout - seconds) * 1e6); - struct timeval tv = { seconds, microseconds }; - const uint64_t base = _glfwPlatformGetTimerValue(); - - const int result = select(count, &fds, NULL, NULL, &tv); - const int error = errno; - - *timeout -= (_glfwPlatformGetTimerValue() - base) / - (double) _glfwPlatformGetTimerFrequency(); - - if (result > 0) - return GLFW_TRUE; - if ((result == -1 && error == EINTR) || *timeout <= 0.0) - return GLFW_FALSE; - } - else if (select(count, &fds, NULL, NULL, NULL) != -1 || errno != EINTR) - return GLFW_TRUE; +// Drains available data from the empty event pipe +// +static void drainEmptyEvents(void) +{ + for (;;) + { + char dummy[64]; + const ssize_t result = read(_glfw.x11.emptyEventPipe[0], dummy, sizeof(dummy)); + if (result == -1 && errno != EINTR) + break; } } // Waits until a VisibilityNotify event arrives for the specified window or the // timeout period elapses (ICCCM section 4.2.2) // -static GLFWbool waitForVisibilityNotify(_GLFWwindow* window) +static GLFWbool waitForVisibilityNotify(_GLFWwindow *window) { XEvent dummy; double timeout = 0.1; @@ -127,7 +146,7 @@ static GLFWbool waitForVisibilityNotify(_GLFWwindow* window) VisibilityNotify, &dummy)) { - if (!waitForEvent(&timeout)) + if (!waitForX11Event(&timeout)) return GLFW_FALSE; } @@ -136,10 +155,11 @@ static GLFWbool waitForVisibilityNotify(_GLFWwindow* window) // Returns whether the window is iconified // -static int getWindowState(_GLFWwindow* window) +static int getWindowState(_GLFWwindow *window) { int result = WithdrawnState; - struct { + struct + { CARD32 state; Window icon; } *state = NULL; @@ -147,7 +167,7 @@ static int getWindowState(_GLFWwindow* window) if (_glfwGetWindowPropertyX11(window->x11.handle, _glfw.x11.WM_STATE, _glfw.x11.WM_STATE, - (unsigned char**) &state) >= 2) + (unsigned char **)&state) >= 2) { result = state->state; } @@ -160,7 +180,7 @@ static int getWindowState(_GLFWwindow* window) // Returns whether the event is a selection event // -static Bool isSelectionEvent(Display* display, XEvent* event, XPointer pointer) +static Bool isSelectionEvent(Display *display, XEvent *event, XPointer pointer) { if (event->xany.window != _glfw.x11.helperWindowHandle) return False; @@ -172,9 +192,9 @@ static Bool isSelectionEvent(Display* display, XEvent* event, XPointer pointer) // Returns whether it is a _NET_FRAME_EXTENTS event for the specified window // -static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointer) +static Bool isFrameExtentsEvent(Display *display, XEvent *event, XPointer pointer) { - _GLFWwindow* window = (_GLFWwindow*) pointer; + _GLFWwindow *window = (_GLFWwindow *)pointer; return event->type == PropertyNotify && event->xproperty.state == PropertyNewValue && event->xproperty.window == window->x11.handle && @@ -183,9 +203,9 @@ static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointe // Returns whether it is a property event for the specified selection transfer // -static Bool isSelPropNewValueNotify(Display* display, XEvent* event, XPointer pointer) +static Bool isSelPropNewValueNotify(Display *display, XEvent *event, XPointer pointer) { - XEvent* notification = (XEvent*) pointer; + XEvent *notification = (XEvent *)pointer; return event->type == PropertyNotify && event->xproperty.state == PropertyNewValue && event->xproperty.window == notification->xselection.requestor && @@ -227,10 +247,10 @@ static int translateKey(int scancode) // Sends an EWMH or ICCCM event to the window manager // -static void sendEventToWM(_GLFWwindow* window, Atom type, +static void sendEventToWM(_GLFWwindow *window, Atom type, long a, long b, long c, long d, long e) { - XEvent event = { ClientMessage }; + XEvent event = {ClientMessage}; event.xclient.window = window->x11.handle; event.xclient.format = 32; // Data is 32-bit longs event.xclient.message_type = type; @@ -248,9 +268,14 @@ static void sendEventToWM(_GLFWwindow* window, Atom type, // Updates the normal hints according to the window settings // -static void updateNormalHints(_GLFWwindow* window, int width, int height) +static void updateNormalHints(_GLFWwindow *window, int width, int height) { - XSizeHints* hints = XAllocSizeHints(); + XSizeHints *hints = XAllocSizeHints(); + + long supplied; + XGetWMNormalHints(_glfw.x11.display, window->x11.handle, hints, &supplied); + + hints->flags &= ~(PMinSize | PMaxSize | PAspect); if (!window->monitor) { @@ -283,21 +308,18 @@ static void updateNormalHints(_GLFWwindow* window, int width, int height) else { hints->flags |= (PMinSize | PMaxSize); - hints->min_width = hints->max_width = width; + hints->min_width = hints->max_width = width; hints->min_height = hints->max_height = height; } } - hints->flags |= PWinGravity; - hints->win_gravity = StaticGravity; - XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints); XFree(hints); } // Updates the full screen status of the window // -static void updateWindowMode(_GLFWwindow* window) +static void updateWindowMode(_GLFWwindow *window) { if (window->monitor) { @@ -346,9 +368,9 @@ static void updateWindowMode(_GLFWwindow* window) { const unsigned long value = 1; - XChangeProperty(_glfw.x11.display, window->x11.handle, + XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32, - PropModeReplace, (unsigned char*) &value, 1); + PropModeReplace, (unsigned char *)&value, 1); } } else @@ -389,135 +411,53 @@ static void updateWindowMode(_GLFWwindow* window) } } -// Splits and translates a text/uri-list into separate file paths -// NOTE: This function destroys the provided string -// -static char** parseUriList(char* text, int* count) -{ - const char* prefix = "file://"; - char** paths = NULL; - char* line; - - *count = 0; - - while ((line = strtok(text, "\r\n"))) - { - text = NULL; - - if (line[0] == '#') - continue; - - if (strncmp(line, prefix, strlen(prefix)) == 0) - { - line += strlen(prefix); - // TODO: Validate hostname - while (*line != '/') - line++; - } - - (*count)++; - - char* path = _glfw_calloc(strlen(line) + 1, 1); - paths = _glfw_realloc(paths, *count * sizeof(char*)); - paths[*count - 1] = path; - - while (*line) - { - if (line[0] == '%' && line[1] && line[2]) - { - const char digits[3] = { line[1], line[2], '\0' }; - *path = strtol(digits, NULL, 16); - line += 2; - } - else - *path = *line; - - path++; - line++; - } - } - - return paths; -} - -// Encode a Unicode code point to a UTF-8 stream -// Based on cutef8 by Jeff Bezanson (Public Domain) -// -static size_t encodeUTF8(char* s, unsigned int ch) -{ - size_t count = 0; - - if (ch < 0x80) - s[count++] = (char) ch; - else if (ch < 0x800) - { - s[count++] = (ch >> 6) | 0xc0; - s[count++] = (ch & 0x3f) | 0x80; - } - else if (ch < 0x10000) - { - s[count++] = (ch >> 12) | 0xe0; - s[count++] = ((ch >> 6) & 0x3f) | 0x80; - s[count++] = (ch & 0x3f) | 0x80; - } - else if (ch < 0x110000) - { - s[count++] = (ch >> 18) | 0xf0; - s[count++] = ((ch >> 12) & 0x3f) | 0x80; - s[count++] = ((ch >> 6) & 0x3f) | 0x80; - s[count++] = (ch & 0x3f) | 0x80; - } - - return count; -} - // Decode a Unicode code point from a UTF-8 stream // Based on cutef8 by Jeff Bezanson (Public Domain) // -static unsigned int decodeUTF8(const char** s) +static uint32_t decodeUTF8(const char **s) { - unsigned int ch = 0, count = 0; - static const unsigned int offsets[] = - { - 0x00000000u, 0x00003080u, 0x000e2080u, - 0x03c82080u, 0xfa082080u, 0x82082080u - }; + uint32_t codepoint = 0, count = 0; + static const uint32_t offsets[] = + { + 0x00000000u, 0x00003080u, 0x000e2080u, + 0x03c82080u, 0xfa082080u, 0x82082080u}; do { - ch = (ch << 6) + (unsigned char) **s; + codepoint = (codepoint << 6) + (unsigned char)**s; (*s)++; count++; } while ((**s & 0xc0) == 0x80); assert(count <= 6); - return ch - offsets[count - 1]; + return codepoint - offsets[count - 1]; } // Convert the specified Latin-1 string to UTF-8 // -static char* convertLatin1toUTF8(const char* source) +static char *convertLatin1toUTF8(const char *source) { size_t size = 1; - const char* sp; + const char *sp; - for (sp = source; *sp; sp++) + for (sp = source; *sp; sp++) size += (*sp & 0x80) ? 2 : 1; - char* target = _glfw_calloc(size, 1); - char* tp = target; + char *target = _glfw_calloc(size, 1); + char *tp = target; - for (sp = source; *sp; sp++) - tp += encodeUTF8(tp, *sp); + for (sp = source; *sp; sp++) + tp += _glfwEncodeUTF8(tp, *sp); return target; } // Updates the cursor image according to its cursor mode // -static void updateCursorImage(_GLFWwindow* window) +static void updateCursorImage(_GLFWwindow *window) { - if (window->cursorMode == GLFW_CURSOR_NORMAL) + if (window->cursorMode == GLFW_CURSOR_NORMAL || + window->cursorMode == GLFW_CURSOR_CAPTURED) { if (window->cursor) { @@ -534,12 +474,31 @@ static void updateCursorImage(_GLFWwindow* window) } } +// Grabs the cursor and confines it to the window +// +static void captureCursor(_GLFWwindow *window) +{ + XGrabPointer(_glfw.x11.display, window->x11.handle, True, + ButtonPressMask | ButtonReleaseMask | PointerMotionMask, + GrabModeAsync, GrabModeAsync, + window->x11.handle, + None, + CurrentTime); +} + +// Ungrabs the cursor +// +static void releaseCursor(void) +{ + XUngrabPointer(_glfw.x11.display, CurrentTime); +} + // Enable XI2 raw mouse motion events // -static void enableRawMouseMotion(_GLFWwindow* window) +static void enableRawMouseMotion(_GLFWwindow *window) { XIEventMask em; - unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 }; + unsigned char mask[XIMaskLen(XI_RawMotion)] = {0}; em.deviceid = XIAllMasterDevices; em.mask_len = sizeof(mask); @@ -551,10 +510,10 @@ static void enableRawMouseMotion(_GLFWwindow* window) // Disable XI2 raw mouse motion events // -static void disableRawMouseMotion(_GLFWwindow* window) +static void disableRawMouseMotion(_GLFWwindow *window) { XIEventMask em; - unsigned char mask[] = { 0 }; + unsigned char mask[] = {0}; em.deviceid = XIAllMasterDevices; em.mask_len = sizeof(mask); @@ -565,37 +524,32 @@ static void disableRawMouseMotion(_GLFWwindow* window) // Apply disabled cursor mode to a focused window // -static void disableCursor(_GLFWwindow* window) +static void disableCursor(_GLFWwindow *window) { if (window->rawMouseMotion) enableRawMouseMotion(window); _glfw.x11.disabledCursorWindow = window; - _glfwPlatformGetCursorPos(window, - &_glfw.x11.restoreCursorPosX, - &_glfw.x11.restoreCursorPosY); + _glfwGetCursorPosX11(window, + &_glfw.x11.restoreCursorPosX, + &_glfw.x11.restoreCursorPosY); updateCursorImage(window); _glfwCenterCursorInContentArea(window); - XGrabPointer(_glfw.x11.display, window->x11.handle, True, - ButtonPressMask | ButtonReleaseMask | PointerMotionMask, - GrabModeAsync, GrabModeAsync, - window->x11.handle, - _glfw.x11.hiddenCursorHandle, - CurrentTime); + captureCursor(window); } // Exit disabled cursor mode for the specified window // -static void enableCursor(_GLFWwindow* window) +static void enableCursor(_GLFWwindow *window) { if (window->rawMouseMotion) disableRawMouseMotion(window); _glfw.x11.disabledCursorWindow = NULL; - XUngrabPointer(_glfw.x11.display, CurrentTime); - _glfwPlatformSetCursorPos(window, - _glfw.x11.restoreCursorPosX, - _glfw.x11.restoreCursorPosY); + releaseCursor(); + _glfwSetCursorPosX11(window, + _glfw.x11.restoreCursorPosX, + _glfw.x11.restoreCursorPosY); updateCursorImage(window); } @@ -603,15 +557,15 @@ static void enableCursor(_GLFWwindow* window) // static void inputContextDestroyCallback(XIC ic, XPointer clientData, XPointer callData) { - _GLFWwindow* window = (_GLFWwindow*) clientData; + _GLFWwindow *window = (_GLFWwindow *)clientData; window->x11.ic = NULL; } // Create the X11 window (and its colormap) // -static GLFWbool createNativeWindow(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - Visual* visual, int depth) +static GLFWbool createNativeWindow(_GLFWwindow *window, + const _GLFWwndconfig *wndconfig, + Visual *visual, int depth) { int width = wndconfig->width; int height = wndconfig->height; @@ -622,6 +576,14 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, height *= _glfw.x11.contentScaleY; } + int xpos = 0, ypos = 0; + + if (wndconfig->xpos != GLFW_ANY_POSITION && wndconfig->ypos != GLFW_ANY_POSITION) + { + xpos = wndconfig->xpos; + ypos = wndconfig->ypos; + } + // Create a colormap based on the visual used by the current context window->x11.colormap = XCreateColormap(_glfw.x11.display, _glfw.x11.root, @@ -630,7 +592,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, window->x11.transparent = _glfwIsVisualTransparentX11(visual); - XSetWindowAttributes wa = { 0 }; + XSetWindowAttributes wa = {0}; wa.colormap = window->x11.colormap; wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | @@ -642,10 +604,10 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, window->x11.parent = _glfw.x11.root; window->x11.handle = XCreateWindow(_glfw.x11.display, _glfw.x11.root, - 0, 0, // Position + xpos, ypos, width, height, - 0, // Border width - depth, // Color depth + 0, // Border width + depth, // Color depth InputOutput, visual, CWBorderPixel | CWColormap | CWEventMask, @@ -663,10 +625,10 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, XSaveContext(_glfw.x11.display, window->x11.handle, _glfw.x11.context, - (XPointer) window); + (XPointer)window); if (!wndconfig->decorated) - _glfwPlatformSetWindowDecorated(window, GLFW_FALSE); + _glfwSetWindowDecoratedX11(window, GLFW_FALSE); if (_glfw.x11.NET_WM_STATE && !window->monitor) { @@ -694,17 +656,16 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, { XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_STATE, XA_ATOM, 32, - PropModeReplace, (unsigned char*) states, count); + PropModeReplace, (unsigned char *)states, count); } } // Declare the WM protocols supported by GLFW { Atom protocols[] = - { - _glfw.x11.WM_DELETE_WINDOW, - _glfw.x11.NET_WM_PING - }; + { + _glfw.x11.WM_DELETE_WINDOW, + _glfw.x11.NET_WM_PING}; XSetWMProtocols(_glfw.x11.display, window->x11.handle, protocols, sizeof(protocols) / sizeof(Atom)); @@ -714,23 +675,23 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, { const long pid = getpid(); - XChangeProperty(_glfw.x11.display, window->x11.handle, + XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_PID, XA_CARDINAL, 32, PropModeReplace, - (unsigned char*) &pid, 1); + (unsigned char *)&pid, 1); } if (_glfw.x11.NET_WM_WINDOW_TYPE && _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL) { Atom type = _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL; - XChangeProperty(_glfw.x11.display, window->x11.handle, + XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_WINDOW_TYPE, XA_ATOM, 32, - PropModeReplace, (unsigned char*) &type, 1); + PropModeReplace, (unsigned char *)&type, 1); } // Set ICCCM WM_HINTS property { - XWMHints* hints = XAllocWMHints(); + XWMHints *hints = XAllocWMHints(); if (!hints) { _glfwInputError(GLFW_OUT_OF_MEMORY, @@ -745,32 +706,62 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, XFree(hints); } - updateNormalHints(window, width, height); + // Set ICCCM WM_NORMAL_HINTS property + { + XSizeHints *hints = XAllocSizeHints(); + if (!hints) + { + _glfwInputError(GLFW_OUT_OF_MEMORY, "X11: Failed to allocate size hints"); + return GLFW_FALSE; + } + + if (!wndconfig->resizable) + { + hints->flags |= (PMinSize | PMaxSize); + hints->min_width = hints->max_width = width; + hints->min_height = hints->max_height = height; + } + + // HACK: Explicitly setting PPosition to any value causes some WMs, notably + // Compiz and Metacity, to honor the position of unmapped windows + if (wndconfig->xpos != GLFW_ANY_POSITION && wndconfig->ypos != GLFW_ANY_POSITION) + { + hints->flags |= PPosition; + hints->x = 0; + hints->y = 0; + } + + hints->flags |= PWinGravity; + hints->win_gravity = StaticGravity; + + XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints); + XFree(hints); + } // Set ICCCM WM_CLASS property { - XClassHint* hint = XAllocClassHint(); + XClassHint *hint = XAllocClassHint(); if (strlen(wndconfig->x11.instanceName) && strlen(wndconfig->x11.className)) { - hint->res_name = (char*) wndconfig->x11.instanceName; - hint->res_class = (char*) wndconfig->x11.className; + hint->res_name = (char *)wndconfig->x11.instanceName; + hint->res_class = (char *)wndconfig->x11.className; } else { - const char* resourceName = getenv("RESOURCE_NAME"); + const char *resourceName = getenv("RESOURCE_NAME"); if (resourceName && strlen(resourceName)) - hint->res_name = (char*) resourceName; + hint->res_name = (char *)resourceName; else if (strlen(wndconfig->title)) - hint->res_name = (char*) wndconfig->title; + hint->res_name = (char *)wndconfig->title; else - hint->res_name = (char*) "glfw-application"; + hint->res_name = (char *)"glfw-application"; if (strlen(wndconfig->title)) - hint->res_class = (char*) wndconfig->title; + hint->res_class = (char *)wndconfig->title; else - hint->res_class = (char*) "GLFW-Application"; + hint->res_class = (char *)"GLFW-Application"; } XSetClassHint(_glfw.x11.display, window->x11.handle, hint); @@ -782,26 +773,25 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, const Atom version = _GLFW_XDND_VERSION; XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.XdndAware, XA_ATOM, 32, - PropModeReplace, (unsigned char*) &version, 1); + PropModeReplace, (unsigned char *)&version, 1); } if (_glfw.x11.im) _glfwCreateInputContextX11(window); - _glfwPlatformSetWindowTitle(window, wndconfig->title); - _glfwPlatformGetWindowPos(window, &window->x11.xpos, &window->x11.ypos); - _glfwPlatformGetWindowSize(window, &window->x11.width, &window->x11.height); + _glfwSetWindowTitleX11(window, wndconfig->title); + _glfwGetWindowPosX11(window, &window->x11.xpos, &window->x11.ypos); + _glfwGetWindowSizeX11(window, &window->x11.width, &window->x11.height); return GLFW_TRUE; } // Set the specified property to the selection converted to the requested target // -static Atom writeTargetToProperty(const XSelectionRequestEvent* request) +static Atom writeTargetToProperty(const XSelectionRequestEvent *request) { - int i; - char* selectionString = NULL; - const Atom formats[] = { _glfw.x11.UTF8_STRING, XA_STRING }; + char *selectionString = NULL; + const Atom formats[] = {_glfw.x11.UTF8_STRING, XA_STRING}; const int formatCount = sizeof(formats) / sizeof(formats[0]); if (request->selection == _glfw.x11.PRIMARY) @@ -820,10 +810,10 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request) { // The list of supported targets was requested - const Atom targets[] = { _glfw.x11.TARGETS, - _glfw.x11.MULTIPLE, - _glfw.x11.UTF8_STRING, - XA_STRING }; + const Atom targets[] = {_glfw.x11.TARGETS, + _glfw.x11.MULTIPLE, + _glfw.x11.UTF8_STRING, + XA_STRING}; XChangeProperty(_glfw.x11.display, request->requestor, @@ -831,7 +821,7 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request) XA_ATOM, 32, PropModeReplace, - (unsigned char*) targets, + (unsigned char *)targets, sizeof(targets) / sizeof(targets[0])); return request->property; @@ -841,19 +831,18 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request) { // Multiple conversions were requested - Atom* targets; - unsigned long i, count; + Atom *targets; + const unsigned long count = + _glfwGetWindowPropertyX11(request->requestor, + request->property, + _glfw.x11.ATOM_PAIR, + (unsigned char **)&targets); - count = _glfwGetWindowPropertyX11(request->requestor, - request->property, - _glfw.x11.ATOM_PAIR, - (unsigned char**) &targets); - - for (i = 0; i < count; i += 2) + for (unsigned long i = 0; i < count; i += 2) { int j; - for (j = 0; j < formatCount; j++) + for (j = 0; j < formatCount; j++) { if (targets[i] == formats[j]) break; @@ -867,7 +856,7 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request) targets[i], 8, PropModeReplace, - (unsigned char *) selectionString, + (unsigned char *)selectionString, strlen(selectionString)); } else @@ -880,7 +869,7 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request) _glfw.x11.ATOM_PAIR, 32, PropModeReplace, - (unsigned char*) targets, + (unsigned char *)targets, count); XFree(targets); @@ -907,7 +896,7 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request) // Conversion to a data target was requested - for (i = 0; i < formatCount; i++) + for (int i = 0; i < formatCount; i++) { if (request->target == formats[i]) { @@ -919,7 +908,7 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request) request->target, 8, PropModeReplace, - (unsigned char *) selectionString, + (unsigned char *)selectionString, strlen(selectionString)); return request->property; @@ -931,25 +920,11 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request) return None; } -static void handleSelectionClear(XEvent* event) +static void handleSelectionRequest(XEvent *event) { - if (event->xselectionclear.selection == _glfw.x11.PRIMARY) - { - _glfw_free(_glfw.x11.primarySelectionString); - _glfw.x11.primarySelectionString = NULL; - } - else - { - _glfw_free(_glfw.x11.clipboardString); - _glfw.x11.clipboardString = NULL; - } -} + const XSelectionRequestEvent *request = &event->xselectionrequest; -static void handleSelectionRequest(XEvent* event) -{ - const XSelectionRequestEvent* request = &event->xselectionrequest; - - XEvent reply = { SelectionNotify }; + XEvent reply = {SelectionNotify}; reply.xselection.property = writeTargetToProperty(request); reply.xselection.display = request->display; reply.xselection.requestor = request->requestor; @@ -960,10 +935,10 @@ static void handleSelectionRequest(XEvent* event) XSendEvent(_glfw.x11.display, request->requestor, False, 0, &reply); } -static const char* getSelectionString(Atom selection) +static const char *getSelectionString(Atom selection) { - char** selectionString = NULL; - const Atom targets[] = { _glfw.x11.UTF8_STRING, XA_STRING }; + char **selectionString = NULL; + const Atom targets[] = {_glfw.x11.UTF8_STRING, XA_STRING}; const size_t targetCount = sizeof(targets) / sizeof(targets[0]); if (selection == _glfw.x11.PRIMARY) @@ -982,9 +957,9 @@ static const char* getSelectionString(Atom selection) _glfw_free(*selectionString); *selectionString = NULL; - for (size_t i = 0; i < targetCount; i++) + for (size_t i = 0; i < targetCount; i++) { - char* data; + char *data; Atom actualType; int actualFormat; unsigned long itemCount, bytesAfter; @@ -1002,7 +977,7 @@ static const char* getSelectionString(Atom selection) SelectionNotify, ¬ification)) { - waitForEvent(NULL); + waitForX11Event(NULL); } if (notification.xselection.property == None) @@ -1011,7 +986,7 @@ static const char* getSelectionString(Atom selection) XCheckIfEvent(_glfw.x11.display, &dummy, isSelPropNewValueNotify, - (XPointer) ¬ification); + (XPointer)¬ification); XGetWindowProperty(_glfw.x11.display, notification.xselection.requestor, @@ -1024,21 +999,21 @@ static const char* getSelectionString(Atom selection) &actualFormat, &itemCount, &bytesAfter, - (unsigned char**) &data); + (unsigned char **)&data); if (actualType == _glfw.x11.INCR) { size_t size = 1; - char* string = NULL; + char *string = NULL; for (;;) { while (!XCheckIfEvent(_glfw.x11.display, &dummy, isSelPropNewValueNotify, - (XPointer) ¬ification)) + (XPointer)¬ification)) { - waitForEvent(NULL); + waitForX11Event(NULL); } XFree(data); @@ -1053,7 +1028,7 @@ static const char* getSelectionString(Atom selection) &actualFormat, &itemCount, &bytesAfter, - (unsigned char**) &data); + (unsigned char **)&data); if (itemCount) { @@ -1065,13 +1040,16 @@ static const char* getSelectionString(Atom selection) if (!itemCount) { - if (targets[i] == XA_STRING) + if (string) { - *selectionString = convertLatin1toUTF8(string); - _glfw_free(string); + if (targets[i] == XA_STRING) + { + *selectionString = convertLatin1toUTF8(string); + _glfw_free(string); + } + else + *selectionString = string; } - else - *selectionString = string; break; } @@ -1102,7 +1080,7 @@ static const char* getSelectionString(Atom selection) // Make the specified window and its video mode active on its monitor // -static void acquireMonitor(_GLFWwindow* window) +static void acquireMonitor(_GLFWwindow *window) { if (_glfw.x11.saver.count == 0) { @@ -1129,8 +1107,8 @@ static void acquireMonitor(_GLFWwindow* window) GLFWvidmode mode; // Manually position the window over its monitor - _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos); - _glfwPlatformGetVideoMode(window->monitor, &mode); + _glfwGetMonitorPosX11(window->monitor, &xpos, &ypos); + _glfwGetVideoModeX11(window->monitor, &mode); XMoveResizeWindow(_glfw.x11.display, window->x11.handle, xpos, ypos, mode.width, mode.height); @@ -1141,7 +1119,7 @@ static void acquireMonitor(_GLFWwindow* window) // Remove the window and restore the original video mode // -static void releaseMonitor(_GLFWwindow* window) +static void releaseMonitor(_GLFWwindow *window) { if (window->monitor->window != window) return; @@ -1189,10 +1167,10 @@ static void processEvent(XEvent *event) { if (event->type == _glfw.x11.xkb.eventBase + XkbEventCode) { - if (((XkbEvent*) event)->any.xkb_type == XkbStateNotify && - (((XkbEvent*) event)->state.changed & XkbGroupStateMask)) + if (((XkbEvent *)event)->any.xkb_type == XkbStateNotify && + (((XkbEvent *)event)->state.changed & XkbGroupStateMask)) { - _glfw.x11.xkb.group = ((XkbEvent*) event)->state.group; + _glfw.x11.xkb.group = ((XkbEvent *)event)->state.group; } return; @@ -1203,7 +1181,7 @@ static void processEvent(XEvent *event) { if (_glfw.x11.xi.available) { - _GLFWwindow* window = _glfw.x11.disabledCursorWindow; + _GLFWwindow *window = _glfw.x11.disabledCursorWindow; if (window && window->rawMouseMotion && @@ -1211,10 +1189,10 @@ static void processEvent(XEvent *event) XGetEventData(_glfw.x11.display, &event->xcookie) && event->xcookie.evtype == XI_RawMotion) { - XIRawEvent* re = event->xcookie.data; + XIRawEvent *re = event->xcookie.data; if (re->valuators.mask_len) { - const double* values = re->raw_values; + const double *values = re->raw_values; double xpos = window->virtualCursorPosX; double ypos = window->virtualCursorPosY; @@ -1237,22 +1215,17 @@ static void processEvent(XEvent *event) return; } - if (event->type == SelectionClear) - { - handleSelectionClear(event); - return; - } - else if (event->type == SelectionRequest) + if (event->type == SelectionRequest) { handleSelectionRequest(event); return; } - _GLFWwindow* window = NULL; + _GLFWwindow *window = NULL; if (XFindContext(_glfw.x11.display, event->xany.window, _glfw.x11.context, - (XPointer*) &window) != 0) + (XPointer *)&window) != 0) { // This is an event for a window that has already been destroyed return; @@ -1260,601 +1233,604 @@ static void processEvent(XEvent *event) switch (event->type) { - case ReparentNotify: - { - window->x11.parent = event->xreparent.parent; - return; - } + case ReparentNotify: + { + window->x11.parent = event->xreparent.parent; + return; + } - case KeyPress: - { - const int key = translateKey(keycode); - const int mods = translateState(event->xkey.state); - const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); + case KeyPress: + { + const int key = translateKey(keycode); + const int mods = translateState(event->xkey.state); + const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); - if (window->x11.ic) + if (window->x11.ic) + { + // HACK: Do not report the key press events duplicated by XIM + // Duplicate key releases are filtered out implicitly by + // the GLFW key repeat logic in _glfwInputKey + // A timestamp per key is used to handle simultaneous keys + // NOTE: Always allow the first event for each key through + // (the server never sends a timestamp of zero) + // NOTE: Timestamp difference is compared to handle wrap-around + Time diff = event->xkey.time - window->x11.keyPressTimes[keycode]; + if (diff == event->xkey.time || (diff > 0 && diff < ((Time)1 << 31))) { - // HACK: Do not report the key press events duplicated by XIM - // Duplicate key releases are filtered out implicitly by - // the GLFW key repeat logic in _glfwInputKey - // A timestamp per key is used to handle simultaneous keys - // NOTE: Always allow the first event for each key through - // (the server never sends a timestamp of zero) - // NOTE: Timestamp difference is compared to handle wrap-around - Time diff = event->xkey.time - window->x11.keyPressTimes[keycode]; - if (diff == event->xkey.time || (diff > 0 && diff < (1 << 31))) + if (keycode) + _glfwInputKey(window, key, keycode, GLFW_PRESS, mods); + + window->x11.keyPressTimes[keycode] = event->xkey.time; + } + + if (!filtered) + { + int count; + Status status; + char buffer[100]; + char *chars = buffer; + + count = Xutf8LookupString(window->x11.ic, + &event->xkey, + buffer, sizeof(buffer) - 1, + NULL, &status); + + if (status == XBufferOverflow) { - if (keycode) - _glfwInputKey(window, key, keycode, GLFW_PRESS, mods); - - window->x11.keyPressTimes[keycode] = event->xkey.time; - } - - if (!filtered) - { - int count; - Status status; - char buffer[100]; - char* chars = buffer; - + chars = _glfw_calloc(count + 1, 1); count = Xutf8LookupString(window->x11.ic, &event->xkey, - buffer, sizeof(buffer) - 1, + chars, count, NULL, &status); - - if (status == XBufferOverflow) - { - chars = _glfw_calloc(count + 1, 1); - count = Xutf8LookupString(window->x11.ic, - &event->xkey, - chars, count, - NULL, &status); - } - - if (status == XLookupChars || status == XLookupBoth) - { - const char* c = chars; - chars[count] = '\0'; - while (c - chars < count) - _glfwInputChar(window, decodeUTF8(&c), mods, plain); - } - - if (chars != buffer) - _glfw_free(chars); } + + if (status == XLookupChars || status == XLookupBoth) + { + const char *c = chars; + chars[count] = '\0'; + while (c - chars < count) + _glfwInputChar(window, decodeUTF8(&c), mods, plain); + } + + if (chars != buffer) + _glfw_free(chars); + } + } + else + { + KeySym keysym; + XLookupString(&event->xkey, NULL, 0, &keysym, NULL); + + _glfwInputKey(window, key, keycode, GLFW_PRESS, mods); + + const uint32_t codepoint = _glfwKeySym2Unicode(keysym); + if (codepoint != GLFW_INVALID_CODEPOINT) + _glfwInputChar(window, codepoint, mods, plain); + } + + return; + } + + case KeyRelease: + { + const int key = translateKey(keycode); + const int mods = translateState(event->xkey.state); + + if (!_glfw.x11.xkb.detectable) + { + // HACK: Key repeat events will arrive as KeyRelease/KeyPress + // pairs with similar or identical time stamps + // The key repeat logic in _glfwInputKey expects only key + // presses to repeat, so detect and discard release events + if (XEventsQueued(_glfw.x11.display, QueuedAfterReading)) + { + XEvent next; + XPeekEvent(_glfw.x11.display, &next); + + if (next.type == KeyPress && + next.xkey.window == event->xkey.window && + next.xkey.keycode == keycode) + { + // HACK: The time of repeat events sometimes doesn't + // match that of the press event, so add an + // epsilon + // Toshiyuki Takahashi can press a button + // 16 times per second so it's fairly safe to + // assume that no human is pressing the key 50 + // times per second (value is ms) + if ((next.xkey.time - event->xkey.time) < 20) + { + // This is very likely a server-generated key repeat + // event, so ignore it + return; + } + } + } + } + + _glfwInputKey(window, key, keycode, GLFW_RELEASE, mods); + return; + } + + case ButtonPress: + { + const int mods = translateState(event->xbutton.state); + + if (event->xbutton.button == Button1) + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods); + else if (event->xbutton.button == Button2) + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, mods); + else if (event->xbutton.button == Button3) + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, mods); + + // Modern X provides scroll events as mouse button presses + else if (event->xbutton.button == Button4) + _glfwInputScroll(window, 0.0, 1.0); + else if (event->xbutton.button == Button5) + _glfwInputScroll(window, 0.0, -1.0); + else if (event->xbutton.button == Button6) + _glfwInputScroll(window, 1.0, 0.0); + else if (event->xbutton.button == Button7) + _glfwInputScroll(window, -1.0, 0.0); + + else + { + // Additional buttons after 7 are treated as regular buttons + // We subtract 4 to fill the gap left by scroll input above + _glfwInputMouseClick(window, + event->xbutton.button - Button1 - 4, + GLFW_PRESS, + mods); + } + + return; + } + + case ButtonRelease: + { + const int mods = translateState(event->xbutton.state); + + if (event->xbutton.button == Button1) + { + _glfwInputMouseClick(window, + GLFW_MOUSE_BUTTON_LEFT, + GLFW_RELEASE, + mods); + } + else if (event->xbutton.button == Button2) + { + _glfwInputMouseClick(window, + GLFW_MOUSE_BUTTON_MIDDLE, + GLFW_RELEASE, + mods); + } + else if (event->xbutton.button == Button3) + { + _glfwInputMouseClick(window, + GLFW_MOUSE_BUTTON_RIGHT, + GLFW_RELEASE, + mods); + } + else if (event->xbutton.button > Button7) + { + // Additional buttons after 7 are treated as regular buttons + // We subtract 4 to fill the gap left by scroll input above + _glfwInputMouseClick(window, + event->xbutton.button - Button1 - 4, + GLFW_RELEASE, + mods); + } + + return; + } + + case EnterNotify: + { + // XEnterWindowEvent is XCrossingEvent + const int x = event->xcrossing.x; + const int y = event->xcrossing.y; + + // HACK: This is a workaround for WMs (KWM, Fluxbox) that otherwise + // ignore the defined cursor for hidden cursor mode + if (window->cursorMode == GLFW_CURSOR_HIDDEN) + updateCursorImage(window); + + _glfwInputCursorEnter(window, GLFW_TRUE); + _glfwInputCursorPos(window, x, y); + + window->x11.lastCursorPosX = x; + window->x11.lastCursorPosY = y; + return; + } + + case LeaveNotify: + { + _glfwInputCursorEnter(window, GLFW_FALSE); + return; + } + + case MotionNotify: + { + const int x = event->xmotion.x; + const int y = event->xmotion.y; + + if (x != window->x11.warpCursorPosX || + y != window->x11.warpCursorPosY) + { + // The cursor was moved by something other than GLFW + + if (window->cursorMode == GLFW_CURSOR_DISABLED) + { + if (_glfw.x11.disabledCursorWindow != window) + return; + if (window->rawMouseMotion) + return; + + const int dx = x - window->x11.lastCursorPosX; + const int dy = y - window->x11.lastCursorPosY; + + _glfwInputCursorPos(window, + window->virtualCursorPosX + dx, + window->virtualCursorPosY + dy); + } + else + _glfwInputCursorPos(window, x, y); + } + + window->x11.lastCursorPosX = x; + window->x11.lastCursorPosY = y; + return; + } + + case ConfigureNotify: + { + if (event->xconfigure.width != window->x11.width || + event->xconfigure.height != window->x11.height) + { + _glfwInputFramebufferSize(window, + event->xconfigure.width, + event->xconfigure.height); + + _glfwInputWindowSize(window, + event->xconfigure.width, + event->xconfigure.height); + + window->x11.width = event->xconfigure.width; + window->x11.height = event->xconfigure.height; + } + + int xpos = event->xconfigure.x; + int ypos = event->xconfigure.y; + + // NOTE: ConfigureNotify events from the server are in local + // coordinates, so if we are reparented we need to translate + // the position into root (screen) coordinates + if (!event->xany.send_event && window->x11.parent != _glfw.x11.root) + { + _glfwGrabErrorHandlerX11(); + + Window dummy; + XTranslateCoordinates(_glfw.x11.display, + window->x11.parent, + _glfw.x11.root, + xpos, ypos, + &xpos, &ypos, + &dummy); + + _glfwReleaseErrorHandlerX11(); + if (_glfw.x11.errorCode == BadWindow) + return; + } + + if (xpos != window->x11.xpos || ypos != window->x11.ypos) + { + _glfwInputWindowPos(window, xpos, ypos); + window->x11.xpos = xpos; + window->x11.ypos = ypos; + } + + return; + } + + case ClientMessage: + { + // Custom client message, probably from the window manager + + if (filtered) + return; + + if (event->xclient.message_type == None) + return; + + if (event->xclient.message_type == _glfw.x11.WM_PROTOCOLS) + { + const Atom protocol = event->xclient.data.l[0]; + if (protocol == None) + return; + + if (protocol == _glfw.x11.WM_DELETE_WINDOW) + { + // The window manager was asked to close the window, for + // example by the user pressing a 'close' window decoration + // button + _glfwInputWindowCloseRequest(window); + } + else if (protocol == _glfw.x11.NET_WM_PING) + { + // The window manager is pinging the application to ensure + // it's still responding to events + + XEvent reply = *event; + reply.xclient.window = _glfw.x11.root; + + XSendEvent(_glfw.x11.display, _glfw.x11.root, + False, + SubstructureNotifyMask | SubstructureRedirectMask, + &reply); + } + } + else if (event->xclient.message_type == _glfw.x11.XdndEnter) + { + // A drag operation has entered the window + unsigned long count; + Atom *formats = NULL; + const GLFWbool list = event->xclient.data.l[1] & 1; + + _glfw.x11.xdnd.source = event->xclient.data.l[0]; + _glfw.x11.xdnd.version = event->xclient.data.l[1] >> 24; + _glfw.x11.xdnd.format = None; + + if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION) + return; + + if (list) + { + count = _glfwGetWindowPropertyX11(_glfw.x11.xdnd.source, + _glfw.x11.XdndTypeList, + XA_ATOM, + (unsigned char **)&formats); } else { - KeySym keysym; - XLookupString(&event->xkey, NULL, 0, &keysym, NULL); - - _glfwInputKey(window, key, keycode, GLFW_PRESS, mods); - - const long character = _glfwKeySym2Unicode(keysym); - if (character != -1) - _glfwInputChar(window, character, mods, plain); + count = 3; + formats = (Atom *)event->xclient.data.l + 2; } - return; - } - - case KeyRelease: - { - const int key = translateKey(keycode); - const int mods = translateState(event->xkey.state); - - if (!_glfw.x11.xkb.detectable) + for (unsigned int i = 0; i < count; i++) { - // HACK: Key repeat events will arrive as KeyRelease/KeyPress - // pairs with similar or identical time stamps - // The key repeat logic in _glfwInputKey expects only key - // presses to repeat, so detect and discard release events - if (XEventsQueued(_glfw.x11.display, QueuedAfterReading)) + if (formats[i] == _glfw.x11.text_uri_list) { - XEvent next; - XPeekEvent(_glfw.x11.display, &next); - - if (next.type == KeyPress && - next.xkey.window == event->xkey.window && - next.xkey.keycode == keycode) - { - // HACK: The time of repeat events sometimes doesn't - // match that of the press event, so add an - // epsilon - // Toshiyuki Takahashi can press a button - // 16 times per second so it's fairly safe to - // assume that no human is pressing the key 50 - // times per second (value is ms) - if ((next.xkey.time - event->xkey.time) < 20) - { - // This is very likely a server-generated key repeat - // event, so ignore it - return; - } - } + _glfw.x11.xdnd.format = _glfw.x11.text_uri_list; + break; } } - _glfwInputKey(window, key, keycode, GLFW_RELEASE, mods); - return; + if (list && formats) + XFree(formats); } - - case ButtonPress: + else if (event->xclient.message_type == _glfw.x11.XdndDrop) { - const int mods = translateState(event->xbutton.state); + // The drag operation has finished by dropping on the window + Time time = CurrentTime; - if (event->xbutton.button == Button1) - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods); - else if (event->xbutton.button == Button2) - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, mods); - else if (event->xbutton.button == Button3) - _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, mods); - - // Modern X provides scroll events as mouse button presses - else if (event->xbutton.button == Button4) - _glfwInputScroll(window, 0.0, 1.0); - else if (event->xbutton.button == Button5) - _glfwInputScroll(window, 0.0, -1.0); - else if (event->xbutton.button == Button6) - _glfwInputScroll(window, 1.0, 0.0); - else if (event->xbutton.button == Button7) - _glfwInputScroll(window, -1.0, 0.0); - - else - { - // Additional buttons after 7 are treated as regular buttons - // We subtract 4 to fill the gap left by scroll input above - _glfwInputMouseClick(window, - event->xbutton.button - Button1 - 4, - GLFW_PRESS, - mods); - } - - return; - } - - case ButtonRelease: - { - const int mods = translateState(event->xbutton.state); - - if (event->xbutton.button == Button1) - { - _glfwInputMouseClick(window, - GLFW_MOUSE_BUTTON_LEFT, - GLFW_RELEASE, - mods); - } - else if (event->xbutton.button == Button2) - { - _glfwInputMouseClick(window, - GLFW_MOUSE_BUTTON_MIDDLE, - GLFW_RELEASE, - mods); - } - else if (event->xbutton.button == Button3) - { - _glfwInputMouseClick(window, - GLFW_MOUSE_BUTTON_RIGHT, - GLFW_RELEASE, - mods); - } - else if (event->xbutton.button > Button7) - { - // Additional buttons after 7 are treated as regular buttons - // We subtract 4 to fill the gap left by scroll input above - _glfwInputMouseClick(window, - event->xbutton.button - Button1 - 4, - GLFW_RELEASE, - mods); - } - - return; - } - - case EnterNotify: - { - // XEnterWindowEvent is XCrossingEvent - const int x = event->xcrossing.x; - const int y = event->xcrossing.y; - - // HACK: This is a workaround for WMs (KWM, Fluxbox) that otherwise - // ignore the defined cursor for hidden cursor mode - if (window->cursorMode == GLFW_CURSOR_HIDDEN) - updateCursorImage(window); - - _glfwInputCursorEnter(window, GLFW_TRUE); - _glfwInputCursorPos(window, x, y); - - window->x11.lastCursorPosX = x; - window->x11.lastCursorPosY = y; - return; - } - - case LeaveNotify: - { - _glfwInputCursorEnter(window, GLFW_FALSE); - return; - } - - case MotionNotify: - { - const int x = event->xmotion.x; - const int y = event->xmotion.y; - - if (x != window->x11.warpCursorPosX || - y != window->x11.warpCursorPosY) - { - // The cursor was moved by something other than GLFW - - if (window->cursorMode == GLFW_CURSOR_DISABLED) - { - if (_glfw.x11.disabledCursorWindow != window) - return; - if (window->rawMouseMotion) - return; - - const int dx = x - window->x11.lastCursorPosX; - const int dy = y - window->x11.lastCursorPosY; - - _glfwInputCursorPos(window, - window->virtualCursorPosX + dx, - window->virtualCursorPosY + dy); - } - else - _glfwInputCursorPos(window, x, y); - } - - window->x11.lastCursorPosX = x; - window->x11.lastCursorPosY = y; - return; - } - - case ConfigureNotify: - { - if (event->xconfigure.width != window->x11.width || - event->xconfigure.height != window->x11.height) - { - _glfwInputFramebufferSize(window, - event->xconfigure.width, - event->xconfigure.height); - - _glfwInputWindowSize(window, - event->xconfigure.width, - event->xconfigure.height); - - window->x11.width = event->xconfigure.width; - window->x11.height = event->xconfigure.height; - } - - int xpos = event->xconfigure.x; - int ypos = event->xconfigure.y; - - // NOTE: ConfigureNotify events from the server are in local - // coordinates, so if we are reparented we need to translate - // the position into root (screen) coordinates - if (!event->xany.send_event && window->x11.parent != _glfw.x11.root) - { - _glfwGrabErrorHandlerX11(); - - Window dummy; - XTranslateCoordinates(_glfw.x11.display, - window->x11.parent, - _glfw.x11.root, - xpos, ypos, - &xpos, &ypos, - &dummy); - - _glfwReleaseErrorHandlerX11(); - if (_glfw.x11.errorCode == BadWindow) - return; - } - - if (xpos != window->x11.xpos || ypos != window->x11.ypos) - { - _glfwInputWindowPos(window, xpos, ypos); - window->x11.xpos = xpos; - window->x11.ypos = ypos; - } - - return; - } - - case ClientMessage: - { - // Custom client message, probably from the window manager - - if (filtered) + if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION) return; - if (event->xclient.message_type == None) - return; - - if (event->xclient.message_type == _glfw.x11.WM_PROTOCOLS) + if (_glfw.x11.xdnd.format) { - const Atom protocol = event->xclient.data.l[0]; - if (protocol == None) - return; + if (_glfw.x11.xdnd.version >= 1) + time = event->xclient.data.l[2]; - if (protocol == _glfw.x11.WM_DELETE_WINDOW) - { - // The window manager was asked to close the window, for - // example by the user pressing a 'close' window decoration - // button - _glfwInputWindowCloseRequest(window); - } - else if (protocol == _glfw.x11.NET_WM_PING) - { - // The window manager is pinging the application to ensure - // it's still responding to events - - XEvent reply = *event; - reply.xclient.window = _glfw.x11.root; - - XSendEvent(_glfw.x11.display, _glfw.x11.root, - False, - SubstructureNotifyMask | SubstructureRedirectMask, - &reply); - } + // Request the chosen format from the source window + XConvertSelection(_glfw.x11.display, + _glfw.x11.XdndSelection, + _glfw.x11.xdnd.format, + _glfw.x11.XdndSelection, + window->x11.handle, + time); } - else if (event->xclient.message_type == _glfw.x11.XdndEnter) + else if (_glfw.x11.xdnd.version >= 2) { - // A drag operation has entered the window - unsigned long i, count; - Atom* formats = NULL; - const GLFWbool list = event->xclient.data.l[1] & 1; - - _glfw.x11.xdnd.source = event->xclient.data.l[0]; - _glfw.x11.xdnd.version = event->xclient.data.l[1] >> 24; - _glfw.x11.xdnd.format = None; - - if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION) - return; - - if (list) - { - count = _glfwGetWindowPropertyX11(_glfw.x11.xdnd.source, - _glfw.x11.XdndTypeList, - XA_ATOM, - (unsigned char**) &formats); - } - else - { - count = 3; - formats = (Atom*) event->xclient.data.l + 2; - } - - for (i = 0; i < count; i++) - { - if (formats[i] == _glfw.x11.text_uri_list) - { - _glfw.x11.xdnd.format = _glfw.x11.text_uri_list; - break; - } - } - - if (list && formats) - XFree(formats); - } - else if (event->xclient.message_type == _glfw.x11.XdndDrop) - { - // The drag operation has finished by dropping on the window - Time time = CurrentTime; - - if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION) - return; - - if (_glfw.x11.xdnd.format) - { - if (_glfw.x11.xdnd.version >= 1) - time = event->xclient.data.l[2]; - - // Request the chosen format from the source window - XConvertSelection(_glfw.x11.display, - _glfw.x11.XdndSelection, - _glfw.x11.xdnd.format, - _glfw.x11.XdndSelection, - window->x11.handle, - time); - } - else if (_glfw.x11.xdnd.version >= 2) - { - XEvent reply = { ClientMessage }; - reply.xclient.window = _glfw.x11.xdnd.source; - reply.xclient.message_type = _glfw.x11.XdndFinished; - reply.xclient.format = 32; - reply.xclient.data.l[0] = window->x11.handle; - reply.xclient.data.l[1] = 0; // The drag was rejected - reply.xclient.data.l[2] = None; - - XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source, - False, NoEventMask, &reply); - XFlush(_glfw.x11.display); - } - } - else if (event->xclient.message_type == _glfw.x11.XdndPosition) - { - // The drag operation has moved over the window - const int xabs = (event->xclient.data.l[2] >> 16) & 0xffff; - const int yabs = (event->xclient.data.l[2]) & 0xffff; - Window dummy; - int xpos, ypos; - - if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION) - return; - - XTranslateCoordinates(_glfw.x11.display, - _glfw.x11.root, - window->x11.handle, - xabs, yabs, - &xpos, &ypos, - &dummy); - - _glfwInputCursorPos(window, xpos, ypos); - - XEvent reply = { ClientMessage }; + XEvent reply = {ClientMessage}; reply.xclient.window = _glfw.x11.xdnd.source; - reply.xclient.message_type = _glfw.x11.XdndStatus; + reply.xclient.message_type = _glfw.x11.XdndFinished; reply.xclient.format = 32; reply.xclient.data.l[0] = window->x11.handle; - reply.xclient.data.l[2] = 0; // Specify an empty rectangle - reply.xclient.data.l[3] = 0; - - if (_glfw.x11.xdnd.format) - { - // Reply that we are ready to copy the dragged data - reply.xclient.data.l[1] = 1; // Accept with no rectangle - if (_glfw.x11.xdnd.version >= 2) - reply.xclient.data.l[4] = _glfw.x11.XdndActionCopy; - } + reply.xclient.data.l[1] = 0; // The drag was rejected + reply.xclient.data.l[2] = None; XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source, False, NoEventMask, &reply); XFlush(_glfw.x11.display); } - - return; } - - case SelectionNotify: + else if (event->xclient.message_type == _glfw.x11.XdndPosition) { - if (event->xselection.property == _glfw.x11.XdndSelection) + // The drag operation has moved over the window + const int xabs = (event->xclient.data.l[2] >> 16) & 0xffff; + const int yabs = (event->xclient.data.l[2]) & 0xffff; + Window dummy; + int xpos, ypos; + + if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION) + return; + + XTranslateCoordinates(_glfw.x11.display, + _glfw.x11.root, + window->x11.handle, + xabs, yabs, + &xpos, &ypos, + &dummy); + + _glfwInputCursorPos(window, xpos, ypos); + + XEvent reply = {ClientMessage}; + reply.xclient.window = _glfw.x11.xdnd.source; + reply.xclient.message_type = _glfw.x11.XdndStatus; + reply.xclient.format = 32; + reply.xclient.data.l[0] = window->x11.handle; + reply.xclient.data.l[2] = 0; // Specify an empty rectangle + reply.xclient.data.l[3] = 0; + + if (_glfw.x11.xdnd.format) { - // The converted data from the drag operation has arrived - char* data; - const unsigned long result = - _glfwGetWindowPropertyX11(event->xselection.requestor, - event->xselection.property, - event->xselection.target, - (unsigned char**) &data); - - if (result) - { - int i, count; - char** paths = parseUriList(data, &count); - - _glfwInputDrop(window, count, (const char**) paths); - - for (i = 0; i < count; i++) - _glfw_free(paths[i]); - _glfw_free(paths); - } - - if (data) - XFree(data); - + // Reply that we are ready to copy the dragged data + reply.xclient.data.l[1] = 1; // Accept with no rectangle if (_glfw.x11.xdnd.version >= 2) - { - XEvent reply = { ClientMessage }; - reply.xclient.window = _glfw.x11.xdnd.source; - reply.xclient.message_type = _glfw.x11.XdndFinished; - reply.xclient.format = 32; - reply.xclient.data.l[0] = window->x11.handle; - reply.xclient.data.l[1] = result; - reply.xclient.data.l[2] = _glfw.x11.XdndActionCopy; - - XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source, - False, NoEventMask, &reply); - XFlush(_glfw.x11.display); - } + reply.xclient.data.l[4] = _glfw.x11.XdndActionCopy; } - return; + XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source, + False, NoEventMask, &reply); + XFlush(_glfw.x11.display); } - case FocusIn: + return; + } + + case SelectionNotify: + { + if (event->xselection.property == _glfw.x11.XdndSelection) { - if (event->xfocus.mode == NotifyGrab || - event->xfocus.mode == NotifyUngrab) + // The converted data from the drag operation has arrived + char *data; + const unsigned long result = + _glfwGetWindowPropertyX11(event->xselection.requestor, + event->xselection.property, + event->xselection.target, + (unsigned char **)&data); + + if (result) { - // Ignore focus events from popup indicator windows, window menu - // key chords and window dragging - return; + int count; + char **paths = _glfwParseUriList(data, &count); + + _glfwInputDrop(window, count, (const char **)paths); + + for (int i = 0; i < count; i++) + _glfw_free(paths[i]); + _glfw_free(paths); } - if (window->cursorMode == GLFW_CURSOR_DISABLED) - disableCursor(window); + if (data) + XFree(data); - if (window->x11.ic) - XSetICFocus(window->x11.ic); - - _glfwInputWindowFocus(window, GLFW_TRUE); - return; - } - - case FocusOut: - { - if (event->xfocus.mode == NotifyGrab || - event->xfocus.mode == NotifyUngrab) + if (_glfw.x11.xdnd.version >= 2) { - // Ignore focus events from popup indicator windows, window menu - // key chords and window dragging - return; + XEvent reply = {ClientMessage}; + reply.xclient.window = _glfw.x11.xdnd.source; + reply.xclient.message_type = _glfw.x11.XdndFinished; + reply.xclient.format = 32; + reply.xclient.data.l[0] = window->x11.handle; + reply.xclient.data.l[1] = result; + reply.xclient.data.l[2] = _glfw.x11.XdndActionCopy; + + XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source, + False, NoEventMask, &reply); + XFlush(_glfw.x11.display); } + } - if (window->cursorMode == GLFW_CURSOR_DISABLED) - enableCursor(window); + return; + } - if (window->x11.ic) - XUnsetICFocus(window->x11.ic); - - if (window->monitor && window->autoIconify) - _glfwPlatformIconifyWindow(window); - - _glfwInputWindowFocus(window, GLFW_FALSE); + case FocusIn: + { + if (event->xfocus.mode == NotifyGrab || + event->xfocus.mode == NotifyUngrab) + { + // Ignore focus events from popup indicator windows, window menu + // key chords and window dragging return; } - case Expose: + if (window->cursorMode == GLFW_CURSOR_DISABLED) + disableCursor(window); + else if (window->cursorMode == GLFW_CURSOR_CAPTURED) + captureCursor(window); + + if (window->x11.ic) + XSetICFocus(window->x11.ic); + + _glfwInputWindowFocus(window, GLFW_TRUE); + return; + } + + case FocusOut: + { + if (event->xfocus.mode == NotifyGrab || + event->xfocus.mode == NotifyUngrab) { - _glfwInputWindowDamage(window); + // Ignore focus events from popup indicator windows, window menu + // key chords and window dragging return; } - case PropertyNotify: + if (window->cursorMode == GLFW_CURSOR_DISABLED) + enableCursor(window); + else if (window->cursorMode == GLFW_CURSOR_CAPTURED) + releaseCursor(); + + if (window->x11.ic) + XUnsetICFocus(window->x11.ic); + + if (window->monitor && window->autoIconify) + _glfwIconifyWindowX11(window); + + _glfwInputWindowFocus(window, GLFW_FALSE); + return; + } + + case Expose: + { + _glfwInputWindowDamage(window); + return; + } + + case PropertyNotify: + { + if (event->xproperty.state != PropertyNewValue) + return; + + if (event->xproperty.atom == _glfw.x11.WM_STATE) { - if (event->xproperty.state != PropertyNewValue) + const int state = getWindowState(window); + if (state != IconicState && state != NormalState) return; - if (event->xproperty.atom == _glfw.x11.WM_STATE) + const GLFWbool iconified = (state == IconicState); + if (window->x11.iconified != iconified) { - const int state = getWindowState(window); - if (state != IconicState && state != NormalState) - return; - - const GLFWbool iconified = (state == IconicState); - if (window->x11.iconified != iconified) + if (window->monitor) { - if (window->monitor) - { - if (iconified) - releaseMonitor(window); - else - acquireMonitor(window); - } - - window->x11.iconified = iconified; - _glfwInputWindowIconify(window, iconified); + if (iconified) + releaseMonitor(window); + else + acquireMonitor(window); } + + window->x11.iconified = iconified; + _glfwInputWindowIconify(window, iconified); } - else if (event->xproperty.atom == _glfw.x11.NET_WM_STATE) + } + else if (event->xproperty.atom == _glfw.x11.NET_WM_STATE) + { + const GLFWbool maximized = _glfwWindowMaximizedX11(window); + if (window->x11.maximized != maximized) { - const GLFWbool maximized = _glfwPlatformWindowMaximized(window); - if (window->x11.maximized != maximized) - { - window->x11.maximized = maximized; - _glfwInputWindowMaximize(window, maximized); - } + window->x11.maximized = maximized; + _glfwInputWindowMaximize(window, maximized); } - - return; } - case DestroyNotify: - return; + return; + } + + case DestroyNotify: + return; } } - ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// @@ -1865,7 +1841,7 @@ static void processEvent(XEvent *event) unsigned long _glfwGetWindowPropertyX11(Window window, Atom property, Atom type, - unsigned char** value) + unsigned char **value) { Atom actualType; int actualFormat; @@ -1887,12 +1863,12 @@ unsigned long _glfwGetWindowPropertyX11(Window window, return itemCount; } -GLFWbool _glfwIsVisualTransparentX11(Visual* visual) +GLFWbool _glfwIsVisualTransparentX11(Visual *visual) { if (!_glfw.x11.xrender.available) return GLFW_FALSE; - XRenderPictFormat* pf = XRenderFindVisualFormat(_glfw.x11.display, visual); + XRenderPictFormat *pf = XRenderFindVisualFormat(_glfw.x11.display, visual); return pf && pf->direct.alphaMask; } @@ -1915,40 +1891,36 @@ void _glfwPushSelectionToManagerX11(void) { switch (event.type) { - case SelectionRequest: - handleSelectionRequest(&event); - break; + case SelectionRequest: + handleSelectionRequest(&event); + break; - case SelectionClear: - handleSelectionClear(&event); - break; - - case SelectionNotify: + case SelectionNotify: + { + if (event.xselection.target == _glfw.x11.SAVE_TARGETS) { - if (event.xselection.target == _glfw.x11.SAVE_TARGETS) - { - // This means one of two things; either the selection - // was not owned, which means there is no clipboard - // manager, or the transfer to the clipboard manager has - // completed - // In either case, it means we are done here - return; - } - - break; + // This means one of two things; either the selection + // was not owned, which means there is no clipboard + // manager, or the transfer to the clipboard manager has + // completed + // In either case, it means we are done here + return; } + + break; + } } } - waitForEvent(NULL); + waitForX11Event(NULL); } } -void _glfwCreateInputContextX11(_GLFWwindow* window) +void _glfwCreateInputContextX11(_GLFWwindow *window) { XIMCallback callback; - callback.callback = (XIMProc) inputContextDestroyCallback; - callback.client_data = (XPointer) window; + callback.callback = (XIMProc)inputContextDestroyCallback; + callback.client_data = (XPointer)window; window->x11.ic = XCreateIC(_glfw.x11.im, XNInputStyle, @@ -1976,17 +1948,16 @@ void _glfwCreateInputContextX11(_GLFWwindow* window) } } - ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -int _glfwPlatformCreateWindow(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig) +GLFWbool _glfwCreateWindowX11(_GLFWwindow *window, + const _GLFWwndconfig *wndconfig, + const _GLFWctxconfig *ctxconfig, + const _GLFWfbconfig *fbconfig) { - Visual* visual = NULL; + Visual *visual = NULL; int depth; if (ctxconfig->client != GLFW_NO_API) @@ -2038,23 +2009,41 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig)) return GLFW_FALSE; } + + if (!_glfwRefreshContextAttribs(window, ctxconfig)) + return GLFW_FALSE; } + if (wndconfig->mousePassthrough) + _glfwSetWindowMousePassthroughX11(window, GLFW_TRUE); + if (window->monitor) { - _glfwPlatformShowWindow(window); + _glfwShowWindowX11(window); updateWindowMode(window); acquireMonitor(window); + + if (wndconfig->centerCursor) + _glfwCenterCursorInContentArea(window); + } + else + { + if (wndconfig->visible) + { + _glfwShowWindowX11(window); + if (wndconfig->focused) + _glfwFocusWindowX11(window); + } } XFlush(_glfw.x11.display); return GLFW_TRUE; } -void _glfwPlatformDestroyWindow(_GLFWwindow* window) +void _glfwDestroyWindowX11(_GLFWwindow *window) { if (_glfw.x11.disabledCursorWindow == window) - _glfw.x11.disabledCursorWindow = NULL; + enableCursor(window); if (window->monitor) releaseMonitor(window); @@ -2073,19 +2062,19 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) XDeleteContext(_glfw.x11.display, window->x11.handle, _glfw.x11.context); XUnmapWindow(_glfw.x11.display, window->x11.handle); XDestroyWindow(_glfw.x11.display, window->x11.handle); - window->x11.handle = (Window) 0; + window->x11.handle = (Window)0; } if (window->x11.colormap) { XFreeColormap(_glfw.x11.display, window->x11.colormap); - window->x11.colormap = (Colormap) 0; + window->x11.colormap = (Colormap)0; } XFlush(_glfw.x11.display); } -void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) +void _glfwSetWindowTitleX11(_GLFWwindow *window, const char *title) { if (_glfw.x11.xlib.utf8) { @@ -2096,51 +2085,56 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) NULL, NULL, NULL); } - XChangeProperty(_glfw.x11.display, window->x11.handle, + XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_NAME, _glfw.x11.UTF8_STRING, 8, PropModeReplace, - (unsigned char*) title, strlen(title)); + (unsigned char *)title, strlen(title)); - XChangeProperty(_glfw.x11.display, window->x11.handle, + XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_ICON_NAME, _glfw.x11.UTF8_STRING, 8, PropModeReplace, - (unsigned char*) title, strlen(title)); + (unsigned char *)title, strlen(title)); XFlush(_glfw.x11.display); } -void _glfwPlatformSetWindowIcon(_GLFWwindow* window, - int count, const GLFWimage* images) +void _glfwSetWindowIconX11(_GLFWwindow *window, int count, const GLFWimage *images) { if (count) { - int i, j, longCount = 0; + int longCount = 0; - for (i = 0; i < count; i++) + for (int i = 0; i < count; i++) longCount += 2 + images[i].width * images[i].height; - long* icon = _glfw_calloc(longCount, sizeof(long)); - long* target = icon; + unsigned long *icon = _glfw_calloc(longCount, sizeof(unsigned long)); + unsigned long *target = icon; - for (i = 0; i < count; i++) + for (int i = 0; i < count; i++) { *target++ = images[i].width; *target++ = images[i].height; - for (j = 0; j < images[i].width * images[i].height; j++) + for (int j = 0; j < images[i].width * images[i].height; j++) { - *target++ = (images[i].pixels[j * 4 + 0] << 16) | - (images[i].pixels[j * 4 + 1] << 8) | - (images[i].pixels[j * 4 + 2] << 0) | - (images[i].pixels[j * 4 + 3] << 24); + *target++ = (((unsigned long)images[i].pixels[j * 4 + 0]) << 16) | + (((unsigned long)images[i].pixels[j * 4 + 1]) << 8) | + (((unsigned long)images[i].pixels[j * 4 + 2]) << 0) | + (((unsigned long)images[i].pixels[j * 4 + 3]) << 24); } } + // NOTE: XChangeProperty expects 32-bit values like the image data above to be + // placed in the 32 least significant bits of individual longs. This is + // true even if long is 64-bit and a WM protocol calls for "packed" data. + // This is because of a historical mistake that then became part of the Xlib + // ABI. Xlib will pack these values into a regular array of 32-bit values + // before sending it over the wire. XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, - (unsigned char*) icon, + (unsigned char *)icon, longCount); _glfw_free(icon); @@ -2154,7 +2148,7 @@ void _glfwPlatformSetWindowIcon(_GLFWwindow* window, XFlush(_glfw.x11.display); } -void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) +void _glfwGetWindowPosX11(_GLFWwindow *window, int *xpos, int *ypos) { Window dummy; int x, y; @@ -2168,14 +2162,14 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) *ypos = y; } -void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) +void _glfwSetWindowPosX11(_GLFWwindow *window, int xpos, int ypos) { // HACK: Explicitly setting PPosition to any value causes some WMs, notably // Compiz and Metacity, to honor the position of unmapped windows - if (!_glfwPlatformWindowVisible(window)) + if (!_glfwWindowVisibleX11(window)) { long supplied; - XSizeHints* hints = XAllocSizeHints(); + XSizeHints *hints = XAllocSizeHints(); if (XGetWMNormalHints(_glfw.x11.display, window->x11.handle, hints, &supplied)) { @@ -2192,7 +2186,7 @@ void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) XFlush(_glfw.x11.display); } -void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) +void _glfwGetWindowSizeX11(_GLFWwindow *window, int *width, int *height) { XWindowAttributes attribs; XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &attribs); @@ -2203,7 +2197,7 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) *height = attribs.height; } -void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) +void _glfwSetWindowSizeX11(_GLFWwindow *window, int width, int height) { if (window->monitor) { @@ -2221,34 +2215,34 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) XFlush(_glfw.x11.display); } -void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, - int minwidth, int minheight, - int maxwidth, int maxheight) +void _glfwSetWindowSizeLimitsX11(_GLFWwindow *window, + int minwidth, int minheight, + int maxwidth, int maxheight) { int width, height; - _glfwPlatformGetWindowSize(window, &width, &height); + _glfwGetWindowSizeX11(window, &width, &height); updateNormalHints(window, width, height); XFlush(_glfw.x11.display); } -void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom) +void _glfwSetWindowAspectRatioX11(_GLFWwindow *window, int numer, int denom) { int width, height; - _glfwPlatformGetWindowSize(window, &width, &height); + _glfwGetWindowSizeX11(window, &width, &height); updateNormalHints(window, width, height); XFlush(_glfw.x11.display); } -void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) +void _glfwGetFramebufferSizeX11(_GLFWwindow *window, int *width, int *height) { - _glfwPlatformGetWindowSize(window, width, height); + _glfwGetWindowSizeX11(window, width, height); } -void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, - int* left, int* top, - int* right, int* bottom) +void _glfwGetWindowFrameSizeX11(_GLFWwindow *window, + int *left, int *top, + int *right, int *bottom) { - long* extents = NULL; + long *extents = NULL; if (window->monitor || !window->decorated) return; @@ -2256,7 +2250,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, if (_glfw.x11.NET_FRAME_EXTENTS == None) return; - if (!_glfwPlatformWindowVisible(window) && + if (!_glfwWindowVisibleX11(window) && _glfw.x11.NET_REQUEST_FRAME_EXTENTS) { XEvent event; @@ -2275,9 +2269,9 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, while (!XCheckIfEvent(_glfw.x11.display, &event, isFrameExtentsEvent, - (XPointer) window)) + (XPointer)window)) { - if (!waitForEvent(&timeout)) + if (!waitForX11Event(&timeout)) { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue"); @@ -2289,7 +2283,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, if (_glfwGetWindowPropertyX11(window->x11.handle, _glfw.x11.NET_FRAME_EXTENTS, XA_CARDINAL, - (unsigned char**) &extents) == 4) + (unsigned char **)&extents) == 4) { if (left) *left = extents[0]; @@ -2305,8 +2299,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, XFree(extents); } -void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, - float* xscale, float* yscale) +void _glfwGetWindowContentScaleX11(_GLFWwindow *window, float *xscale, float *yscale) { if (xscale) *xscale = _glfw.x11.contentScaleX; @@ -2314,7 +2307,7 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, *yscale = _glfw.x11.contentScaleY; } -void _glfwPlatformIconifyWindow(_GLFWwindow* window) +void _glfwIconifyWindowX11(_GLFWwindow *window) { if (window->x11.overrideRedirect) { @@ -2329,7 +2322,7 @@ void _glfwPlatformIconifyWindow(_GLFWwindow* window) XFlush(_glfw.x11.display); } -void _glfwPlatformRestoreWindow(_GLFWwindow* window) +void _glfwRestoreWindowX11(_GLFWwindow *window) { if (window->x11.overrideRedirect) { @@ -2340,12 +2333,12 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) return; } - if (_glfwPlatformWindowIconified(window)) + if (_glfwWindowIconifiedX11(window)) { XMapWindow(_glfw.x11.display, window->x11.handle); waitForVisibilityNotify(window); } - else if (_glfwPlatformWindowVisible(window)) + else if (_glfwWindowVisibleX11(window)) { if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT && @@ -2363,7 +2356,7 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) XFlush(_glfw.x11.display); } -void _glfwPlatformMaximizeWindow(_GLFWwindow* window) +void _glfwMaximizeWindowX11(_GLFWwindow *window) { if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT || @@ -2372,37 +2365,36 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window) return; } - if (_glfwPlatformWindowVisible(window)) + if (_glfwWindowVisibleX11(window)) { sendEventToWM(window, - _glfw.x11.NET_WM_STATE, - _NET_WM_STATE_ADD, - _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT, - _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ, - 1, 0); + _glfw.x11.NET_WM_STATE, + _NET_WM_STATE_ADD, + _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT, + _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ, + 1, 0); } else { - Atom* states = NULL; + Atom *states = NULL; unsigned long count = _glfwGetWindowPropertyX11(window->x11.handle, _glfw.x11.NET_WM_STATE, XA_ATOM, - (unsigned char**) &states); + (unsigned char **)&states); // NOTE: We don't check for failure as this property may not exist yet // and that's fine (and we'll create it implicitly with append) Atom missing[2] = - { - _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT, - _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ - }; + { + _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT, + _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ}; unsigned long missingCount = 2; - for (unsigned long i = 0; i < count; i++) + for (unsigned long i = 0; i < count; i++) { - for (unsigned long j = 0; j < missingCount; j++) + for (unsigned long j = 0; j < missingCount; j++) { if (states[i] == missing[j]) { @@ -2421,29 +2413,29 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window) XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_STATE, XA_ATOM, 32, PropModeAppend, - (unsigned char*) missing, + (unsigned char *)missing, missingCount); } XFlush(_glfw.x11.display); } -void _glfwPlatformShowWindow(_GLFWwindow* window) +void _glfwShowWindowX11(_GLFWwindow *window) { - if (_glfwPlatformWindowVisible(window)) + if (_glfwWindowVisibleX11(window)) return; XMapWindow(_glfw.x11.display, window->x11.handle); waitForVisibilityNotify(window); } -void _glfwPlatformHideWindow(_GLFWwindow* window) +void _glfwHideWindowX11(_GLFWwindow *window) { XUnmapWindow(_glfw.x11.display, window->x11.handle); XFlush(_glfw.x11.display); } -void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) +void _glfwRequestWindowAttentionX11(_GLFWwindow *window) { if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION) return; @@ -2455,11 +2447,11 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) 0, 1, 0); } -void _glfwPlatformFocusWindow(_GLFWwindow* window) +void _glfwFocusWindowX11(_GLFWwindow *window) { if (_glfw.x11.NET_ACTIVE_WINDOW) sendEventToWM(window, _glfw.x11.NET_ACTIVE_WINDOW, 1, 0, 0, 0, 0); - else if (_glfwPlatformWindowVisible(window)) + else if (_glfwWindowVisibleX11(window)) { XRaiseWindow(_glfw.x11.display, window->x11.handle); XSetInputFocus(_glfw.x11.display, window->x11.handle, @@ -2469,11 +2461,11 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window) XFlush(_glfw.x11.display); } -void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, - _GLFWmonitor* monitor, - int xpos, int ypos, - int width, int height, - int refreshRate) +void _glfwSetWindowMonitorX11(_GLFWwindow *window, + _GLFWmonitor *monitor, + int xpos, int ypos, + int width, int height, + int refreshRate) { if (window->monitor == monitor) { @@ -2497,8 +2489,8 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, if (window->monitor) { - _glfwPlatformSetWindowDecorated(window, window->decorated); - _glfwPlatformSetWindowFloating(window, window->floating); + _glfwSetWindowDecoratedX11(window, window->decorated); + _glfwSetWindowFloatingX11(window, window->floating); releaseMonitor(window); } @@ -2507,7 +2499,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, if (window->monitor) { - if (!_glfwPlatformWindowVisible(window)) + if (!_glfwWindowVisibleX11(window)) { XMapRaised(_glfw.x11.display, window->x11.handle); waitForVisibilityNotify(window); @@ -2526,7 +2518,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, XFlush(_glfw.x11.display); } -int _glfwPlatformWindowFocused(_GLFWwindow* window) +GLFWbool _glfwWindowFocusedX11(_GLFWwindow *window) { Window focused; int state; @@ -2535,22 +2527,21 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window) return window->x11.handle == focused; } -int _glfwPlatformWindowIconified(_GLFWwindow* window) +GLFWbool _glfwWindowIconifiedX11(_GLFWwindow *window) { return getWindowState(window) == IconicState; } -int _glfwPlatformWindowVisible(_GLFWwindow* window) +GLFWbool _glfwWindowVisibleX11(_GLFWwindow *window) { XWindowAttributes wa; XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &wa); return wa.map_state == IsViewable; } -int _glfwPlatformWindowMaximized(_GLFWwindow* window) +GLFWbool _glfwWindowMaximizedX11(_GLFWwindow *window) { - Atom* states; - unsigned long i; + Atom *states; GLFWbool maximized = GLFW_FALSE; if (!_glfw.x11.NET_WM_STATE || @@ -2564,9 +2555,9 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window) _glfwGetWindowPropertyX11(window->x11.handle, _glfw.x11.NET_WM_STATE, XA_ATOM, - (unsigned char**) &states); + (unsigned char **)&states); - for (i = 0; i < count; i++) + for (unsigned long i = 0; i < count; i++) { if (states[i] == _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT || states[i] == _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ) @@ -2582,7 +2573,7 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window) return maximized; } -int _glfwPlatformWindowHovered(_GLFWwindow* window) +GLFWbool _glfwWindowHoveredX11(_GLFWwindow *window) { Window w = _glfw.x11.root; while (w) @@ -2610,7 +2601,7 @@ int _glfwPlatformWindowHovered(_GLFWwindow* window) return GLFW_FALSE; } -int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) +GLFWbool _glfwFramebufferTransparentX11(_GLFWwindow *window) { if (!window->x11.transparent) return GLFW_FALSE; @@ -2618,14 +2609,14 @@ int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) return XGetSelectionOwner(_glfw.x11.display, _glfw.x11.NET_WM_CM_Sx) != None; } -void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowResizableX11(_GLFWwindow *window, GLFWbool enabled) { int width, height; - _glfwPlatformGetWindowSize(window, &width, &height); + _glfwGetWindowSizeX11(window, &width, &height); updateNormalHints(window, width, height); } -void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowDecoratedX11(_GLFWwindow *window, GLFWbool enabled) { struct { @@ -2643,16 +2634,16 @@ void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled) _glfw.x11.MOTIF_WM_HINTS, _glfw.x11.MOTIF_WM_HINTS, 32, PropModeReplace, - (unsigned char*) &hints, + (unsigned char *)&hints, sizeof(hints) / sizeof(long)); } -void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowFloatingX11(_GLFWwindow *window, GLFWbool enabled) { if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_ABOVE) return; - if (_glfwPlatformWindowVisible(window)) + if (_glfwWindowVisibleX11(window)) { const long action = enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; sendEventToWM(window, @@ -2663,20 +2654,21 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) } else { - Atom* states = NULL; - unsigned long i, count; - - count = _glfwGetWindowPropertyX11(window->x11.handle, - _glfw.x11.NET_WM_STATE, - XA_ATOM, - (unsigned char**) &states); + Atom *states = NULL; + const unsigned long count = + _glfwGetWindowPropertyX11(window->x11.handle, + _glfw.x11.NET_WM_STATE, + XA_ATOM, + (unsigned char **)&states); // NOTE: We don't check for failure as this property may not exist yet // and that's fine (and we'll create it implicitly with append) if (enabled) { - for (i = 0; i < count; i++) + unsigned long i; + + for (i = 0; i < count; i++) { if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE) break; @@ -2687,26 +2679,22 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_STATE, XA_ATOM, 32, PropModeAppend, - (unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE, + (unsigned char *)&_glfw.x11.NET_WM_STATE_ABOVE, 1); } } else if (states) { - for (i = 0; i < count; i++) + for (unsigned long i = 0; i < count; i++) { if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE) + { + states[i] = states[count - 1]; + XChangeProperty(_glfw.x11.display, window->x11.handle, + _glfw.x11.NET_WM_STATE, XA_ATOM, 32, + PropModeReplace, (unsigned char *)states, count - 1); break; - } - - if (i < count) - { - states[i] = states[count - 1]; - count--; - - XChangeProperty(_glfw.x11.display, window->x11.handle, - _glfw.x11.NET_WM_STATE, XA_ATOM, 32, - PropModeReplace, (unsigned char*) states, count); + } } } @@ -2717,7 +2705,7 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) XFlush(_glfw.x11.display); } -void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled) +void _glfwSetWindowMousePassthroughX11(_GLFWwindow *window, GLFWbool enabled) { if (!_glfw.x11.xshape.available) return; @@ -2736,20 +2724,20 @@ void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enable } } -float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) +float _glfwGetWindowOpacityX11(_GLFWwindow *window) { float opacity = 1.f; if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.NET_WM_CM_Sx)) { - CARD32* value = NULL; + CARD32 *value = NULL; if (_glfwGetWindowPropertyX11(window->x11.handle, _glfw.x11.NET_WM_WINDOW_OPACITY, XA_CARDINAL, - (unsigned char**) &value)) + (unsigned char **)&value)) { - opacity = (float) (*value / (double) 0xffffffffu); + opacity = (float)(*value / (double)0xffffffffu); } if (value) @@ -2759,15 +2747,15 @@ float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) return opacity; } -void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) +void _glfwSetWindowOpacityX11(_GLFWwindow *window, float opacity) { - const CARD32 value = (CARD32) (0xffffffffu * (double) opacity); + const CARD32 value = (CARD32)(0xffffffffu * (double)opacity); XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32, - PropModeReplace, (unsigned char*) &value, 1); + PropModeReplace, (unsigned char *)&value, 1); } -void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled) +void _glfwSetRawMouseMotionX11(_GLFWwindow *window, GLFWbool enabled) { if (!_glfw.x11.xi.available) return; @@ -2781,20 +2769,19 @@ void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled) disableRawMouseMotion(window); } -GLFWbool _glfwPlatformRawMouseMotionSupported(void) +GLFWbool _glfwRawMouseMotionSupportedX11(void) { return _glfw.x11.xi.available; } -void _glfwPlatformPollEvents(void) +void _glfwPollEventsX11(void) { - _GLFWwindow* window; + drainEmptyEvents(); -#if defined(__linux__) - if (_glfw.joysticksInitialized) { - _glfwDetectJoystickConnectionLinux(); - _glfwPollAllJoysticks(); - } +#if defined(_GLFW_LINUX_JOYSTICK) + if (_glfw.joysticksInitialized) + _glfwPollAllJoysticks(); + _glfwDetectJoystickConnectionLinux(); #endif XPending(_glfw.x11.display); @@ -2805,67 +2792,42 @@ void _glfwPlatformPollEvents(void) processEvent(&event); } - window = _glfw.x11.disabledCursorWindow; + _GLFWwindow *window = _glfw.x11.disabledCursorWindow; if (window) { int width, height; - _glfwPlatformGetWindowSize(window, &width, &height); + _glfwGetWindowSizeX11(window, &width, &height); // NOTE: Re-center the cursor only if it has moved since the last call, // to avoid breaking glfwWaitEvents with MotionNotify if (window->x11.lastCursorPosX != width / 2 || window->x11.lastCursorPosY != height / 2) { - _glfwPlatformSetCursorPos(window, width / 2, height / 2); + _glfwSetCursorPosX11(window, width / 2, height / 2); } } XFlush(_glfw.x11.display); } -static GLFWbool waitForAndPollEvents(double * timeout) +void _glfwWaitEventsX11(void) { - GLFWbool result = GLFW_FALSE; - for (;;) - { - int xpending = XPending(_glfw.x11.display); - GLFWbool event = waitForEvent(timeout); - // We cannot use the boolean shortcut here, since - // waiting for events might have a side effect. - if (event || xpending ) - { - result = GLFW_TRUE; - break; - } - } - - _glfwPlatformPollEvents(); - return result; + waitForAnyEvent(NULL); + _glfwPollEventsX11(); } - -void _glfwPlatformWaitEvents(void) +void _glfwWaitEventsTimeoutX11(double timeout) { - waitForAndPollEvents(NULL); + waitForAnyEvent(&timeout); + _glfwPollEventsX11(); } -void _glfwPlatformWaitEventsTimeout(double timeout) +void _glfwPostEmptyEventX11(void) { - waitForAndPollEvents(&timeout); + writeEmptyEvent(); } -void _glfwPlatformPostEmptyEvent(void) -{ - XEvent event = { ClientMessage }; - event.xclient.window = _glfw.x11.helperWindowHandle; - event.xclient.format = 32; // Data is 32-bit longs - event.xclient.message_type = _glfw.x11.NULL_; - - XSendEvent(_glfw.x11.display, _glfw.x11.helperWindowHandle, False, 0, &event); - XFlush(_glfw.x11.display); -} - -void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) +void _glfwGetCursorPosX11(_GLFWwindow *window, double *xpos, double *ypos) { Window root, child; int rootX, rootY, childX, childY; @@ -2882,33 +2844,57 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) *ypos = childY; } -void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) +void _glfwSetCursorPosX11(_GLFWwindow *window, double x, double y) { // Store the new position so it can be recognized later - window->x11.warpCursorPosX = (int) x; - window->x11.warpCursorPosY = (int) y; + window->x11.warpCursorPosX = (int)x; + window->x11.warpCursorPosY = (int)y; XWarpPointer(_glfw.x11.display, None, window->x11.handle, - 0,0,0,0, (int) x, (int) y); + 0, 0, 0, 0, (int)x, (int)y); XFlush(_glfw.x11.display); } -void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) +void _glfwSetCursorModeX11(_GLFWwindow *window, int mode) { - if (mode == GLFW_CURSOR_DISABLED) + if (_glfwWindowFocusedX11(window)) { - if (_glfwPlatformWindowFocused(window)) - disableCursor(window); - } - else if (_glfw.x11.disabledCursorWindow == window) - enableCursor(window); - else - updateCursorImage(window); + if (mode == GLFW_CURSOR_DISABLED) + { + _glfwGetCursorPosX11(window, + &_glfw.x11.restoreCursorPosX, + &_glfw.x11.restoreCursorPosY); + _glfwCenterCursorInContentArea(window); + if (window->rawMouseMotion) + enableRawMouseMotion(window); + } + else if (_glfw.x11.disabledCursorWindow == window) + { + if (window->rawMouseMotion) + disableRawMouseMotion(window); + } + if (mode == GLFW_CURSOR_DISABLED || mode == GLFW_CURSOR_CAPTURED) + captureCursor(window); + else + releaseCursor(); + + if (mode == GLFW_CURSOR_DISABLED) + _glfw.x11.disabledCursorWindow = window; + else if (_glfw.x11.disabledCursorWindow == window) + { + _glfw.x11.disabledCursorWindow = NULL; + _glfwSetCursorPosX11(window, + _glfw.x11.restoreCursorPosX, + _glfw.x11.restoreCursorPosY); + } + } + + updateCursorImage(window); XFlush(_glfw.x11.display); } -const char* _glfwPlatformGetScancodeName(int scancode) +const char *_glfwGetScancodeNameX11(int scancode) { if (!_glfw.x11.xkb.available) return NULL; @@ -2926,11 +2912,11 @@ const char* _glfwPlatformGetScancodeName(int scancode) if (keysym == NoSymbol) return NULL; - const long ch = _glfwKeySym2Unicode(keysym); - if (ch == -1) + const uint32_t codepoint = _glfwKeySym2Unicode(keysym); + if (codepoint == GLFW_INVALID_CODEPOINT) return NULL; - const size_t count = encodeUTF8(_glfw.x11.keynames[key], (unsigned int) ch); + const size_t count = _glfwEncodeUTF8(_glfw.x11.keynames[key], codepoint); if (count == 0) return NULL; @@ -2938,67 +2924,67 @@ const char* _glfwPlatformGetScancodeName(int scancode) return _glfw.x11.keynames[key]; } -int _glfwPlatformGetKeyScancode(int key) +int _glfwGetKeyScancodeX11(int key) { return _glfw.x11.scancodes[key]; } -int _glfwPlatformCreateCursor(_GLFWcursor* cursor, - const GLFWimage* image, +GLFWbool _glfwCreateCursorX11(_GLFWcursor *cursor, + const GLFWimage *image, int xhot, int yhot) { - cursor->x11.handle = _glfwCreateCursorX11(image, xhot, yhot); + cursor->x11.handle = _glfwCreateNativeCursorX11(image, xhot, yhot); if (!cursor->x11.handle) return GLFW_FALSE; return GLFW_TRUE; } -int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) +GLFWbool _glfwCreateStandardCursorX11(_GLFWcursor *cursor, int shape) { if (_glfw.x11.xcursor.handle) { - char* theme = XcursorGetTheme(_glfw.x11.display); + char *theme = XcursorGetTheme(_glfw.x11.display); if (theme) { const int size = XcursorGetDefaultSize(_glfw.x11.display); - const char* name = NULL; + const char *name = NULL; switch (shape) { - case GLFW_ARROW_CURSOR: - name = "default"; - break; - case GLFW_IBEAM_CURSOR: - name = "text"; - break; - case GLFW_CROSSHAIR_CURSOR: - name = "crosshair"; - break; - case GLFW_POINTING_HAND_CURSOR: - name = "pointer"; - break; - case GLFW_RESIZE_EW_CURSOR: - name = "ew-resize"; - break; - case GLFW_RESIZE_NS_CURSOR: - name = "ns-resize"; - break; - case GLFW_RESIZE_NWSE_CURSOR: - name = "nwse-resize"; - break; - case GLFW_RESIZE_NESW_CURSOR: - name = "nesw-resize"; - break; - case GLFW_RESIZE_ALL_CURSOR: - name = "all-scroll"; - break; - case GLFW_NOT_ALLOWED_CURSOR: - name = "not-allowed"; - break; + case GLFW_ARROW_CURSOR: + name = "default"; + break; + case GLFW_IBEAM_CURSOR: + name = "text"; + break; + case GLFW_CROSSHAIR_CURSOR: + name = "crosshair"; + break; + case GLFW_POINTING_HAND_CURSOR: + name = "pointer"; + break; + case GLFW_RESIZE_EW_CURSOR: + name = "ew-resize"; + break; + case GLFW_RESIZE_NS_CURSOR: + name = "ns-resize"; + break; + case GLFW_RESIZE_NWSE_CURSOR: + name = "nwse-resize"; + break; + case GLFW_RESIZE_NESW_CURSOR: + name = "nesw-resize"; + break; + case GLFW_RESIZE_ALL_CURSOR: + name = "all-scroll"; + break; + case GLFW_NOT_ALLOWED_CURSOR: + name = "not-allowed"; + break; } - XcursorImage* image = XcursorLibraryLoadImage(name, theme, size); + XcursorImage *image = XcursorLibraryLoadImage(name, theme, size); if (image) { cursor->x11.handle = XcursorImageLoadCursor(_glfw.x11.display, image); @@ -3013,31 +2999,31 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) switch (shape) { - case GLFW_ARROW_CURSOR: - native = XC_left_ptr; - break; - case GLFW_IBEAM_CURSOR: - native = XC_xterm; - break; - case GLFW_CROSSHAIR_CURSOR: - native = XC_crosshair; - break; - case GLFW_POINTING_HAND_CURSOR: - native = XC_hand2; - break; - case GLFW_RESIZE_EW_CURSOR: - native = XC_sb_h_double_arrow; - break; - case GLFW_RESIZE_NS_CURSOR: - native = XC_sb_v_double_arrow; - break; - case GLFW_RESIZE_ALL_CURSOR: - native = XC_fleur; - break; - default: - _glfwInputError(GLFW_CURSOR_UNAVAILABLE, - "X11: Standard cursor shape unavailable"); - return GLFW_FALSE; + case GLFW_ARROW_CURSOR: + native = XC_left_ptr; + break; + case GLFW_IBEAM_CURSOR: + native = XC_xterm; + break; + case GLFW_CROSSHAIR_CURSOR: + native = XC_crosshair; + break; + case GLFW_POINTING_HAND_CURSOR: + native = XC_hand2; + break; + case GLFW_RESIZE_EW_CURSOR: + native = XC_sb_h_double_arrow; + break; + case GLFW_RESIZE_NS_CURSOR: + native = XC_sb_v_double_arrow; + break; + case GLFW_RESIZE_ALL_CURSOR: + native = XC_fleur; + break; + default: + _glfwInputError(GLFW_CURSOR_UNAVAILABLE, + "X11: Standard cursor shape unavailable"); + return GLFW_FALSE; } cursor->x11.handle = XCreateFontCursor(_glfw.x11.display, native); @@ -3052,24 +3038,25 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) return GLFW_TRUE; } -void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) +void _glfwDestroyCursorX11(_GLFWcursor *cursor) { if (cursor->x11.handle) XFreeCursor(_glfw.x11.display, cursor->x11.handle); } -void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) +void _glfwSetCursorX11(_GLFWwindow *window, _GLFWcursor *cursor) { - if (window->cursorMode == GLFW_CURSOR_NORMAL) + if (window->cursorMode == GLFW_CURSOR_NORMAL || + window->cursorMode == GLFW_CURSOR_CAPTURED) { updateCursorImage(window); XFlush(_glfw.x11.display); } } -void _glfwPlatformSetClipboardString(const char* string) +void _glfwSetClipboardStringX11(const char *string) { - char* copy = _glfw_strdup(string); + char *copy = _glfw_strdup(string); _glfw_free(_glfw.x11.clipboardString); _glfw.x11.clipboardString = copy; @@ -3086,12 +3073,12 @@ void _glfwPlatformSetClipboardString(const char* string) } } -const char* _glfwPlatformGetClipboardString(void) +const char *_glfwGetClipboardStringX11(void) { return getSelectionString(_glfw.x11.CLIPBOARD); } -EGLenum _glfwPlatformGetEGLPlatform(EGLint** attribs) +EGLenum _glfwGetEGLPlatformX11(EGLint **attribs) { if (_glfw.egl.ANGLE_platform_angle) { @@ -3127,20 +3114,20 @@ EGLenum _glfwPlatformGetEGLPlatform(EGLint** attribs) return 0; } -EGLNativeDisplayType _glfwPlatformGetEGLNativeDisplay(void) +EGLNativeDisplayType _glfwGetEGLNativeDisplayX11(void) { return _glfw.x11.display; } -EGLNativeWindowType _glfwPlatformGetEGLNativeWindow(_GLFWwindow* window) +EGLNativeWindowType _glfwGetEGLNativeWindowX11(_GLFWwindow *window) { if (_glfw.egl.platform) return &window->x11.handle; else - return (EGLNativeWindowType) window->x11.handle; + return (EGLNativeWindowType)window->x11.handle; } -void _glfwPlatformGetRequiredInstanceExtensions(char** extensions) +void _glfwGetRequiredInstanceExtensionsX11(char **extensions) { if (!_glfw.vk.KHR_surface) return; @@ -3161,7 +3148,7 @@ void _glfwPlatformGetRequiredInstanceExtensions(char** extensions) extensions[1] = "VK_KHR_xlib_surface"; } -int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, +GLFWbool _glfwGetPhysicalDevicePresentationSupportX11(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily) { @@ -3172,8 +3159,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, { PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR = - (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR) - vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR"); + (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR) + vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR"); if (!vkGetPhysicalDeviceXcbPresentationSupportKHR) { _glfwInputError(GLFW_API_UNAVAILABLE, @@ -3181,7 +3168,7 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, return GLFW_FALSE; } - xcb_connection_t* connection = XGetXCBConnection(_glfw.x11.display); + xcb_connection_t *connection = XGetXCBConnection(_glfw.x11.display); if (!connection) { _glfwInputError(GLFW_PLATFORM_ERROR, @@ -3198,8 +3185,8 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, { PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR = - (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR) - vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR"); + (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR) + vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR"); if (!vkGetPhysicalDeviceXlibPresentationSupportKHR) { _glfwInputError(GLFW_API_UNAVAILABLE, @@ -3214,10 +3201,10 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, } } -VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, - _GLFWwindow* window, - const VkAllocationCallbacks* allocator, - VkSurfaceKHR* surface) +VkResult _glfwCreateWindowSurfaceX11(VkInstance instance, + _GLFWwindow *window, + const VkAllocationCallbacks *allocator, + VkSurfaceKHR *surface) { if (_glfw.vk.KHR_xcb_surface && _glfw.x11.x11xcb.handle) { @@ -3225,7 +3212,7 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, VkXcbSurfaceCreateInfoKHR sci; PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR; - xcb_connection_t* connection = XGetXCBConnection(_glfw.x11.display); + xcb_connection_t *connection = XGetXCBConnection(_glfw.x11.display); if (!connection) { _glfwInputError(GLFW_PLATFORM_ERROR, @@ -3289,28 +3276,47 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, } } - ////////////////////////////////////////////////////////////////////////// ////// GLFW native API ////// ////////////////////////////////////////////////////////////////////////// -GLFWAPI Display* glfwGetX11Display(void) +GLFWAPI Display *glfwGetX11Display(void) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + + if (_glfw.platform.platformID != GLFW_PLATFORM_X11) + { + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "X11: Platform not initialized"); + return NULL; + } + return _glfw.x11.display; } -GLFWAPI Window glfwGetX11Window(GLFWwindow* handle) +GLFWAPI Window glfwGetX11Window(GLFWwindow *handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow *window = (_GLFWwindow *)handle; _GLFW_REQUIRE_INIT_OR_RETURN(None); + + if (_glfw.platform.platformID != GLFW_PLATFORM_X11) + { + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "X11: Platform not initialized"); + return None; + } + return window->x11.handle; } -GLFWAPI void glfwSetX11SelectionString(const char* string) +GLFWAPI void glfwSetX11SelectionString(const char *string) { _GLFW_REQUIRE_INIT(); + if (_glfw.platform.platformID != GLFW_PLATFORM_X11) + { + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "X11: Platform not initialized"); + return; + } + _glfw_free(_glfw.x11.primarySelectionString); _glfw.x11.primarySelectionString = _glfw_strdup(string); @@ -3327,9 +3333,17 @@ GLFWAPI void glfwSetX11SelectionString(const char* string) } } -GLFWAPI const char* glfwGetX11SelectionString(void) +GLFWAPI const char *glfwGetX11SelectionString(void) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + + if (_glfw.platform.platformID != GLFW_PLATFORM_X11) + { + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "X11: Platform not initialized"); + return NULL; + } + return getSelectionString(_glfw.x11.PRIMARY); } +#endif // _GLFW_X11 diff --git a/src/xkb_unicode.c b/src/xkb_unicode.c index 2772ea09..a516af00 100644 --- a/src/xkb_unicode.c +++ b/src/xkb_unicode.c @@ -29,6 +29,7 @@ #include "internal.h" +#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND) /* * Marcus: This code was originally written by Markus G. Kuhn. @@ -907,7 +908,7 @@ static const struct codepair { // Convert XKB KeySym to Unicode // -long _glfwKeySym2Unicode(unsigned int keysym) +uint32_t _glfwKeySym2Unicode(unsigned int keysym) { int min = 0; int max = sizeof(keysymtab) / sizeof(struct codepair) - 1; @@ -937,6 +938,8 @@ long _glfwKeySym2Unicode(unsigned int keysym) } // No matching Unicode value found - return -1; + return GLFW_INVALID_CODEPOINT; } +#endif // _GLFW_WAYLAND or _GLFW_X11 + diff --git a/src/xkb_unicode.h b/src/xkb_unicode.h index 76d83ffd..b07408f6 100644 --- a/src/xkb_unicode.h +++ b/src/xkb_unicode.h @@ -24,5 +24,7 @@ // //======================================================================== -long _glfwKeySym2Unicode(unsigned int keysym); +#define GLFW_INVALID_CODEPOINT 0xffffffffu + +uint32_t _glfwKeySym2Unicode(unsigned int keysym); diff --git a/tests/cursor.c b/tests/cursor.c index 9be42748..37f3299c 100644 --- a/tests/cursor.c +++ b/tests/cursor.c @@ -172,7 +172,8 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action, case GLFW_KEY_ESCAPE: { - if (glfwGetInputMode(window, GLFW_CURSOR) != GLFW_CURSOR_DISABLED) + const int mode = glfwGetInputMode(window, GLFW_CURSOR); + if (mode != GLFW_CURSOR_DISABLED && mode != GLFW_CURSOR_CAPTURED) { glfwSetWindowShouldClose(window, GLFW_TRUE); break; @@ -197,6 +198,11 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action, printf("(( cursor is hidden ))\n"); break; + case GLFW_KEY_C: + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_CAPTURED); + printf("(( cursor is captured ))\n"); + break; + case GLFW_KEY_R: if (!glfwRawMouseMotionSupported()) break; diff --git a/tests/events.c b/tests/events.c index 2341a637..d849d37d 100644 --- a/tests/events.c +++ b/tests/events.c @@ -692,7 +692,7 @@ int main(int argc, char** argv) glfwMakeContextCurrent(slots[i].window); gladLoadGL(glfwGetProcAddress); - glfwSwapInterval(1); + glfwSwapBuffers(slots[i].window); } printf("Main loop starting\n"); diff --git a/tests/gamma.c b/tests/gamma.c index 734955cd..d1f6dc27 100644 --- a/tests/gamma.c +++ b/tests/gamma.c @@ -113,6 +113,12 @@ int main(int argc, char** argv) { const GLFWgammaramp* ramp = glfwGetGammaRamp(monitor); + if (!ramp) + { + glfwTerminate(); + exit(EXIT_FAILURE); + } + const size_t array_size = ramp->size * sizeof(short); orig_ramp.size = ramp->size; orig_ramp.red = malloc(array_size); diff --git a/tests/glfwinfo.c b/tests/glfwinfo.c index 87ed385f..eda2f821 100644 --- a/tests/glfwinfo.c +++ b/tests/glfwinfo.c @@ -64,10 +64,24 @@ #define ANGLE_TYPE_VULKAN "vk" #define ANGLE_TYPE_METAL "mtl" +#define PLATFORM_NAME_ANY "any" +#define PLATFORM_NAME_WIN32 "win32" +#define PLATFORM_NAME_COCOA "cooca" +#define PLATFORM_NAME_WL "wayland" +#define PLATFORM_NAME_X11 "x11" +#define PLATFORM_NAME_NULL "null" + static void usage(void) { printf("Usage: glfwinfo [OPTION]...\n"); printf("Options:\n"); + printf(" --platform=PLATFORM the platform to use (" + PLATFORM_NAME_ANY " or " + PLATFORM_NAME_WIN32 " or " + PLATFORM_NAME_COCOA " or " + PLATFORM_NAME_X11 " or " + PLATFORM_NAME_WL " or " + PLATFORM_NAME_NULL ")\n"); printf(" -a, --client-api=API the client API to use (" API_NAME_OPENGL " or " API_NAME_OPENGL_ES ")\n"); @@ -126,6 +140,22 @@ static void error_callback(int error, const char* description) fprintf(stderr, "Error: %s\n", description); } +static const char* get_platform_name(int platform) +{ + if (platform == GLFW_PLATFORM_WIN32) + return "Win32"; + else if (platform == GLFW_PLATFORM_COCOA) + return "Cocoa"; + else if (platform == GLFW_PLATFORM_WAYLAND) + return "Wayland"; + else if (platform == GLFW_PLATFORM_X11) + return "X11"; + else if (platform == GLFW_PLATFORM_NULL) + return "Null"; + + return "unknown"; +} + static const char* get_device_type_name(VkPhysicalDeviceType type) { if (type == VK_PHYSICAL_DEVICE_TYPE_OTHER) @@ -225,21 +255,6 @@ static void list_context_extensions(int client, int major, int minor) } } -static void list_vulkan_instance_extensions(void) -{ - printf("Vulkan instance extensions:\n"); - - uint32_t ep_count; - vkEnumerateInstanceExtensionProperties(NULL, &ep_count, NULL); - VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties)); - vkEnumerateInstanceExtensionProperties(NULL, &ep_count, ep); - - for (uint32_t i = 0; i < ep_count; i++) - printf(" %s (spec version %u)\n", ep[i].extensionName, ep[i].specVersion); - - free(ep); -} - static void list_vulkan_instance_layers(void) { printf("Vulkan instance layers:\n"); @@ -260,21 +275,6 @@ static void list_vulkan_instance_layers(void) free(lp); } -static void list_vulkan_device_extensions(VkInstance instance, VkPhysicalDevice device) -{ - printf("Vulkan device extensions:\n"); - - uint32_t ep_count; - vkEnumerateDeviceExtensionProperties(device, NULL, &ep_count, NULL); - VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties)); - vkEnumerateDeviceExtensionProperties(device, NULL, &ep_count, ep); - - for (uint32_t i = 0; i < ep_count; i++) - printf(" %s (spec version %u)\n", ep[i].extensionName, ep[i].specVersion); - - free(ep); -} - static void list_vulkan_device_layers(VkInstance instance, VkPhysicalDevice device) { printf("Vulkan device layers:\n"); @@ -325,12 +325,34 @@ static void print_version(void) printf("GLFW library version string: \"%s\"\n", glfwGetVersionString()); } +static void print_platform(void) +{ + const int platforms[] = + { + GLFW_PLATFORM_WIN32, + GLFW_PLATFORM_COCOA, + GLFW_PLATFORM_WAYLAND, + GLFW_PLATFORM_X11, + GLFW_PLATFORM_NULL + }; + + printf("GLFW platform: %s\n", get_platform_name(glfwGetPlatform())); + printf("GLFW supported platforms:\n"); + + for (size_t i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) + { + if (glfwPlatformSupported(platforms[i])) + printf(" %s\n", get_platform_name(platforms[i])); + } +} + int main(int argc, char** argv) { int ch; bool list_extensions = false, list_layers = false; // These duplicate the defaults for each hint + int platform = GLFW_ANY_PLATFORM; int client_api = GLFW_OPENGL_API; int context_major = 1; int context_minor = 0; @@ -360,7 +382,7 @@ int main(int argc, char** argv) bool cocoa_graphics_switching = false; bool disable_xcb_surface = false; - enum { CLIENT, CONTEXT, BEHAVIOR, DEBUG_CONTEXT, FORWARD, HELP, + enum { PLATFORM, CLIENT, CONTEXT, BEHAVIOR, DEBUG_CONTEXT, FORWARD, HELP, EXTENSIONS, LAYERS, MAJOR, MINOR, PROFILE, ROBUSTNESS, VERSION, REDBITS, GREENBITS, BLUEBITS, ALPHABITS, DEPTHBITS, STENCILBITS, @@ -369,6 +391,7 @@ int main(int argc, char** argv) ANGLE_TYPE, GRAPHICS_SWITCHING, XCB_SURFACE }; const struct option options[] = { + { "platform", 1, NULL, PLATFORM }, { "behavior", 1, NULL, BEHAVIOR }, { "client-api", 1, NULL, CLIENT }, { "context-api", 1, NULL, CONTEXT }, @@ -408,6 +431,25 @@ int main(int argc, char** argv) { switch (ch) { + case PLATFORM: + if (strcasecmp(optarg, PLATFORM_NAME_ANY) == 0) + platform = GLFW_ANY_PLATFORM; + else if (strcasecmp(optarg, PLATFORM_NAME_WIN32) == 0) + platform = GLFW_PLATFORM_WIN32; + else if (strcasecmp(optarg, PLATFORM_NAME_COCOA) == 0) + platform = GLFW_PLATFORM_COCOA; + else if (strcasecmp(optarg, PLATFORM_NAME_WL) == 0) + platform = GLFW_PLATFORM_WAYLAND; + else if (strcasecmp(optarg, PLATFORM_NAME_X11) == 0) + platform = GLFW_PLATFORM_X11; + else if (strcasecmp(optarg, PLATFORM_NAME_NULL) == 0) + platform = GLFW_PLATFORM_NULL; + else + { + usage(); + exit(EXIT_FAILURE); + } + break; case 'a': case CLIENT: if (strcasecmp(optarg, API_NAME_OPENGL) == 0) @@ -623,6 +665,8 @@ int main(int argc, char** argv) glfwSetErrorCallback(error_callback); + glfwInitHint(GLFW_PLATFORM, platform); + glfwInitHint(GLFW_COCOA_MENUBAR, false); glfwInitHint(GLFW_ANGLE_PLATFORM_TYPE, angle_type); @@ -632,6 +676,7 @@ int main(int argc, char** argv) exit(EXIT_FAILURE); print_version(); + print_platform(); glfwWindowHint(GLFW_VISIBLE, false); @@ -878,20 +923,51 @@ int main(int argc, char** argv) VK_VERSION_MAJOR(loader_version), VK_VERSION_MINOR(loader_version)); - uint32_t re_count; - const char** re = glfwGetRequiredInstanceExtensions(&re_count); + uint32_t glfw_re_count; + const char** glfw_re = glfwGetRequiredInstanceExtensions(&glfw_re_count); - if (re) + uint32_t re_count = glfw_re_count; + const char** re = calloc(glfw_re_count, sizeof(char*)); + + if (glfw_re) { printf("Vulkan window surface required instance extensions:\n"); - for (uint32_t i = 0; i < re_count; i++) - printf(" %s\n", re[i]); + for (uint32_t i = 0; i < glfw_re_count; i++) + { + printf(" %s\n", glfw_re[i]); + re[i] = glfw_re[i]; + } } else printf("Vulkan window surface extensions missing\n"); + uint32_t ep_count; + vkEnumerateInstanceExtensionProperties(NULL, &ep_count, NULL); + VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties)); + vkEnumerateInstanceExtensionProperties(NULL, &ep_count, ep); + if (list_extensions) - list_vulkan_instance_extensions(); + { + printf("Vulkan instance extensions:\n"); + + for (uint32_t i = 0; i < ep_count; i++) + printf(" %s (spec version %u)\n", ep[i].extensionName, ep[i].specVersion); + } + + bool portability_enumeration = false; + + for (uint32_t i = 0; i < ep_count; i++) + { + if (strcmp(ep[i].extensionName, "VK_KHR_portability_enumeration") != 0) + continue; + + re_count++; + re = realloc((void*) re, sizeof(char*) * re_count); + re[re_count - 1] = "VK_KHR_portability_enumeration"; + portability_enumeration = true; + } + + free(ep); if (list_layers) list_vulkan_instance_layers(); @@ -912,6 +988,9 @@ int main(int argc, char** argv) ici.enabledExtensionCount = re_count; ici.ppEnabledExtensionNames = re; + if (portability_enumeration) + ici.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + VkInstance instance = VK_NULL_HANDLE; if (vkCreateInstance(&ici, NULL, &instance) != VK_SUCCESS) @@ -920,9 +999,11 @@ int main(int argc, char** argv) exit(EXIT_FAILURE); } + free((void*) re); + gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, instance); - if (re) + if (glfw_re_count) { VkSurfaceKHR surface = VK_NULL_HANDLE; @@ -945,27 +1026,64 @@ int main(int argc, char** argv) VkPhysicalDeviceProperties pdp; vkGetPhysicalDeviceProperties(pd[i], &pdp); - printf("Vulkan %s device: \"%s\" (API version %i.%i)\n", - get_device_type_name(pdp.deviceType), - pdp.deviceName, - VK_VERSION_MAJOR(pdp.apiVersion), - VK_VERSION_MINOR(pdp.apiVersion)); - uint32_t qfp_count; vkGetPhysicalDeviceQueueFamilyProperties(pd[i], &qfp_count, NULL); - printf("Vulkan device queue family presentation support:\n"); - for (uint32_t j = 0; j < qfp_count; j++) + uint32_t ep_count; + vkEnumerateDeviceExtensionProperties(pd[i], NULL, &ep_count, NULL); + VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties)); + vkEnumerateDeviceExtensionProperties(pd[i], NULL, &ep_count, ep); + + if (portability_enumeration) { - printf(" %u: ", j); - if (glfwGetPhysicalDevicePresentationSupport(instance, pd[i], j)) - printf("supported\n"); - else - printf("no\n"); + bool conformant = true; + + for (uint32_t j = 0; j < ep_count; j++) + { + if (strcmp(ep[j].extensionName, "VK_KHR_portability_subset") == 0) + { + conformant = false; + break; + } + } + + printf("Vulkan %s %s device: \"%s\" (API version %i.%i)\n", + conformant ? "conformant" : "non-conformant", + get_device_type_name(pdp.deviceType), + pdp.deviceName, + VK_VERSION_MAJOR(pdp.apiVersion), + VK_VERSION_MINOR(pdp.apiVersion)); + } + else + { + printf("Vulkan %s device: \"%s\" (API version %i.%i)\n", + get_device_type_name(pdp.deviceType), + pdp.deviceName, + VK_VERSION_MAJOR(pdp.apiVersion), + VK_VERSION_MINOR(pdp.apiVersion)); + } + + if (glfw_re_count) + { + printf("Vulkan device queue family presentation support:\n"); + for (uint32_t j = 0; j < qfp_count; j++) + { + printf(" %u: ", j); + if (glfwGetPhysicalDevicePresentationSupport(instance, pd[i], j)) + printf("supported\n"); + else + printf("no\n"); + } } if (list_extensions) - list_vulkan_device_extensions(instance, pd[i]); + { + printf("Vulkan device extensions:\n"); + for (uint32_t j = 0; j < ep_count; j++) + printf(" %s (spec version %u)\n", ep[j].extensionName, ep[j].specVersion); + } + + free(ep); if (list_layers) list_vulkan_device_layers(instance, pd[i]); diff --git a/tests/iconify.c b/tests/iconify.c index e5a428a0..32fd44f2 100644 --- a/tests/iconify.c +++ b/tests/iconify.c @@ -38,7 +38,7 @@ #include "getopt.h" -static int windowed_xpos, windowed_ypos, windowed_width, windowed_height; +static int windowed_xpos, windowed_ypos, windowed_width = 640, windowed_height = 480; static void usage(void) { @@ -181,8 +181,8 @@ static GLFWwindow* create_window(GLFWmonitor* monitor) } else { - width = 640; - height = 480; + width = windowed_width; + height = windowed_height; } window = glfwCreateWindow(width, height, "Iconify", monitor, NULL); diff --git a/tests/threads.c b/tests/threads.c index ec13b001..a2caea56 100644 --- a/tests/threads.c +++ b/tests/threads.c @@ -96,10 +96,11 @@ int main(void) if (!glfwInit()) exit(EXIT_FAILURE); - glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); - for (i = 0; i < count; i++) { + glfwWindowHint(GLFW_POSITION_X, 200 + 250 * i); + glfwWindowHint(GLFW_POSITION_Y, 200); + threads[i].window = glfwCreateWindow(200, 200, threads[i].title, NULL, NULL); @@ -110,9 +111,6 @@ int main(void) } glfwSetKeyCallback(threads[i].window, key_callback); - - glfwSetWindowPos(threads[i].window, 200 + 250 * i, 200); - glfwShowWindow(threads[i].window); } glfwMakeContextCurrent(threads[0].window); diff --git a/tests/triangle-vulkan.c b/tests/triangle-vulkan.c index fb5db3e2..b38ee139 100644 --- a/tests/triangle-vulkan.c +++ b/tests/triangle-vulkan.c @@ -1561,6 +1561,7 @@ static VkBool32 demo_check_layers(uint32_t check_count, const char **check_names static void demo_init_vk(struct demo *demo) { VkResult err; + VkBool32 portability_enumeration = VK_FALSE; uint32_t i = 0; uint32_t required_extension_count = 0; uint32_t instance_extension_count = 0; @@ -1668,6 +1669,13 @@ static void demo_init_vk(struct demo *demo) { } } assert(demo->enabled_extension_count < 64); + if (!strcmp(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, + instance_extensions[i].extensionName)) { + demo->extension_names[demo->enabled_extension_count++] = + VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME; + portability_enumeration = VK_TRUE; + } + assert(demo->enabled_extension_count < 64); } free(instance_extensions); @@ -1692,6 +1700,9 @@ static void demo_init_vk(struct demo *demo) { .ppEnabledExtensionNames = (const char *const *)demo->extension_names, }; + if (portability_enumeration) + inst_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + uint32_t gpu_count; err = vkCreateInstance(&inst_info, NULL, &demo->inst); diff --git a/tests/window.c b/tests/window.c index 075d3887..83baff46 100644 --- a/tests/window.c +++ b/tests/window.c @@ -56,11 +56,11 @@ int main(int argc, char** argv) int limit_aspect_ratio = false, aspect_numer = 1, aspect_denom = 1; int limit_min_size = false, min_width = 400, min_height = 400; int limit_max_size = false, max_width = 400, max_height = 400; - char width_buffer[10] = "", height_buffer[10] = ""; - char xpos_buffer[10] = "", ypos_buffer[10] = ""; - char numer_buffer[10] = "", denom_buffer[10] = ""; - char min_width_buffer[10] = "", min_height_buffer[10] = ""; - char max_width_buffer[10] = "", max_height_buffer[10] = ""; + char width_buffer[12] = "", height_buffer[12] = ""; + char xpos_buffer[12] = "", ypos_buffer[12] = ""; + char numer_buffer[12] = "", denom_buffer[12] = ""; + char min_width_buffer[12] = "", min_height_buffer[12] = ""; + char max_width_buffer[12] = "", max_height_buffer[12] = ""; int may_close = true; if (!glfwInit()) @@ -121,7 +121,7 @@ int main(int argc, char** argv) nk_glfw3_new_frame(); if (nk_begin(nk, "main", area, 0)) { - nk_layout_row_dynamic(nk, 30, 4); + nk_layout_row_dynamic(nk, 30, 5); if (nk_button_label(nk, "Toggle Fullscreen")) { @@ -149,6 +149,16 @@ int main(int argc, char** argv) glfwIconifyWindow(window); if (nk_button_label(nk, "Restore")) glfwRestoreWindow(window); + if (nk_button_label(nk, "Hide (briefly)")) + { + glfwHideWindow(window); + + const double time = glfwGetTime() + 3.0; + while (glfwGetTime() < time) + glfwWaitEventsTimeout(1.0); + + glfwShowWindow(window); + } nk_layout_row_dynamic(nk, 30, 1);