[-] Bloat

This commit is contained in:
Reece Wilson 2023-11-02 01:28:31 +00:00
parent 533b642c47
commit 36ad56ecdf
70 changed files with 0 additions and 61246 deletions

View File

@ -1,47 +0,0 @@
image:
- Visual Studio 2015
branches:
only:
- ci
- master
- latest
- 3.3-stable
skip_tags: true
environment:
matrix:
- GENERATOR: MinGW Makefiles
BUILD_SHARED_LIBS: ON
CFLAGS: -Werror
- GENERATOR: MinGW Makefiles
BUILD_SHARED_LIBS: OFF
CFLAGS: -Werror
- GENERATOR: Visual Studio 10 2010
BUILD_SHARED_LIBS: ON
CFLAGS: /WX
- GENERATOR: Visual Studio 10 2010
BUILD_SHARED_LIBS: OFF
CFLAGS: /WX
matrix:
fast_finish: true
for:
-
matrix:
only:
- GENERATOR: MinGW Makefiles
build_script:
- set PATH=%PATH:C:\Program Files\Git\usr\bin=C:\MinGW\bin%
- cmake -S . -B build -G "%GENERATOR%" -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS%
- cmake --build build
-
matrix:
only:
- GENERATOR: Visual Studio 10 2010
build_script:
- cmake -S . -B build -G "%GENERATOR%" -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS%
- cmake --build build --target glfw
notifications:
- provider: Email
to:
- ci@glfw.org
on_build_failure: true
on_build_success: false

5
.gitattributes vendored
View File

@ -1,5 +0,0 @@
*.m linguist-language=Objective-C
.gitignore export-ignore
.gitattributes export-ignore
.travis.yml export-ignore
.appveyor.yml export-ignore

10
.github/CODEOWNERS vendored
View File

@ -1,10 +0,0 @@
* @elmindreda
src/wl_* @linkmauve
docs/*.css @glfw/webdev
docs/*.scss @glfw/webdev
docs/*.html @glfw/webdev
docs/*.xml @glfw/webdev

View File

@ -1,94 +0,0 @@
name: Build
on:
pull_request:
push:
branches: [ ci, master, latest, 3.3-stable ]
workflow_dispatch:
permissions:
statuses: write
contents: read
jobs:
build-linux-x11-clang:
name: X11 (Linux, Clang)
runs-on: ubuntu-latest
env:
CC: clang
CFLAGS: -Werror
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: |
sudo apt update
sudo apt install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxext-dev
- name: Configure static library
run: cmake -S . -B build-static
- name: Build static library
run: cmake --build build-static --parallel
- name: Configure shared library
run: cmake -S . -B build-shared -D BUILD_SHARED_LIBS=ON
- name: Build shared library
run: cmake --build build-shared --parallel
build-linux-full-clang:
name: X11+Wayland (Linux, Clang)
runs-on: ubuntu-latest
env:
CC: clang
CFLAGS: -Werror
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: |
sudo apt update
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_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_BUILD_WAYLAND=ON -D BUILD_SHARED_LIBS=ON
- name: Build shared library
run: cmake --build build-shared --parallel
build-macos-cocoa-clang:
name: Cocoa (macOS, Clang)
runs-on: macos-latest
env:
CFLAGS: -Werror
MACOSX_DEPLOYMENT_TARGET: 10.8
steps:
- uses: actions/checkout@v3
- name: Configure static library
run: cmake -S . -B build-static
- name: Build static library
run: cmake --build build-static --parallel
- name: Configure shared library
run: cmake -S . -B build-shared -D BUILD_SHARED_LIBS=ON
- name: Build shared library
run: cmake --build build-shared --parallel
build-windows-win32-vs2022:
name: Win32 (Windows, VS2022)
runs-on: windows-latest
env:
CFLAGS: /WX
steps:
- uses: actions/checkout@v3
- name: Configure static library
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 17 2022" -D BUILD_SHARED_LIBS=ON
- name: Build shared library
run: cmake --build build-shared --parallel

View File

@ -1,10 +0,0 @@
Camilla Löwy <elmindreda@glfw.org> <elmindreda@users.sourceforge.net>
Camilla Löwy <elmindreda@glfw.org> <elmindreda@elmindreda.org>
Camilla Löwy <elmindreda@glfw.org>
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
Marcus Geelnard <m@bitsnbites.eu> <marcus256@users.sourceforge.net>
Marcus Geelnard <m@bitsnbites.eu> <marcus@geelnards-pc.(none)>
Marcus Geelnard <m@bitsnbites.eu>

View File

@ -1,48 +0,0 @@
# Usage:
# cmake -P GenerateMappings.cmake <path/to/mappings.h.in> <path/to/mappings.h>
set(source_url "https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt")
set(source_path "${CMAKE_CURRENT_BINARY_DIR}/gamecontrollerdb.txt")
set(template_path "${CMAKE_ARGV3}")
set(target_path "${CMAKE_ARGV4}")
if (NOT EXISTS "${template_path}")
message(FATAL_ERROR "Failed to find template file ${template_path}")
endif()
file(DOWNLOAD "${source_url}" "${source_path}"
STATUS download_status
TLS_VERIFY on)
list(GET download_status 0 status_code)
list(GET download_status 1 status_message)
if (status_code)
message(FATAL_ERROR "Failed to download ${source_url}: ${status_message}")
endif()
file(STRINGS "${source_path}" lines)
foreach(line ${lines})
if (line MATCHES "^[0-9a-fA-F]")
if (line MATCHES "platform:Windows")
if (GLFW_WIN32_MAPPINGS)
string(APPEND GLFW_WIN32_MAPPINGS "\n")
endif()
string(APPEND GLFW_WIN32_MAPPINGS "\"${line}\",")
elseif (line MATCHES "platform:Mac OS X")
if (GLFW_COCOA_MAPPINGS)
string(APPEND GLFW_COCOA_MAPPINGS "\n")
endif()
string(APPEND GLFW_COCOA_MAPPINGS "\"${line}\",")
elseif (line MATCHES "platform:Linux")
if (GLFW_LINUX_MAPPINGS)
string(APPEND GLFW_LINUX_MAPPINGS "\n")
endif()
string(APPEND GLFW_LINUX_MAPPINGS "\"${line}\",")
endif()
endif()
endforeach()
configure_file("${template_path}" "${target_path}" @ONLY NEWLINE_STYLE UNIX)
file(REMOVE "${source_path}")

View File

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleGetInfoString</key>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>LSRequiresCarbon</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>

View File

@ -1,29 +0,0 @@
if (NOT EXISTS "@GLFW_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: \"@GLFW_BINARY_DIR@/install_manifest.txt\"")
endif()
file(READ "@GLFW_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach (file ${files})
message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
if (EXISTS "$ENV{DESTDIR}${file}")
exec_program("@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval)
if (NOT "${rm_retval}" STREQUAL 0)
MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
endif()
elseif (IS_SYMLINK "$ENV{DESTDIR}${file}")
EXEC_PROGRAM("@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval)
if (NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing symlink \"$ENV{DESTDIR}${file}\"")
endif()
else()
message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
endif()
endforeach()

View File

@ -1,13 +0,0 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
Name: GLFW
Description: A multi-platform library for OpenGL, window and input
Version: @GLFW_VERSION@
URL: https://www.glfw.org/
Requires.private: @GLFW_PKG_CONFIG_REQUIRES_PRIVATE@
Libs: -L${libdir} -l@GLFW_LIB_NAME@
Libs.private: @GLFW_PKG_CONFIG_LIBS_PRIVATE@
Cflags: -I${includedir}

View File

@ -1,3 +0,0 @@
include(CMakeFindDependencyMacro)
find_dependency(Threads)
include("${CMAKE_CURRENT_LIST_DIR}/glfw3Targets.cmake")

View File

@ -1,13 +0,0 @@
# Define the environment for cross-compiling with 32-bit MinGW-w64 Clang
SET(CMAKE_SYSTEM_NAME Windows) # Target system name
SET(CMAKE_SYSTEM_VERSION 1)
SET(CMAKE_C_COMPILER "i686-w64-mingw32-clang")
SET(CMAKE_CXX_COMPILER "i686-w64-mingw32-clang++")
SET(CMAKE_RC_COMPILER "i686-w64-mingw32-windres")
SET(CMAKE_RANLIB "i686-w64-mingw32-ranlib")
# Configure the behaviour of the find commands
SET(CMAKE_FIND_ROOT_PATH "/usr/i686-w64-mingw32")
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

View File

@ -1,13 +0,0 @@
# Define the environment for cross-compiling with 32-bit MinGW-w64 GCC
SET(CMAKE_SYSTEM_NAME Windows) # Target system name
SET(CMAKE_SYSTEM_VERSION 1)
SET(CMAKE_C_COMPILER "i686-w64-mingw32-gcc")
SET(CMAKE_CXX_COMPILER "i686-w64-mingw32-g++")
SET(CMAKE_RC_COMPILER "i686-w64-mingw32-windres")
SET(CMAKE_RANLIB "i686-w64-mingw32-ranlib")
# Configure the behaviour of the find commands
SET(CMAKE_FIND_ROOT_PATH "/usr/i686-w64-mingw32")
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

View File

@ -1,17 +0,0 @@
# Find EpollShim
# Once done, this will define
#
# EPOLLSHIM_FOUND - System has EpollShim
# EPOLLSHIM_INCLUDE_DIRS - The EpollShim include directories
# EPOLLSHIM_LIBRARIES - The libraries needed to use EpollShim
find_path(EPOLLSHIM_INCLUDE_DIRS NAMES sys/epoll.h sys/timerfd.h HINTS /usr/local/include/libepoll-shim)
find_library(EPOLLSHIM_LIBRARIES NAMES epoll-shim libepoll-shim HINTS /usr/local/lib)
if (EPOLLSHIM_INCLUDE_DIRS AND EPOLLSHIM_LIBRARIES)
set(EPOLLSHIM_FOUND TRUE)
endif (EPOLLSHIM_INCLUDE_DIRS AND EPOLLSHIM_LIBRARIES)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(EpollShim DEFAULT_MSG EPOLLSHIM_LIBRARIES EPOLLSHIM_INCLUDE_DIRS)
mark_as_advanced(EPOLLSHIM_INCLUDE_DIRS EPOLLSHIM_LIBRARIES)

View File

@ -1,18 +0,0 @@
# Try to find OSMesa on a Unix system
#
# This will define:
#
# OSMESA_LIBRARIES - Link these to use OSMesa
# OSMESA_INCLUDE_DIR - Include directory for OSMesa
#
# Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
if (NOT WIN32)
find_package (PkgConfig)
pkg_check_modules (PKG_OSMESA QUIET osmesa)
set (OSMESA_INCLUDE_DIR ${PKG_OSMESA_INCLUDE_DIRS})
set (OSMESA_LIBRARIES ${PKG_OSMESA_LIBRARIES})
endif ()

View File

@ -1,13 +0,0 @@
# Define the environment for cross-compiling with 64-bit MinGW-w64 Clang
SET(CMAKE_SYSTEM_NAME Windows) # Target system name
SET(CMAKE_SYSTEM_VERSION 1)
SET(CMAKE_C_COMPILER "x86_64-w64-mingw32-clang")
SET(CMAKE_CXX_COMPILER "x86_64-w64-mingw32-clang++")
SET(CMAKE_RC_COMPILER "x86_64-w64-mingw32-windres")
SET(CMAKE_RANLIB "x86_64-w64-mingw32-ranlib")
# Configure the behaviour of the find commands
SET(CMAKE_FIND_ROOT_PATH "/usr/x86_64-w64-mingw32")
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

View File

@ -1,13 +0,0 @@
# Define the environment for cross-compiling with 64-bit MinGW-w64 GCC
SET(CMAKE_SYSTEM_NAME Windows) # Target system name
SET(CMAKE_SYSTEM_VERSION 1)
SET(CMAKE_C_COMPILER "x86_64-w64-mingw32-gcc")
SET(CMAKE_CXX_COMPILER "x86_64-w64-mingw32-g++")
SET(CMAKE_RC_COMPILER "x86_64-w64-mingw32-windres")
SET(CMAKE_RANLIB "x86_64-w64-mingw32-ranlib")
# Configure the behaviour of the find commands
SET(CMAKE_FIND_ROOT_PATH "/usr/x86_64-w64-mingw32")
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

View File

@ -1,171 +0,0 @@
cmake_minimum_required(VERSION 3.4...3.20 FATAL_ERROR)
project(GLFW VERSION 3.4.0 LANGUAGES C)
if (POLICY CMP0069)
cmake_policy(SET CMP0069 NEW)
endif()
if (POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif()
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
string(COMPARE EQUAL "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_SOURCE_DIR}" GLFW_STANDALONE)
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
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)
include(GNUInstallDirs)
include(CMakeDependentOption)
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(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC runtime library DLL" ON
"MSVC" OFF)
set(GLFW_LIBRARY_TYPE "${GLFW_LIBRARY_TYPE}" CACHE STRING
"Library type override for GLFW (SHARED, STATIC, OBJECT, or empty to follow BUILD_SHARED_LIBS)")
if (GLFW_LIBRARY_TYPE)
if (GLFW_LIBRARY_TYPE STREQUAL "SHARED")
set(GLFW_BUILD_SHARED_LIBRARY TRUE)
else()
set(GLFW_BUILD_SHARED_LIBRARY FALSE)
endif()
else()
set(GLFW_BUILD_SHARED_LIBRARY ${BUILD_SHARED_LIBS})
endif()
list(APPEND CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules")
find_package(Threads REQUIRED)
if (GLFW_BUILD_DOCS)
set(DOXYGEN_SKIP_DOT TRUE)
find_package(Doxygen)
endif()
#--------------------------------------------------------------------
# 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
#--------------------------------------------------------------------
if (MSVC AND NOT USE_MSVC_RUNTIME_LIBRARY_DLL)
if (CMAKE_VERSION VERSION_LESS 3.15)
foreach (flag CMAKE_C_FLAGS
CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_MINSIZEREL
CMAKE_C_FLAGS_RELWITHDEBINFO)
if (flag MATCHES "/MD")
string(REGEX REPLACE "/MD" "/MT" ${flag} "${${flag}}")
endif()
if (flag MATCHES "/MDd")
string(REGEX REPLACE "/MDd" "/MTd" ${flag} "${${flag}}")
endif()
endforeach()
else()
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
endif()
#--------------------------------------------------------------------
# Create generated files
#--------------------------------------------------------------------
include(CMakePackageConfigHelpers)
set(GLFW_CONFIG_PATH "${CMAKE_INSTALL_LIBDIR}/cmake/glfw3")
configure_package_config_file(CMake/glfw3Config.cmake.in
src/glfw3Config.cmake
INSTALL_DESTINATION "${GLFW_CONFIG_PATH}"
NO_CHECK_REQUIRED_COMPONENTS_MACRO)
write_basic_package_version_file(src/glfw3ConfigVersion.cmake
VERSION ${GLFW_VERSION}
COMPATIBILITY SameMajorVersion)
#--------------------------------------------------------------------
# Add subdirectories
#--------------------------------------------------------------------
add_subdirectory(src)
if (GLFW_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
if (GLFW_BUILD_TESTS)
add_subdirectory(tests)
endif()
if (DOXYGEN_FOUND AND GLFW_BUILD_DOCS)
add_subdirectory(docs)
endif()
#--------------------------------------------------------------------
# Install files other than the library
# The library is installed by src/CMakeLists.txt
#--------------------------------------------------------------------
if (GLFW_INSTALL)
install(DIRECTORY include/GLFW DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN glfw3.h PATTERN glfw3native.h)
install(FILES "${GLFW_BINARY_DIR}/src/glfw3Config.cmake"
"${GLFW_BINARY_DIR}/src/glfw3ConfigVersion.cmake"
DESTINATION "${GLFW_CONFIG_PATH}")
install(EXPORT glfwTargets FILE glfw3Targets.cmake
EXPORT_LINK_INTERFACE_LIBRARIES
DESTINATION "${GLFW_CONFIG_PATH}")
install(FILES "${GLFW_BINARY_DIR}/src/glfw3.pc"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
if (DOXYGEN_FOUND AND GLFW_BUILD_DOCS)
install(DIRECTORY "${GLFW_BINARY_DIR}/docs/html"
DESTINATION "${CMAKE_INSTALL_DOCDIR}")
endif()
# Only generate this target if no higher-level project already has
if (NOT TARGET uninstall)
configure_file(CMake/cmake_uninstall.cmake.in
cmake_uninstall.cmake IMMEDIATE @ONLY)
add_custom_target(uninstall
"${CMAKE_COMMAND}" -P
"${GLFW_BINARY_DIR}/cmake_uninstall.cmake")
set_target_properties(uninstall PROPERTIES FOLDER "GLFW3")
endif()
endif()

View File

@ -1,272 +0,0 @@
# 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
- Takuro Ashie
- 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
- Daijiro Fukuda
- 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
- Ryo Ichinose
- 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
- Yasutaka Kumei
- 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
- Juan Ramos
- 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
- Yoshinori Sano
- 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
- xfangfang
- 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

230
deps/getopt.c vendored
View File

@ -1,230 +0,0 @@
/* Copyright (c) 2012, Kim Gräsman
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Kim Gräsman nor the names of contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL KIM GRÄSMAN BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "getopt.h"
#include <stddef.h>
#include <string.h>
const int no_argument = 0;
const int required_argument = 1;
const int optional_argument = 2;
char* optarg;
int optopt;
/* The variable optind [...] shall be initialized to 1 by the system. */
int optind = 1;
int opterr;
static char* optcursor = NULL;
/* Implemented based on [1] and [2] for optional arguments.
optopt is handled FreeBSD-style, per [3].
Other GNU and FreeBSD extensions are purely accidental.
[1] http://pubs.opengroup.org/onlinepubs/000095399/functions/getopt.html
[2] http://www.kernel.org/doc/man-pages/online/pages/man3/getopt.3.html
[3] http://www.freebsd.org/cgi/man.cgi?query=getopt&sektion=3&manpath=FreeBSD+9.0-RELEASE
*/
int getopt(int argc, char* const argv[], const char* optstring) {
int optchar = -1;
const char* optdecl = NULL;
optarg = NULL;
opterr = 0;
optopt = 0;
/* Unspecified, but we need it to avoid overrunning the argv bounds. */
if (optind >= argc)
goto no_more_optchars;
/* If, when getopt() is called argv[optind] is a null pointer, getopt()
shall return -1 without changing optind. */
if (argv[optind] == NULL)
goto no_more_optchars;
/* If, when getopt() is called *argv[optind] is not the character '-',
getopt() shall return -1 without changing optind. */
if (*argv[optind] != '-')
goto no_more_optchars;
/* If, when getopt() is called argv[optind] points to the string "-",
getopt() shall return -1 without changing optind. */
if (strcmp(argv[optind], "-") == 0)
goto no_more_optchars;
/* If, when getopt() is called argv[optind] points to the string "--",
getopt() shall return -1 after incrementing optind. */
if (strcmp(argv[optind], "--") == 0) {
++optind;
goto no_more_optchars;
}
if (optcursor == NULL || *optcursor == '\0')
optcursor = argv[optind] + 1;
optchar = *optcursor;
/* FreeBSD: The variable optopt saves the last known option character
returned by getopt(). */
optopt = optchar;
/* The getopt() function shall return the next option character (if one is
found) from argv that matches a character in optstring, if there is
one that matches. */
optdecl = strchr(optstring, optchar);
if (optdecl) {
/* [I]f a character is followed by a colon, the option takes an
argument. */
if (optdecl[1] == ':') {
optarg = ++optcursor;
if (*optarg == '\0') {
/* GNU extension: Two colons mean an option takes an
optional arg; if there is text in the current argv-element
(i.e., in the same word as the option name itself, for example,
"-oarg"), then it is returned in optarg, otherwise optarg is set
to zero. */
if (optdecl[2] != ':') {
/* If the option was the last character in the string pointed to by
an element of argv, then optarg shall contain the next element
of argv, and optind shall be incremented by 2. If the resulting
value of optind is greater than argc, this indicates a missing
option-argument, and getopt() shall return an error indication.
Otherwise, optarg shall point to the string following the
option character in that element of argv, and optind shall be
incremented by 1.
*/
if (++optind < argc) {
optarg = argv[optind];
} else {
/* If it detects a missing option-argument, it shall return the
colon character ( ':' ) if the first character of optstring
was a colon, or a question-mark character ( '?' ) otherwise.
*/
optarg = NULL;
optchar = (optstring[0] == ':') ? ':' : '?';
}
} else {
optarg = NULL;
}
}
optcursor = NULL;
}
} else {
/* If getopt() encounters an option character that is not contained in
optstring, it shall return the question-mark ( '?' ) character. */
optchar = '?';
}
if (optcursor == NULL || *++optcursor == '\0')
++optind;
return optchar;
no_more_optchars:
optcursor = NULL;
return -1;
}
/* Implementation based on [1].
[1] http://www.kernel.org/doc/man-pages/online/pages/man3/getopt.3.html
*/
int getopt_long(int argc, char* const argv[], const char* optstring,
const struct option* longopts, int* longindex) {
const struct option* o = longopts;
const struct option* match = NULL;
int num_matches = 0;
size_t argument_name_length = 0;
const char* current_argument = NULL;
int retval = -1;
optarg = NULL;
optopt = 0;
if (optind >= argc)
return -1;
if (strlen(argv[optind]) < 3 || strncmp(argv[optind], "--", 2) != 0)
return getopt(argc, argv, optstring);
/* It's an option; starts with -- and is longer than two chars. */
current_argument = argv[optind] + 2;
argument_name_length = strcspn(current_argument, "=");
for (; o->name; ++o) {
if (strncmp(o->name, current_argument, argument_name_length) == 0) {
match = o;
++num_matches;
}
}
if (num_matches == 1) {
/* If longindex is not NULL, it points to a variable which is set to the
index of the long option relative to longopts. */
if (longindex)
*longindex = (int) (match - longopts);
/* If flag is NULL, then getopt_long() shall return val.
Otherwise, getopt_long() returns 0, and flag shall point to a variable
which shall be set to val if the option is found, but left unchanged if
the option is not found. */
if (match->flag)
*(match->flag) = match->val;
retval = match->flag ? 0 : match->val;
if (match->has_arg != no_argument) {
optarg = strchr(argv[optind], '=');
if (optarg != NULL)
++optarg;
if (match->has_arg == required_argument) {
/* Only scan the next argv for required arguments. Behavior is not
specified, but has been observed with Ubuntu and Mac OSX. */
if (optarg == NULL && ++optind < argc) {
optarg = argv[optind];
}
if (optarg == NULL)
retval = ':';
}
} else if (strchr(argv[optind], '=')) {
/* An argument was provided to a non-argument option.
I haven't seen this specified explicitly, but both GNU and BSD-based
implementations show this behavior.
*/
retval = '?';
}
} else {
/* Unknown option or ambiguous match. */
retval = '?';
}
++optind;
return retval;
}

57
deps/getopt.h vendored
View File

@ -1,57 +0,0 @@
/* Copyright (c) 2012, Kim Gräsman
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Kim Gräsman nor the names of contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL KIM GRÄSMAN BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef INCLUDED_GETOPT_PORT_H
#define INCLUDED_GETOPT_PORT_H
#if defined(__cplusplus)
extern "C" {
#endif
extern const int no_argument;
extern const int required_argument;
extern const int optional_argument;
extern char* optarg;
extern int optind, opterr, optopt;
struct option {
const char* name;
int has_arg;
int* flag;
int val;
};
int getopt(int argc, char* const argv[], const char* optstring);
int getopt_long(int argc, char* const argv[],
const char* optstring, const struct option* longopts, int* longindex);
#if defined(__cplusplus)
}
#endif
#endif // INCLUDED_GETOPT_PORT_H

5996
deps/glad/gl.h vendored

File diff suppressed because it is too large Load Diff

1805
deps/glad/gles2.h vendored

File diff suppressed because it is too large Load Diff

6330
deps/glad/vulkan.h vendored

File diff suppressed because it is too large Load Diff

606
deps/linmath.h vendored
View File

@ -1,606 +0,0 @@
#ifndef LINMATH_H
#define LINMATH_H
#include <string.h>
#include <math.h>
#include <string.h>
/* 2021-03-21 Camilla Löwy <elmindreda@elmindreda.org>
* - Replaced double constants with float equivalents
*/
#ifdef LINMATH_NO_INLINE
#define LINMATH_H_FUNC static
#else
#define LINMATH_H_FUNC static inline
#endif
#define LINMATH_H_DEFINE_VEC(n) \
typedef float vec##n[n]; \
LINMATH_H_FUNC void vec##n##_add(vec##n r, vec##n const a, vec##n const b) \
{ \
int i; \
for(i=0; i<n; ++i) \
r[i] = a[i] + b[i]; \
} \
LINMATH_H_FUNC void vec##n##_sub(vec##n r, vec##n const a, vec##n const b) \
{ \
int i; \
for(i=0; i<n; ++i) \
r[i] = a[i] - b[i]; \
} \
LINMATH_H_FUNC void vec##n##_scale(vec##n r, vec##n const v, float const s) \
{ \
int i; \
for(i=0; i<n; ++i) \
r[i] = v[i] * s; \
} \
LINMATH_H_FUNC float vec##n##_mul_inner(vec##n const a, vec##n const b) \
{ \
float p = 0.f; \
int i; \
for(i=0; i<n; ++i) \
p += b[i]*a[i]; \
return p; \
} \
LINMATH_H_FUNC float vec##n##_len(vec##n const v) \
{ \
return sqrtf(vec##n##_mul_inner(v,v)); \
} \
LINMATH_H_FUNC void vec##n##_norm(vec##n r, vec##n const v) \
{ \
float k = 1.f / vec##n##_len(v); \
vec##n##_scale(r, v, k); \
} \
LINMATH_H_FUNC void vec##n##_min(vec##n r, vec##n const a, vec##n const b) \
{ \
int i; \
for(i=0; i<n; ++i) \
r[i] = a[i]<b[i] ? a[i] : b[i]; \
} \
LINMATH_H_FUNC void vec##n##_max(vec##n r, vec##n const a, vec##n const b) \
{ \
int i; \
for(i=0; i<n; ++i) \
r[i] = a[i]>b[i] ? a[i] : b[i]; \
} \
LINMATH_H_FUNC void vec##n##_dup(vec##n r, vec##n const src) \
{ \
int i; \
for(i=0; i<n; ++i) \
r[i] = src[i]; \
}
LINMATH_H_DEFINE_VEC(2)
LINMATH_H_DEFINE_VEC(3)
LINMATH_H_DEFINE_VEC(4)
LINMATH_H_FUNC void vec3_mul_cross(vec3 r, vec3 const a, vec3 const b)
{
r[0] = a[1]*b[2] - a[2]*b[1];
r[1] = a[2]*b[0] - a[0]*b[2];
r[2] = a[0]*b[1] - a[1]*b[0];
}
LINMATH_H_FUNC void vec3_reflect(vec3 r, vec3 const v, vec3 const n)
{
float p = 2.f * vec3_mul_inner(v, n);
int i;
for(i=0;i<3;++i)
r[i] = v[i] - p*n[i];
}
LINMATH_H_FUNC void vec4_mul_cross(vec4 r, vec4 const a, vec4 const b)
{
r[0] = a[1]*b[2] - a[2]*b[1];
r[1] = a[2]*b[0] - a[0]*b[2];
r[2] = a[0]*b[1] - a[1]*b[0];
r[3] = 1.f;
}
LINMATH_H_FUNC void vec4_reflect(vec4 r, vec4 const v, vec4 const n)
{
float p = 2.f*vec4_mul_inner(v, n);
int i;
for(i=0;i<4;++i)
r[i] = v[i] - p*n[i];
}
typedef vec4 mat4x4[4];
LINMATH_H_FUNC void mat4x4_identity(mat4x4 M)
{
int i, j;
for(i=0; i<4; ++i)
for(j=0; j<4; ++j)
M[i][j] = i==j ? 1.f : 0.f;
}
LINMATH_H_FUNC void mat4x4_dup(mat4x4 M, mat4x4 const N)
{
int i;
for(i=0; i<4; ++i)
vec4_dup(M[i], N[i]);
}
LINMATH_H_FUNC void mat4x4_row(vec4 r, mat4x4 const M, int i)
{
int k;
for(k=0; k<4; ++k)
r[k] = M[k][i];
}
LINMATH_H_FUNC void mat4x4_col(vec4 r, mat4x4 const M, int i)
{
int k;
for(k=0; k<4; ++k)
r[k] = M[i][k];
}
LINMATH_H_FUNC void mat4x4_transpose(mat4x4 M, mat4x4 const N)
{
// Note: if M and N are the same, the user has to
// explicitly make a copy of M and set it to N.
int i, j;
for(j=0; j<4; ++j)
for(i=0; i<4; ++i)
M[i][j] = N[j][i];
}
LINMATH_H_FUNC void mat4x4_add(mat4x4 M, mat4x4 const a, mat4x4 const b)
{
int i;
for(i=0; i<4; ++i)
vec4_add(M[i], a[i], b[i]);
}
LINMATH_H_FUNC void mat4x4_sub(mat4x4 M, mat4x4 const a, mat4x4 const b)
{
int i;
for(i=0; i<4; ++i)
vec4_sub(M[i], a[i], b[i]);
}
LINMATH_H_FUNC void mat4x4_scale(mat4x4 M, mat4x4 const a, float k)
{
int i;
for(i=0; i<4; ++i)
vec4_scale(M[i], a[i], k);
}
LINMATH_H_FUNC void mat4x4_scale_aniso(mat4x4 M, mat4x4 const a, float x, float y, float z)
{
vec4_scale(M[0], a[0], x);
vec4_scale(M[1], a[1], y);
vec4_scale(M[2], a[2], z);
vec4_dup(M[3], a[3]);
}
LINMATH_H_FUNC void mat4x4_mul(mat4x4 M, mat4x4 const a, mat4x4 const b)
{
mat4x4 temp;
int k, r, c;
for(c=0; c<4; ++c) for(r=0; r<4; ++r) {
temp[c][r] = 0.f;
for(k=0; k<4; ++k)
temp[c][r] += a[k][r] * b[c][k];
}
mat4x4_dup(M, temp);
}
LINMATH_H_FUNC void mat4x4_mul_vec4(vec4 r, mat4x4 const M, vec4 const v)
{
int i, j;
for(j=0; j<4; ++j) {
r[j] = 0.f;
for(i=0; i<4; ++i)
r[j] += M[i][j] * v[i];
}
}
LINMATH_H_FUNC void mat4x4_translate(mat4x4 T, float x, float y, float z)
{
mat4x4_identity(T);
T[3][0] = x;
T[3][1] = y;
T[3][2] = z;
}
LINMATH_H_FUNC void mat4x4_translate_in_place(mat4x4 M, float x, float y, float z)
{
vec4 t = {x, y, z, 0};
vec4 r;
int i;
for (i = 0; i < 4; ++i) {
mat4x4_row(r, M, i);
M[3][i] += vec4_mul_inner(r, t);
}
}
LINMATH_H_FUNC void mat4x4_from_vec3_mul_outer(mat4x4 M, vec3 const a, vec3 const b)
{
int i, j;
for(i=0; i<4; ++i) for(j=0; j<4; ++j)
M[i][j] = i<3 && j<3 ? a[i] * b[j] : 0.f;
}
LINMATH_H_FUNC void mat4x4_rotate(mat4x4 R, mat4x4 const M, float x, float y, float z, float angle)
{
float s = sinf(angle);
float c = cosf(angle);
vec3 u = {x, y, z};
if(vec3_len(u) > 1e-4) {
vec3_norm(u, u);
mat4x4 T;
mat4x4_from_vec3_mul_outer(T, u, u);
mat4x4 S = {
{ 0, u[2], -u[1], 0},
{-u[2], 0, u[0], 0},
{ u[1], -u[0], 0, 0},
{ 0, 0, 0, 0}
};
mat4x4_scale(S, S, s);
mat4x4 C;
mat4x4_identity(C);
mat4x4_sub(C, C, T);
mat4x4_scale(C, C, c);
mat4x4_add(T, T, C);
mat4x4_add(T, T, S);
T[3][3] = 1.f;
mat4x4_mul(R, M, T);
} else {
mat4x4_dup(R, M);
}
}
LINMATH_H_FUNC void mat4x4_rotate_X(mat4x4 Q, mat4x4 const M, float angle)
{
float s = sinf(angle);
float c = cosf(angle);
mat4x4 R = {
{1.f, 0.f, 0.f, 0.f},
{0.f, c, s, 0.f},
{0.f, -s, c, 0.f},
{0.f, 0.f, 0.f, 1.f}
};
mat4x4_mul(Q, M, R);
}
LINMATH_H_FUNC void mat4x4_rotate_Y(mat4x4 Q, mat4x4 const M, float angle)
{
float s = sinf(angle);
float c = cosf(angle);
mat4x4 R = {
{ c, 0.f, -s, 0.f},
{ 0.f, 1.f, 0.f, 0.f},
{ s, 0.f, c, 0.f},
{ 0.f, 0.f, 0.f, 1.f}
};
mat4x4_mul(Q, M, R);
}
LINMATH_H_FUNC void mat4x4_rotate_Z(mat4x4 Q, mat4x4 const M, float angle)
{
float s = sinf(angle);
float c = cosf(angle);
mat4x4 R = {
{ c, s, 0.f, 0.f},
{ -s, c, 0.f, 0.f},
{ 0.f, 0.f, 1.f, 0.f},
{ 0.f, 0.f, 0.f, 1.f}
};
mat4x4_mul(Q, M, R);
}
LINMATH_H_FUNC void mat4x4_invert(mat4x4 T, mat4x4 const M)
{
float s[6];
float c[6];
s[0] = M[0][0]*M[1][1] - M[1][0]*M[0][1];
s[1] = M[0][0]*M[1][2] - M[1][0]*M[0][2];
s[2] = M[0][0]*M[1][3] - M[1][0]*M[0][3];
s[3] = M[0][1]*M[1][2] - M[1][1]*M[0][2];
s[4] = M[0][1]*M[1][3] - M[1][1]*M[0][3];
s[5] = M[0][2]*M[1][3] - M[1][2]*M[0][3];
c[0] = M[2][0]*M[3][1] - M[3][0]*M[2][1];
c[1] = M[2][0]*M[3][2] - M[3][0]*M[2][2];
c[2] = M[2][0]*M[3][3] - M[3][0]*M[2][3];
c[3] = M[2][1]*M[3][2] - M[3][1]*M[2][2];
c[4] = M[2][1]*M[3][3] - M[3][1]*M[2][3];
c[5] = M[2][2]*M[3][3] - M[3][2]*M[2][3];
/* Assumes it is invertible */
float idet = 1.0f/( s[0]*c[5]-s[1]*c[4]+s[2]*c[3]+s[3]*c[2]-s[4]*c[1]+s[5]*c[0] );
T[0][0] = ( M[1][1] * c[5] - M[1][2] * c[4] + M[1][3] * c[3]) * idet;
T[0][1] = (-M[0][1] * c[5] + M[0][2] * c[4] - M[0][3] * c[3]) * idet;
T[0][2] = ( M[3][1] * s[5] - M[3][2] * s[4] + M[3][3] * s[3]) * idet;
T[0][3] = (-M[2][1] * s[5] + M[2][2] * s[4] - M[2][3] * s[3]) * idet;
T[1][0] = (-M[1][0] * c[5] + M[1][2] * c[2] - M[1][3] * c[1]) * idet;
T[1][1] = ( M[0][0] * c[5] - M[0][2] * c[2] + M[0][3] * c[1]) * idet;
T[1][2] = (-M[3][0] * s[5] + M[3][2] * s[2] - M[3][3] * s[1]) * idet;
T[1][3] = ( M[2][0] * s[5] - M[2][2] * s[2] + M[2][3] * s[1]) * idet;
T[2][0] = ( M[1][0] * c[4] - M[1][1] * c[2] + M[1][3] * c[0]) * idet;
T[2][1] = (-M[0][0] * c[4] + M[0][1] * c[2] - M[0][3] * c[0]) * idet;
T[2][2] = ( M[3][0] * s[4] - M[3][1] * s[2] + M[3][3] * s[0]) * idet;
T[2][3] = (-M[2][0] * s[4] + M[2][1] * s[2] - M[2][3] * s[0]) * idet;
T[3][0] = (-M[1][0] * c[3] + M[1][1] * c[1] - M[1][2] * c[0]) * idet;
T[3][1] = ( M[0][0] * c[3] - M[0][1] * c[1] + M[0][2] * c[0]) * idet;
T[3][2] = (-M[3][0] * s[3] + M[3][1] * s[1] - M[3][2] * s[0]) * idet;
T[3][3] = ( M[2][0] * s[3] - M[2][1] * s[1] + M[2][2] * s[0]) * idet;
}
LINMATH_H_FUNC void mat4x4_orthonormalize(mat4x4 R, mat4x4 const M)
{
mat4x4_dup(R, M);
float s = 1.f;
vec3 h;
vec3_norm(R[2], R[2]);
s = vec3_mul_inner(R[1], R[2]);
vec3_scale(h, R[2], s);
vec3_sub(R[1], R[1], h);
vec3_norm(R[1], R[1]);
s = vec3_mul_inner(R[0], R[2]);
vec3_scale(h, R[2], s);
vec3_sub(R[0], R[0], h);
s = vec3_mul_inner(R[0], R[1]);
vec3_scale(h, R[1], s);
vec3_sub(R[0], R[0], h);
vec3_norm(R[0], R[0]);
}
LINMATH_H_FUNC void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t, float n, float f)
{
M[0][0] = 2.f*n/(r-l);
M[0][1] = M[0][2] = M[0][3] = 0.f;
M[1][1] = 2.f*n/(t-b);
M[1][0] = M[1][2] = M[1][3] = 0.f;
M[2][0] = (r+l)/(r-l);
M[2][1] = (t+b)/(t-b);
M[2][2] = -(f+n)/(f-n);
M[2][3] = -1.f;
M[3][2] = -2.f*(f*n)/(f-n);
M[3][0] = M[3][1] = M[3][3] = 0.f;
}
LINMATH_H_FUNC void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t, float n, float f)
{
M[0][0] = 2.f/(r-l);
M[0][1] = M[0][2] = M[0][3] = 0.f;
M[1][1] = 2.f/(t-b);
M[1][0] = M[1][2] = M[1][3] = 0.f;
M[2][2] = -2.f/(f-n);
M[2][0] = M[2][1] = M[2][3] = 0.f;
M[3][0] = -(r+l)/(r-l);
M[3][1] = -(t+b)/(t-b);
M[3][2] = -(f+n)/(f-n);
M[3][3] = 1.f;
}
LINMATH_H_FUNC void mat4x4_perspective(mat4x4 m, float y_fov, float aspect, float n, float f)
{
/* NOTE: Degrees are an unhandy unit to work with.
* linmath.h uses radians for everything! */
float const a = 1.f / tanf(y_fov / 2.f);
m[0][0] = a / aspect;
m[0][1] = 0.f;
m[0][2] = 0.f;
m[0][3] = 0.f;
m[1][0] = 0.f;
m[1][1] = a;
m[1][2] = 0.f;
m[1][3] = 0.f;
m[2][0] = 0.f;
m[2][1] = 0.f;
m[2][2] = -((f + n) / (f - n));
m[2][3] = -1.f;
m[3][0] = 0.f;
m[3][1] = 0.f;
m[3][2] = -((2.f * f * n) / (f - n));
m[3][3] = 0.f;
}
LINMATH_H_FUNC void mat4x4_look_at(mat4x4 m, vec3 const eye, vec3 const center, vec3 const up)
{
/* Adapted from Android's OpenGL Matrix.java. */
/* See the OpenGL GLUT documentation for gluLookAt for a description */
/* of the algorithm. We implement it in a straightforward way: */
/* TODO: The negation of of can be spared by swapping the order of
* operands in the following cross products in the right way. */
vec3 f;
vec3_sub(f, center, eye);
vec3_norm(f, f);
vec3 s;
vec3_mul_cross(s, f, up);
vec3_norm(s, s);
vec3 t;
vec3_mul_cross(t, s, f);
m[0][0] = s[0];
m[0][1] = t[0];
m[0][2] = -f[0];
m[0][3] = 0.f;
m[1][0] = s[1];
m[1][1] = t[1];
m[1][2] = -f[1];
m[1][3] = 0.f;
m[2][0] = s[2];
m[2][1] = t[2];
m[2][2] = -f[2];
m[2][3] = 0.f;
m[3][0] = 0.f;
m[3][1] = 0.f;
m[3][2] = 0.f;
m[3][3] = 1.f;
mat4x4_translate_in_place(m, -eye[0], -eye[1], -eye[2]);
}
typedef float quat[4];
#define quat_add vec4_add
#define quat_sub vec4_sub
#define quat_norm vec4_norm
#define quat_scale vec4_scale
#define quat_mul_inner vec4_mul_inner
LINMATH_H_FUNC void quat_identity(quat q)
{
q[0] = q[1] = q[2] = 0.f;
q[3] = 1.f;
}
LINMATH_H_FUNC void quat_mul(quat r, quat const p, quat const q)
{
vec3 w;
vec3_mul_cross(r, p, q);
vec3_scale(w, p, q[3]);
vec3_add(r, r, w);
vec3_scale(w, q, p[3]);
vec3_add(r, r, w);
r[3] = p[3]*q[3] - vec3_mul_inner(p, q);
}
LINMATH_H_FUNC void quat_conj(quat r, quat const q)
{
int i;
for(i=0; i<3; ++i)
r[i] = -q[i];
r[3] = q[3];
}
LINMATH_H_FUNC void quat_rotate(quat r, float angle, vec3 const axis) {
vec3 axis_norm;
vec3_norm(axis_norm, axis);
float s = sinf(angle / 2);
float c = cosf(angle / 2);
vec3_scale(r, axis_norm, s);
r[3] = c;
}
LINMATH_H_FUNC void quat_mul_vec3(vec3 r, quat const q, vec3 const v)
{
/*
* Method by Fabian 'ryg' Giessen (of Farbrausch)
t = 2 * cross(q.xyz, v)
v' = v + q.w * t + cross(q.xyz, t)
*/
vec3 t;
vec3 q_xyz = {q[0], q[1], q[2]};
vec3 u = {q[0], q[1], q[2]};
vec3_mul_cross(t, q_xyz, v);
vec3_scale(t, t, 2);
vec3_mul_cross(u, q_xyz, t);
vec3_scale(t, t, q[3]);
vec3_add(r, v, t);
vec3_add(r, r, u);
}
LINMATH_H_FUNC void mat4x4_from_quat(mat4x4 M, quat const q)
{
float a = q[3];
float b = q[0];
float c = q[1];
float d = q[2];
float a2 = a*a;
float b2 = b*b;
float c2 = c*c;
float d2 = d*d;
M[0][0] = a2 + b2 - c2 - d2;
M[0][1] = 2.f*(b*c + a*d);
M[0][2] = 2.f*(b*d - a*c);
M[0][3] = 0.f;
M[1][0] = 2*(b*c - a*d);
M[1][1] = a2 - b2 + c2 - d2;
M[1][2] = 2.f*(c*d + a*b);
M[1][3] = 0.f;
M[2][0] = 2.f*(b*d + a*c);
M[2][1] = 2.f*(c*d - a*b);
M[2][2] = a2 - b2 - c2 + d2;
M[2][3] = 0.f;
M[3][0] = M[3][1] = M[3][2] = 0.f;
M[3][3] = 1.f;
}
LINMATH_H_FUNC void mat4x4o_mul_quat(mat4x4 R, mat4x4 const M, quat const q)
{
/* XXX: The way this is written only works for orthogonal matrices. */
/* TODO: Take care of non-orthogonal case. */
quat_mul_vec3(R[0], q, M[0]);
quat_mul_vec3(R[1], q, M[1]);
quat_mul_vec3(R[2], q, M[2]);
R[3][0] = R[3][1] = R[3][2] = 0.f;
R[0][3] = M[0][3];
R[1][3] = M[1][3];
R[2][3] = M[2][3];
R[3][3] = M[3][3]; // typically 1.0, but here we make it general
}
LINMATH_H_FUNC void quat_from_mat4x4(quat q, mat4x4 const M)
{
float r=0.f;
int i;
int perm[] = { 0, 1, 2, 0, 1 };
int *p = perm;
for(i = 0; i<3; i++) {
float m = M[i][i];
if( m < r )
continue;
m = r;
p = &perm[i];
}
r = sqrtf(1.f + M[p[0]][p[0]] - M[p[1]][p[1]] - M[p[2]][p[2]] );
if(r < 1e-6) {
q[0] = 1.f;
q[1] = q[2] = q[3] = 0.f;
return;
}
q[0] = r/2.f;
q[1] = (M[p[0]][p[1]] - M[p[1]][p[0]])/(2.f*r);
q[2] = (M[p[2]][p[0]] - M[p[0]][p[2]])/(2.f*r);
q[3] = (M[p[2]][p[1]] - M[p[1]][p[2]])/(2.f*r);
}
LINMATH_H_FUNC void mat4x4_arcball(mat4x4 R, mat4x4 const M, vec2 const _a, vec2 const _b, float s)
{
vec2 a; memcpy(a, _a, sizeof(a));
vec2 b; memcpy(b, _b, sizeof(b));
float z_a = 0.f;
float z_b = 0.f;
if(vec2_len(a) < 1.f) {
z_a = sqrtf(1.f - vec2_mul_inner(a, a));
} else {
vec2_norm(a, a);
}
if(vec2_len(b) < 1.f) {
z_b = sqrtf(1.f - vec2_mul_inner(b, b));
} else {
vec2_norm(b, b);
}
vec3 a_ = {a[0], a[1], z_a};
vec3 b_ = {b[0], b[1], z_b};
vec3 c_;
vec3_mul_cross(c_, a_, b_);
float const angle = acos(vec3_mul_inner(a_, b_)) * s;
mat4x4_rotate(R, M, c_[0], c_[1], c_[2], angle);
}
#endif

View File

@ -1,117 +0,0 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER within this package.
*/
#if defined(_MSC_VER) && !defined(_MSC_EXTENSIONS)
#define NONAMELESSUNION 1
#endif
#if defined(NONAMELESSSTRUCT) && \
!defined(NONAMELESSUNION)
#define NONAMELESSUNION 1
#endif
#if defined(NONAMELESSUNION) && \
!defined(NONAMELESSSTRUCT)
#define NONAMELESSSTRUCT 1
#endif
#if !defined(__GNU_EXTENSION)
#if defined(__GNUC__) || defined(__GNUG__)
#define __GNU_EXTENSION __extension__
#else
#define __GNU_EXTENSION
#endif
#endif /* __extension__ */
#ifndef __ANONYMOUS_DEFINED
#define __ANONYMOUS_DEFINED
#if defined(__GNUC__) || defined(__GNUG__)
#define _ANONYMOUS_UNION __extension__
#define _ANONYMOUS_STRUCT __extension__
#else
#define _ANONYMOUS_UNION
#define _ANONYMOUS_STRUCT
#endif
#ifndef NONAMELESSUNION
#define _UNION_NAME(x)
#define _STRUCT_NAME(x)
#else /* NONAMELESSUNION */
#define _UNION_NAME(x) x
#define _STRUCT_NAME(x) x
#endif
#endif /* __ANONYMOUS_DEFINED */
#ifndef DUMMYUNIONNAME
# ifdef NONAMELESSUNION
# define DUMMYUNIONNAME u
# define DUMMYUNIONNAME1 u1 /* Wine uses this variant */
# define DUMMYUNIONNAME2 u2
# define DUMMYUNIONNAME3 u3
# define DUMMYUNIONNAME4 u4
# define DUMMYUNIONNAME5 u5
# define DUMMYUNIONNAME6 u6
# define DUMMYUNIONNAME7 u7
# define DUMMYUNIONNAME8 u8
# define DUMMYUNIONNAME9 u9
# else /* NONAMELESSUNION */
# define DUMMYUNIONNAME
# define DUMMYUNIONNAME1 /* Wine uses this variant */
# define DUMMYUNIONNAME2
# define DUMMYUNIONNAME3
# define DUMMYUNIONNAME4
# define DUMMYUNIONNAME5
# define DUMMYUNIONNAME6
# define DUMMYUNIONNAME7
# define DUMMYUNIONNAME8
# define DUMMYUNIONNAME9
# endif
#endif /* DUMMYUNIONNAME */
#if !defined(DUMMYUNIONNAME1) /* MinGW does not define this one */
# ifdef NONAMELESSUNION
# define DUMMYUNIONNAME1 u1 /* Wine uses this variant */
# else
# define DUMMYUNIONNAME1 /* Wine uses this variant */
# endif
#endif /* DUMMYUNIONNAME1 */
#ifndef DUMMYSTRUCTNAME
# ifdef NONAMELESSUNION
# define DUMMYSTRUCTNAME s
# define DUMMYSTRUCTNAME1 s1 /* Wine uses this variant */
# define DUMMYSTRUCTNAME2 s2
# define DUMMYSTRUCTNAME3 s3
# define DUMMYSTRUCTNAME4 s4
# define DUMMYSTRUCTNAME5 s5
# else
# define DUMMYSTRUCTNAME
# define DUMMYSTRUCTNAME1 /* Wine uses this variant */
# define DUMMYSTRUCTNAME2
# define DUMMYSTRUCTNAME3
# define DUMMYSTRUCTNAME4
# define DUMMYSTRUCTNAME5
# endif
#endif /* DUMMYSTRUCTNAME */
/* These are for compatibility with the Wine source tree */
#ifndef WINELIB_NAME_AW
# ifdef __MINGW_NAME_AW
# define WINELIB_NAME_AW __MINGW_NAME_AW
# else
# ifdef UNICODE
# define WINELIB_NAME_AW(func) func##W
# else
# define WINELIB_NAME_AW(func) func##A
# endif
# endif
#endif /* WINELIB_NAME_AW */
#ifndef DECL_WINELIB_TYPE_AW
# ifdef __MINGW_TYPEDEF_AW
# define DECL_WINELIB_TYPE_AW __MINGW_TYPEDEF_AW
# else
# define DECL_WINELIB_TYPE_AW(type) typedef WINELIB_NAME_AW(type) type;
# endif
#endif /* DECL_WINELIB_TYPE_AW */

2467
deps/mingw/dinput.h vendored

File diff suppressed because it is too large Load Diff

239
deps/mingw/xinput.h vendored
View File

@ -1,239 +0,0 @@
/*
* The Wine project - Xinput Joystick Library
* Copyright 2008 Andrew Fenn
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __WINE_XINPUT_H
#define __WINE_XINPUT_H
#include <windef.h>
/*
* Bitmasks for the joysticks buttons, determines what has
* been pressed on the joystick, these need to be mapped
* to whatever device you're using instead of an xbox 360
* joystick
*/
#define XINPUT_GAMEPAD_DPAD_UP 0x0001
#define XINPUT_GAMEPAD_DPAD_DOWN 0x0002
#define XINPUT_GAMEPAD_DPAD_LEFT 0x0004
#define XINPUT_GAMEPAD_DPAD_RIGHT 0x0008
#define XINPUT_GAMEPAD_START 0x0010
#define XINPUT_GAMEPAD_BACK 0x0020
#define XINPUT_GAMEPAD_LEFT_THUMB 0x0040
#define XINPUT_GAMEPAD_RIGHT_THUMB 0x0080
#define XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100
#define XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200
#define XINPUT_GAMEPAD_A 0x1000
#define XINPUT_GAMEPAD_B 0x2000
#define XINPUT_GAMEPAD_X 0x4000
#define XINPUT_GAMEPAD_Y 0x8000
/*
* Defines the flags used to determine if the user is pushing
* down on a button, not holding a button, etc
*/
#define XINPUT_KEYSTROKE_KEYDOWN 0x0001
#define XINPUT_KEYSTROKE_KEYUP 0x0002
#define XINPUT_KEYSTROKE_REPEAT 0x0004
/*
* Defines the codes which are returned by XInputGetKeystroke
*/
#define VK_PAD_A 0x5800
#define VK_PAD_B 0x5801
#define VK_PAD_X 0x5802
#define VK_PAD_Y 0x5803
#define VK_PAD_RSHOULDER 0x5804
#define VK_PAD_LSHOULDER 0x5805
#define VK_PAD_LTRIGGER 0x5806
#define VK_PAD_RTRIGGER 0x5807
#define VK_PAD_DPAD_UP 0x5810
#define VK_PAD_DPAD_DOWN 0x5811
#define VK_PAD_DPAD_LEFT 0x5812
#define VK_PAD_DPAD_RIGHT 0x5813
#define VK_PAD_START 0x5814
#define VK_PAD_BACK 0x5815
#define VK_PAD_LTHUMB_PRESS 0x5816
#define VK_PAD_RTHUMB_PRESS 0x5817
#define VK_PAD_LTHUMB_UP 0x5820
#define VK_PAD_LTHUMB_DOWN 0x5821
#define VK_PAD_LTHUMB_RIGHT 0x5822
#define VK_PAD_LTHUMB_LEFT 0x5823
#define VK_PAD_LTHUMB_UPLEFT 0x5824
#define VK_PAD_LTHUMB_UPRIGHT 0x5825
#define VK_PAD_LTHUMB_DOWNRIGHT 0x5826
#define VK_PAD_LTHUMB_DOWNLEFT 0x5827
#define VK_PAD_RTHUMB_UP 0x5830
#define VK_PAD_RTHUMB_DOWN 0x5831
#define VK_PAD_RTHUMB_RIGHT 0x5832
#define VK_PAD_RTHUMB_LEFT 0x5833
#define VK_PAD_RTHUMB_UPLEFT 0x5834
#define VK_PAD_RTHUMB_UPRIGHT 0x5835
#define VK_PAD_RTHUMB_DOWNRIGHT 0x5836
#define VK_PAD_RTHUMB_DOWNLEFT 0x5837
/*
* Deadzones are for analogue joystick controls on the joypad
* which determine when input should be assumed to be in the
* middle of the pad. This is a threshold to stop a joypad
* controlling the game when the player isn't touching the
* controls.
*/
#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
/*
* Defines what type of abilities the type of joystick has
* DEVTYPE_GAMEPAD is available for all joysticks, however
* there may be more specific identifiers for other joysticks
* which are being used.
*/
#define XINPUT_DEVTYPE_GAMEPAD 0x01
#define XINPUT_DEVSUBTYPE_GAMEPAD 0x01
#define XINPUT_DEVSUBTYPE_WHEEL 0x02
#define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
#define XINPUT_DEVSUBTYPE_FLIGHT_SICK 0x04
#define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
#define XINPUT_DEVSUBTYPE_GUITAR 0x06
#define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
/*
* These are used with the XInputGetCapabilities function to
* determine the abilities to the joystick which has been
* plugged in.
*/
#define XINPUT_CAPS_VOICE_SUPPORTED 0x0004
#define XINPUT_FLAG_GAMEPAD 0x00000001
/*
* Defines the status of the battery if one is used in the
* attached joystick. The first two define if the joystick
* supports a battery. Disconnected means that the joystick
* isn't connected. Wired shows that the joystick is a wired
* joystick.
*/
#define BATTERY_DEVTYPE_GAMEPAD 0x00
#define BATTERY_DEVTYPE_HEADSET 0x01
#define BATTERY_TYPE_DISCONNECTED 0x00
#define BATTERY_TYPE_WIRED 0x01
#define BATTERY_TYPE_ALKALINE 0x02
#define BATTERY_TYPE_NIMH 0x03
#define BATTERY_TYPE_UNKNOWN 0xFF
#define BATTERY_LEVEL_EMPTY 0x00
#define BATTERY_LEVEL_LOW 0x01
#define BATTERY_LEVEL_MEDIUM 0x02
#define BATTERY_LEVEL_FULL 0x03
/*
* How many joysticks can be used with this library. Games that
* use the xinput library will not go over this number.
*/
#define XUSER_MAX_COUNT 4
#define XUSER_INDEX_ANY 0x000000FF
/*
* Defines the structure of an xbox 360 joystick.
*/
typedef struct _XINPUT_GAMEPAD {
WORD wButtons;
BYTE bLeftTrigger;
BYTE bRightTrigger;
SHORT sThumbLX;
SHORT sThumbLY;
SHORT sThumbRX;
SHORT sThumbRY;
} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;
typedef struct _XINPUT_STATE {
DWORD dwPacketNumber;
XINPUT_GAMEPAD Gamepad;
} XINPUT_STATE, *PXINPUT_STATE;
/*
* Defines the structure of how much vibration is set on both the
* right and left motors in a joystick. If you're not using a 360
* joystick you will have to map these to your device.
*/
typedef struct _XINPUT_VIBRATION {
WORD wLeftMotorSpeed;
WORD wRightMotorSpeed;
} XINPUT_VIBRATION, *PXINPUT_VIBRATION;
/*
* Defines the structure for what kind of abilities the joystick has
* such abilities are things such as if the joystick has the ability
* to send and receive audio, if the joystick is in fact a driving
* wheel or perhaps if the joystick is some kind of dance pad or
* guitar.
*/
typedef struct _XINPUT_CAPABILITIES {
BYTE Type;
BYTE SubType;
WORD Flags;
XINPUT_GAMEPAD Gamepad;
XINPUT_VIBRATION Vibration;
} XINPUT_CAPABILITIES, *PXINPUT_CAPABILITIES;
/*
* Defines the structure for a joystick input event which is
* retrieved using the function XInputGetKeystroke
*/
typedef struct _XINPUT_KEYSTROKE {
WORD VirtualKey;
WCHAR Unicode;
WORD Flags;
BYTE UserIndex;
BYTE HidCode;
} XINPUT_KEYSTROKE, *PXINPUT_KEYSTROKE;
typedef struct _XINPUT_BATTERY_INFORMATION
{
BYTE BatteryType;
BYTE BatteryLevel;
} XINPUT_BATTERY_INFORMATION, *PXINPUT_BATTERY_INFORMATION;
#ifdef __cplusplus
extern "C" {
#endif
void WINAPI XInputEnable(WINBOOL);
DWORD WINAPI XInputSetState(DWORD, XINPUT_VIBRATION*);
DWORD WINAPI XInputGetState(DWORD, XINPUT_STATE*);
DWORD WINAPI XInputGetKeystroke(DWORD, DWORD, PXINPUT_KEYSTROKE);
DWORD WINAPI XInputGetCapabilities(DWORD, DWORD, XINPUT_CAPABILITIES*);
DWORD WINAPI XInputGetDSoundAudioDeviceGuids(DWORD, GUID*, GUID*);
DWORD WINAPI XInputGetBatteryInformation(DWORD, BYTE, XINPUT_BATTERY_INFORMATION*);
#ifdef __cplusplus
}
#endif
#endif /* __WINE_XINPUT_H */

25778
deps/nuklear.h vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,381 +0,0 @@
/*
* Nuklear - v1.32.0 - public domain
* no warrenty implied; use at your own risk.
* authored from 2015-2017 by Micha Mettke
*/
/*
* ==============================================================
*
* API
*
* ===============================================================
*/
#ifndef NK_GLFW_GL2_H_
#define NK_GLFW_GL2_H_
#include <GLFW/glfw3.h>
enum nk_glfw_init_state{
NK_GLFW3_DEFAULT = 0,
NK_GLFW3_INSTALL_CALLBACKS
};
NK_API struct nk_context* nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state);
NK_API void nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas);
NK_API void nk_glfw3_font_stash_end(void);
NK_API void nk_glfw3_new_frame(void);
NK_API void nk_glfw3_render(enum nk_anti_aliasing);
NK_API void nk_glfw3_shutdown(void);
NK_API void nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff);
#endif
/*
* ==============================================================
*
* IMPLEMENTATION
*
* ===============================================================
*/
#ifdef NK_GLFW_GL2_IMPLEMENTATION
#ifndef NK_GLFW_TEXT_MAX
#define NK_GLFW_TEXT_MAX 256
#endif
#ifndef NK_GLFW_DOUBLE_CLICK_LO
#define NK_GLFW_DOUBLE_CLICK_LO 0.02
#endif
#ifndef NK_GLFW_DOUBLE_CLICK_HI
#define NK_GLFW_DOUBLE_CLICK_HI 0.2
#endif
struct nk_glfw_device {
struct nk_buffer cmds;
struct nk_draw_null_texture null;
GLuint font_tex;
};
struct nk_glfw_vertex {
float position[2];
float uv[2];
nk_byte col[4];
};
static struct nk_glfw {
GLFWwindow *win;
int width, height;
int display_width, display_height;
struct nk_glfw_device ogl;
struct nk_context ctx;
struct nk_font_atlas atlas;
struct nk_vec2 fb_scale;
unsigned int text[NK_GLFW_TEXT_MAX];
int text_len;
struct nk_vec2 scroll;
double last_button_click;
int is_double_click_down;
struct nk_vec2 double_click_pos;
} glfw;
NK_INTERN void
nk_glfw3_device_upload_atlas(const void *image, int width, int height)
{
struct nk_glfw_device *dev = &glfw.ogl;
glGenTextures(1, &dev->font_tex);
glBindTexture(GL_TEXTURE_2D, dev->font_tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, image);
}
NK_API void
nk_glfw3_render(enum nk_anti_aliasing AA)
{
/* setup global state */
struct nk_glfw_device *dev = &glfw.ogl;
glPushAttrib(GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT|GL_TRANSFORM_BIT);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST);
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/* setup viewport/project */
glViewport(0,0,(GLsizei)glfw.display_width,(GLsizei)glfw.display_height);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0f, glfw.width, glfw.height, 0.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
{
GLsizei vs = sizeof(struct nk_glfw_vertex);
size_t vp = offsetof(struct nk_glfw_vertex, position);
size_t vt = offsetof(struct nk_glfw_vertex, uv);
size_t vc = offsetof(struct nk_glfw_vertex, col);
/* convert from command queue into draw list and draw to screen */
const struct nk_draw_command *cmd;
const nk_draw_index *offset = NULL;
struct nk_buffer vbuf, ebuf;
/* fill convert configuration */
struct nk_convert_config config;
static const struct nk_draw_vertex_layout_element vertex_layout[] = {
{NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)},
{NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)},
{NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)},
{NK_VERTEX_LAYOUT_END}
};
NK_MEMSET(&config, 0, sizeof(config));
config.vertex_layout = vertex_layout;
config.vertex_size = sizeof(struct nk_glfw_vertex);
config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex);
config.null = dev->null;
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
config.global_alpha = 1.0f;
config.shape_AA = AA;
config.line_AA = AA;
/* convert shapes into vertexes */
nk_buffer_init_default(&vbuf);
nk_buffer_init_default(&ebuf);
nk_convert(&glfw.ctx, &dev->cmds, &vbuf, &ebuf, &config);
/* setup vertex buffer pointer */
{const void *vertices = nk_buffer_memory_const(&vbuf);
glVertexPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vp));
glTexCoordPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vt));
glColorPointer(4, GL_UNSIGNED_BYTE, vs, (const void*)((const nk_byte*)vertices + vc));}
/* iterate over and execute each draw command */
offset = (const nk_draw_index*)nk_buffer_memory_const(&ebuf);
nk_draw_foreach(cmd, &glfw.ctx, &dev->cmds)
{
if (!cmd->elem_count) continue;
glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
glScissor(
(GLint)(cmd->clip_rect.x * glfw.fb_scale.x),
(GLint)((glfw.height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * glfw.fb_scale.y),
(GLint)(cmd->clip_rect.w * glfw.fb_scale.x),
(GLint)(cmd->clip_rect.h * glfw.fb_scale.y));
glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
offset += cmd->elem_count;
}
nk_clear(&glfw.ctx);
nk_buffer_free(&vbuf);
nk_buffer_free(&ebuf);
}
/* default OpenGL state */
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
}
NK_API void
nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint)
{
(void)win;
if (glfw.text_len < NK_GLFW_TEXT_MAX)
glfw.text[glfw.text_len++] = codepoint;
}
NK_API void
nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff)
{
(void)win; (void)xoff;
glfw.scroll.x += (float)xoff;
glfw.scroll.y += (float)yoff;
}
NK_API void
nk_glfw3_mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
double x, y;
if (button != GLFW_MOUSE_BUTTON_LEFT) return;
glfwGetCursorPos(window, &x, &y);
if (action == GLFW_PRESS) {
double dt = glfwGetTime() - glfw.last_button_click;
if (dt > NK_GLFW_DOUBLE_CLICK_LO && dt < NK_GLFW_DOUBLE_CLICK_HI) {
glfw.is_double_click_down = nk_true;
glfw.double_click_pos = nk_vec2((float)x, (float)y);
}
glfw.last_button_click = glfwGetTime();
} else glfw.is_double_click_down = nk_false;
}
NK_INTERN void
nk_glfw3_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
{
const char *text = glfwGetClipboardString(glfw.win);
if (text) nk_textedit_paste(edit, text, nk_strlen(text));
(void)usr;
}
NK_INTERN void
nk_glfw3_clipboard_copy(nk_handle usr, const char *text, int len)
{
char *str = 0;
(void)usr;
if (!len) return;
str = (char*)malloc((size_t)len+1);
if (!str) return;
NK_MEMCPY(str, text, (size_t)len);
str[len] = '\0';
glfwSetClipboardString(glfw.win, str);
free(str);
}
NK_API struct nk_context*
nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state)
{
glfw.win = win;
if (init_state == NK_GLFW3_INSTALL_CALLBACKS) {
glfwSetScrollCallback(win, nk_gflw3_scroll_callback);
glfwSetCharCallback(win, nk_glfw3_char_callback);
glfwSetMouseButtonCallback(win, nk_glfw3_mouse_button_callback);
}
nk_init_default(&glfw.ctx, 0);
glfw.ctx.clip.copy = nk_glfw3_clipboard_copy;
glfw.ctx.clip.paste = nk_glfw3_clipboard_paste;
glfw.ctx.clip.userdata = nk_handle_ptr(0);
nk_buffer_init_default(&glfw.ogl.cmds);
glfw.is_double_click_down = nk_false;
glfw.double_click_pos = nk_vec2(0, 0);
return &glfw.ctx;
}
NK_API void
nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas)
{
nk_font_atlas_init_default(&glfw.atlas);
nk_font_atlas_begin(&glfw.atlas);
*atlas = &glfw.atlas;
}
NK_API void
nk_glfw3_font_stash_end(void)
{
const void *image; int w, h;
image = nk_font_atlas_bake(&glfw.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
nk_glfw3_device_upload_atlas(image, w, h);
nk_font_atlas_end(&glfw.atlas, nk_handle_id((int)glfw.ogl.font_tex), &glfw.ogl.null);
if (glfw.atlas.default_font)
nk_style_set_font(&glfw.ctx, &glfw.atlas.default_font->handle);
}
NK_API void
nk_glfw3_new_frame(void)
{
int i;
double x, y;
struct nk_context *ctx = &glfw.ctx;
struct GLFWwindow *win = glfw.win;
glfwGetWindowSize(win, &glfw.width, &glfw.height);
glfwGetFramebufferSize(win, &glfw.display_width, &glfw.display_height);
glfw.fb_scale.x = (float)glfw.display_width/(float)glfw.width;
glfw.fb_scale.y = (float)glfw.display_height/(float)glfw.height;
nk_input_begin(ctx);
for (i = 0; i < glfw.text_len; ++i)
nk_input_unicode(ctx, glfw.text[i]);
/* optional grabbing behavior */
if (ctx->input.mouse.grab)
glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
else if (ctx->input.mouse.ungrab)
glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
nk_input_key(ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SCROLL_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SCROLL_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SCROLL_DOWN, glfwGetKey(win, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SCROLL_UP, glfwGetKey(win, GLFW_KEY_PAGE_UP) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_SHIFT, glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS||
glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS);
if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) {
nk_input_key(ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_V) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_UNDO, glfwGetKey(win, GLFW_KEY_Z) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_REDO, glfwGetKey(win, GLFW_KEY_R) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_LINE_START, glfwGetKey(win, GLFW_KEY_B) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_TEXT_LINE_END, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS);
} else {
nk_input_key(ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
nk_input_key(ctx, NK_KEY_COPY, 0);
nk_input_key(ctx, NK_KEY_PASTE, 0);
nk_input_key(ctx, NK_KEY_CUT, 0);
nk_input_key(ctx, NK_KEY_SHIFT, 0);
}
glfwGetCursorPos(win, &x, &y);
nk_input_motion(ctx, (int)x, (int)y);
if (ctx->input.mouse.grabbed) {
glfwSetCursorPos(glfw.win, (double)ctx->input.mouse.prev.x, (double)ctx->input.mouse.prev.y);
ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
}
nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
nk_input_button(ctx, NK_BUTTON_DOUBLE, (int)glfw.double_click_pos.x, (int)glfw.double_click_pos.y, glfw.is_double_click_down);
nk_input_scroll(ctx, glfw.scroll);
nk_input_end(&glfw.ctx);
glfw.text_len = 0;
glfw.scroll = nk_vec2(0,0);
}
NK_API
void nk_glfw3_shutdown(void)
{
struct nk_glfw_device *dev = &glfw.ogl;
nk_font_atlas_clear(&glfw.atlas);
nk_free(&glfw.ctx);
glDeleteTextures(1, &dev->font_tex);
nk_buffer_free(&dev->cmds);
NK_MEMSET(&glfw, 0, sizeof(glfw));
}
#endif

1724
deps/stb_image_write.h vendored

File diff suppressed because it is too large Load Diff

594
deps/tinycthread.c vendored
View File

@ -1,594 +0,0 @@
/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; -*-
Copyright (c) 2012 Marcus Geelnard
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
/* 2013-01-06 Camilla Löwy <elmindreda@glfw.org>
*
* Added casts from time_t to DWORD to avoid warnings on VC++.
* Fixed time retrieval on POSIX systems.
*/
#include "tinycthread.h"
#include <stdlib.h>
/* Platform specific includes */
#if defined(_TTHREAD_POSIX_)
#include <signal.h>
#include <sched.h>
#include <unistd.h>
#include <sys/time.h>
#include <errno.h>
#elif defined(_TTHREAD_WIN32_)
#include <process.h>
#include <sys/timeb.h>
#endif
/* Standard, good-to-have defines */
#ifndef NULL
#define NULL (void*)0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
int mtx_init(mtx_t *mtx, int type)
{
#if defined(_TTHREAD_WIN32_)
mtx->mAlreadyLocked = FALSE;
mtx->mRecursive = type & mtx_recursive;
InitializeCriticalSection(&mtx->mHandle);
return thrd_success;
#else
int ret;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
if (type & mtx_recursive)
{
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
}
ret = pthread_mutex_init(mtx, &attr);
pthread_mutexattr_destroy(&attr);
return ret == 0 ? thrd_success : thrd_error;
#endif
}
void mtx_destroy(mtx_t *mtx)
{
#if defined(_TTHREAD_WIN32_)
DeleteCriticalSection(&mtx->mHandle);
#else
pthread_mutex_destroy(mtx);
#endif
}
int mtx_lock(mtx_t *mtx)
{
#if defined(_TTHREAD_WIN32_)
EnterCriticalSection(&mtx->mHandle);
if (!mtx->mRecursive)
{
while(mtx->mAlreadyLocked) Sleep(1000); /* Simulate deadlock... */
mtx->mAlreadyLocked = TRUE;
}
return thrd_success;
#else
return pthread_mutex_lock(mtx) == 0 ? thrd_success : thrd_error;
#endif
}
int mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
{
/* FIXME! */
(void)mtx;
(void)ts;
return thrd_error;
}
int mtx_trylock(mtx_t *mtx)
{
#if defined(_TTHREAD_WIN32_)
int ret = TryEnterCriticalSection(&mtx->mHandle) ? thrd_success : thrd_busy;
if ((!mtx->mRecursive) && (ret == thrd_success) && mtx->mAlreadyLocked)
{
LeaveCriticalSection(&mtx->mHandle);
ret = thrd_busy;
}
return ret;
#else
return (pthread_mutex_trylock(mtx) == 0) ? thrd_success : thrd_busy;
#endif
}
int mtx_unlock(mtx_t *mtx)
{
#if defined(_TTHREAD_WIN32_)
mtx->mAlreadyLocked = FALSE;
LeaveCriticalSection(&mtx->mHandle);
return thrd_success;
#else
return pthread_mutex_unlock(mtx) == 0 ? thrd_success : thrd_error;;
#endif
}
#if defined(_TTHREAD_WIN32_)
#define _CONDITION_EVENT_ONE 0
#define _CONDITION_EVENT_ALL 1
#endif
int cnd_init(cnd_t *cond)
{
#if defined(_TTHREAD_WIN32_)
cond->mWaitersCount = 0;
/* Init critical section */
InitializeCriticalSection(&cond->mWaitersCountLock);
/* Init events */
cond->mEvents[_CONDITION_EVENT_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL);
if (cond->mEvents[_CONDITION_EVENT_ONE] == NULL)
{
cond->mEvents[_CONDITION_EVENT_ALL] = NULL;
return thrd_error;
}
cond->mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL);
if (cond->mEvents[_CONDITION_EVENT_ALL] == NULL)
{
CloseHandle(cond->mEvents[_CONDITION_EVENT_ONE]);
cond->mEvents[_CONDITION_EVENT_ONE] = NULL;
return thrd_error;
}
return thrd_success;
#else
return pthread_cond_init(cond, NULL) == 0 ? thrd_success : thrd_error;
#endif
}
void cnd_destroy(cnd_t *cond)
{
#if defined(_TTHREAD_WIN32_)
if (cond->mEvents[_CONDITION_EVENT_ONE] != NULL)
{
CloseHandle(cond->mEvents[_CONDITION_EVENT_ONE]);
}
if (cond->mEvents[_CONDITION_EVENT_ALL] != NULL)
{
CloseHandle(cond->mEvents[_CONDITION_EVENT_ALL]);
}
DeleteCriticalSection(&cond->mWaitersCountLock);
#else
pthread_cond_destroy(cond);
#endif
}
int cnd_signal(cnd_t *cond)
{
#if defined(_TTHREAD_WIN32_)
int haveWaiters;
/* Are there any waiters? */
EnterCriticalSection(&cond->mWaitersCountLock);
haveWaiters = (cond->mWaitersCount > 0);
LeaveCriticalSection(&cond->mWaitersCountLock);
/* If we have any waiting threads, send them a signal */
if(haveWaiters)
{
if (SetEvent(cond->mEvents[_CONDITION_EVENT_ONE]) == 0)
{
return thrd_error;
}
}
return thrd_success;
#else
return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
#endif
}
int cnd_broadcast(cnd_t *cond)
{
#if defined(_TTHREAD_WIN32_)
int haveWaiters;
/* Are there any waiters? */
EnterCriticalSection(&cond->mWaitersCountLock);
haveWaiters = (cond->mWaitersCount > 0);
LeaveCriticalSection(&cond->mWaitersCountLock);
/* If we have any waiting threads, send them a signal */
if(haveWaiters)
{
if (SetEvent(cond->mEvents[_CONDITION_EVENT_ALL]) == 0)
{
return thrd_error;
}
}
return thrd_success;
#else
return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
#endif
}
#if defined(_TTHREAD_WIN32_)
static int _cnd_timedwait_win32(cnd_t *cond, mtx_t *mtx, DWORD timeout)
{
int result, lastWaiter;
/* Increment number of waiters */
EnterCriticalSection(&cond->mWaitersCountLock);
++ cond->mWaitersCount;
LeaveCriticalSection(&cond->mWaitersCountLock);
/* Release the mutex while waiting for the condition (will decrease
the number of waiters when done)... */
mtx_unlock(mtx);
/* Wait for either event to become signaled due to cnd_signal() or
cnd_broadcast() being called */
result = WaitForMultipleObjects(2, cond->mEvents, FALSE, timeout);
if (result == WAIT_TIMEOUT)
{
return thrd_timeout;
}
else if (result == (int)WAIT_FAILED)
{
return thrd_error;
}
/* Check if we are the last waiter */
EnterCriticalSection(&cond->mWaitersCountLock);
-- cond->mWaitersCount;
lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) &&
(cond->mWaitersCount == 0);
LeaveCriticalSection(&cond->mWaitersCountLock);
/* If we are the last waiter to be notified to stop waiting, reset the event */
if (lastWaiter)
{
if (ResetEvent(cond->mEvents[_CONDITION_EVENT_ALL]) == 0)
{
return thrd_error;
}
}
/* Re-acquire the mutex */
mtx_lock(mtx);
return thrd_success;
}
#endif
int cnd_wait(cnd_t *cond, mtx_t *mtx)
{
#if defined(_TTHREAD_WIN32_)
return _cnd_timedwait_win32(cond, mtx, INFINITE);
#else
return pthread_cond_wait(cond, mtx) == 0 ? thrd_success : thrd_error;
#endif
}
int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
{
#if defined(_TTHREAD_WIN32_)
struct timespec now;
if (clock_gettime(CLOCK_REALTIME, &now) == 0)
{
DWORD delta = (DWORD) ((ts->tv_sec - now.tv_sec) * 1000 +
(ts->tv_nsec - now.tv_nsec + 500000) / 1000000);
return _cnd_timedwait_win32(cond, mtx, delta);
}
else
return thrd_error;
#else
int ret;
ret = pthread_cond_timedwait(cond, mtx, ts);
if (ret == ETIMEDOUT)
{
return thrd_timeout;
}
return ret == 0 ? thrd_success : thrd_error;
#endif
}
/** Information to pass to the new thread (what to run). */
typedef struct {
thrd_start_t mFunction; /**< Pointer to the function to be executed. */
void * mArg; /**< Function argument for the thread function. */
} _thread_start_info;
/* Thread wrapper function. */
#if defined(_TTHREAD_WIN32_)
static unsigned WINAPI _thrd_wrapper_function(void * aArg)
#elif defined(_TTHREAD_POSIX_)
static void * _thrd_wrapper_function(void * aArg)
#endif
{
thrd_start_t fun;
void *arg;
int res;
#if defined(_TTHREAD_POSIX_)
void *pres;
#endif
/* Get thread startup information */
_thread_start_info *ti = (_thread_start_info *) aArg;
fun = ti->mFunction;
arg = ti->mArg;
/* The thread is responsible for freeing the startup information */
free((void *)ti);
/* Call the actual client thread function */
res = fun(arg);
#if defined(_TTHREAD_WIN32_)
return res;
#else
pres = malloc(sizeof(int));
if (pres != NULL)
{
*(int*)pres = res;
}
return pres;
#endif
}
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
{
/* Fill out the thread startup information (passed to the thread wrapper,
which will eventually free it) */
_thread_start_info* ti = (_thread_start_info*)malloc(sizeof(_thread_start_info));
if (ti == NULL)
{
return thrd_nomem;
}
ti->mFunction = func;
ti->mArg = arg;
/* Create the thread */
#if defined(_TTHREAD_WIN32_)
*thr = (HANDLE)_beginthreadex(NULL, 0, _thrd_wrapper_function, (void *)ti, 0, NULL);
#elif defined(_TTHREAD_POSIX_)
if(pthread_create(thr, NULL, _thrd_wrapper_function, (void *)ti) != 0)
{
*thr = 0;
}
#endif
/* Did we fail to create the thread? */
if(!*thr)
{
free(ti);
return thrd_error;
}
return thrd_success;
}
thrd_t thrd_current(void)
{
#if defined(_TTHREAD_WIN32_)
return GetCurrentThread();
#else
return pthread_self();
#endif
}
int thrd_detach(thrd_t thr)
{
/* FIXME! */
(void)thr;
return thrd_error;
}
int thrd_equal(thrd_t thr0, thrd_t thr1)
{
#if defined(_TTHREAD_WIN32_)
return thr0 == thr1;
#else
return pthread_equal(thr0, thr1);
#endif
}
void thrd_exit(int res)
{
#if defined(_TTHREAD_WIN32_)
ExitThread(res);
#else
void *pres = malloc(sizeof(int));
if (pres != NULL)
{
*(int*)pres = res;
}
pthread_exit(pres);
#endif
}
int thrd_join(thrd_t thr, int *res)
{
#if defined(_TTHREAD_WIN32_)
if (WaitForSingleObject(thr, INFINITE) == WAIT_FAILED)
{
return thrd_error;
}
if (res != NULL)
{
DWORD dwRes;
GetExitCodeThread(thr, &dwRes);
*res = dwRes;
}
#elif defined(_TTHREAD_POSIX_)
void *pres;
int ires = 0;
if (pthread_join(thr, &pres) != 0)
{
return thrd_error;
}
if (pres != NULL)
{
ires = *(int*)pres;
free(pres);
}
if (res != NULL)
{
*res = ires;
}
#endif
return thrd_success;
}
int thrd_sleep(const struct timespec *time_point, struct timespec *remaining)
{
struct timespec now;
#if defined(_TTHREAD_WIN32_)
DWORD delta;
#else
long delta;
#endif
/* Get the current time */
if (clock_gettime(CLOCK_REALTIME, &now) != 0)
return -2; // FIXME: Some specific error code?
#if defined(_TTHREAD_WIN32_)
/* Delta in milliseconds */
delta = (DWORD) ((time_point->tv_sec - now.tv_sec) * 1000 +
(time_point->tv_nsec - now.tv_nsec + 500000) / 1000000);
if (delta > 0)
{
Sleep(delta);
}
#else
/* Delta in microseconds */
delta = (time_point->tv_sec - now.tv_sec) * 1000000L +
(time_point->tv_nsec - now.tv_nsec + 500L) / 1000L;
/* On some systems, the usleep argument must be < 1000000 */
while (delta > 999999L)
{
usleep(999999);
delta -= 999999L;
}
if (delta > 0L)
{
usleep((useconds_t)delta);
}
#endif
/* We don't support waking up prematurely (yet) */
if (remaining)
{
remaining->tv_sec = 0;
remaining->tv_nsec = 0;
}
return 0;
}
void thrd_yield(void)
{
#if defined(_TTHREAD_WIN32_)
Sleep(0);
#else
sched_yield();
#endif
}
int tss_create(tss_t *key, tss_dtor_t dtor)
{
#if defined(_TTHREAD_WIN32_)
/* FIXME: The destructor function is not supported yet... */
if (dtor != NULL)
{
return thrd_error;
}
*key = TlsAlloc();
if (*key == TLS_OUT_OF_INDEXES)
{
return thrd_error;
}
#else
if (pthread_key_create(key, dtor) != 0)
{
return thrd_error;
}
#endif
return thrd_success;
}
void tss_delete(tss_t key)
{
#if defined(_TTHREAD_WIN32_)
TlsFree(key);
#else
pthread_key_delete(key);
#endif
}
void *tss_get(tss_t key)
{
#if defined(_TTHREAD_WIN32_)
return TlsGetValue(key);
#else
return pthread_getspecific(key);
#endif
}
int tss_set(tss_t key, void *val)
{
#if defined(_TTHREAD_WIN32_)
if (TlsSetValue(key, val) == 0)
{
return thrd_error;
}
#else
if (pthread_setspecific(key, val) != 0)
{
return thrd_error;
}
#endif
return thrd_success;
}
#if defined(_TTHREAD_EMULATE_CLOCK_GETTIME_)
int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts)
{
#if defined(_TTHREAD_WIN32_)
struct _timeb tb;
_ftime(&tb);
ts->tv_sec = (time_t)tb.time;
ts->tv_nsec = 1000000L * (long)tb.millitm;
#else
struct timeval tv;
gettimeofday(&tv, NULL);
ts->tv_sec = (time_t)tv.tv_sec;
ts->tv_nsec = 1000L * (long)tv.tv_usec;
#endif
return 0;
}
#endif // _TTHREAD_EMULATE_CLOCK_GETTIME_

443
deps/tinycthread.h vendored
View File

@ -1,443 +0,0 @@
/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; -*-
Copyright (c) 2012 Marcus Geelnard
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef _TINYCTHREAD_H_
#define _TINYCTHREAD_H_
/**
* @file
* @mainpage TinyCThread API Reference
*
* @section intro_sec Introduction
* TinyCThread is a minimal, portable implementation of basic threading
* classes for C.
*
* They closely mimic the functionality and naming of the C11 standard, and
* should be easily replaceable with the corresponding standard variants.
*
* @section port_sec Portability
* The Win32 variant uses the native Win32 API for implementing the thread
* classes, while for other systems, the POSIX threads API (pthread) is used.
*
* @section misc_sec Miscellaneous
* The following special keywords are available: #_Thread_local.
*
* For more detailed information, browse the different sections of this
* documentation. A good place to start is:
* tinycthread.h.
*/
/* Which platform are we on? */
#if !defined(_TTHREAD_PLATFORM_DEFINED_)
#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
#define _TTHREAD_WIN32_
#else
#define _TTHREAD_POSIX_
#endif
#define _TTHREAD_PLATFORM_DEFINED_
#endif
/* Activate some POSIX functionality (e.g. clock_gettime and recursive mutexes) */
#if defined(_TTHREAD_POSIX_)
#undef _FEATURES_H
#if !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif
#if !defined(_POSIX_C_SOURCE) || ((_POSIX_C_SOURCE - 0) < 199309L)
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 199309L
#endif
#if !defined(_XOPEN_SOURCE) || ((_XOPEN_SOURCE - 0) < 500)
#undef _XOPEN_SOURCE
#define _XOPEN_SOURCE 500
#endif
#endif
/* Generic includes */
#include <time.h>
/* Platform specific includes */
#if defined(_TTHREAD_POSIX_)
#include <sys/time.h>
#include <pthread.h>
#elif defined(_TTHREAD_WIN32_)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#define __UNDEF_LEAN_AND_MEAN
#endif
#include <windows.h>
#ifdef __UNDEF_LEAN_AND_MEAN
#undef WIN32_LEAN_AND_MEAN
#undef __UNDEF_LEAN_AND_MEAN
#endif
#endif
/* Workaround for missing TIME_UTC: If time.h doesn't provide TIME_UTC,
it's quite likely that libc does not support it either. Hence, fall back to
the only other supported time specifier: CLOCK_REALTIME (and if that fails,
we're probably emulating clock_gettime anyway, so anything goes). */
#ifndef TIME_UTC
#ifdef CLOCK_REALTIME
#define TIME_UTC CLOCK_REALTIME
#else
#define TIME_UTC 0
#endif
#endif
/* Workaround for missing clock_gettime (most Windows compilers, afaik) */
#if defined(_TTHREAD_WIN32_) || defined(__APPLE_CC__)
#define _TTHREAD_EMULATE_CLOCK_GETTIME_
/* Emulate struct timespec */
#if defined(_TTHREAD_WIN32_)
struct _ttherad_timespec {
time_t tv_sec;
long tv_nsec;
};
#define timespec _ttherad_timespec
#endif
/* Emulate clockid_t */
typedef int _tthread_clockid_t;
#define clockid_t _tthread_clockid_t
/* Emulate clock_gettime */
int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts);
#define clock_gettime _tthread_clock_gettime
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 0
#endif
#endif
/** TinyCThread version (major number). */
#define TINYCTHREAD_VERSION_MAJOR 1
/** TinyCThread version (minor number). */
#define TINYCTHREAD_VERSION_MINOR 1
/** TinyCThread version (full version). */
#define TINYCTHREAD_VERSION (TINYCTHREAD_VERSION_MAJOR * 100 + TINYCTHREAD_VERSION_MINOR)
/**
* @def _Thread_local
* Thread local storage keyword.
* A variable that is declared with the @c _Thread_local keyword makes the
* value of the variable local to each thread (known as thread-local storage,
* or TLS). Example usage:
* @code
* // This variable is local to each thread.
* _Thread_local int variable;
* @endcode
* @note The @c _Thread_local keyword is a macro that maps to the corresponding
* compiler directive (e.g. @c __declspec(thread)).
* @note This directive is currently not supported on Mac OS X (it will give
* a compiler error), since compile-time TLS is not supported in the Mac OS X
* executable format. Also, some older versions of MinGW (before GCC 4.x) do
* not support this directive.
* @hideinitializer
*/
/* FIXME: Check for a PROPER value of __STDC_VERSION__ to know if we have C11 */
#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) && !defined(_Thread_local)
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
#define _Thread_local __thread
#else
#define _Thread_local __declspec(thread)
#endif
#endif
/* Macros */
#define TSS_DTOR_ITERATIONS 0
/* Function return values */
#define thrd_error 0 /**< The requested operation failed */
#define thrd_success 1 /**< The requested operation succeeded */
#define thrd_timeout 2 /**< The time specified in the call was reached without acquiring the requested resource */
#define thrd_busy 3 /**< The requested operation failed because a tesource requested by a test and return function is already in use */
#define thrd_nomem 4 /**< The requested operation failed because it was unable to allocate memory */
/* Mutex types */
#define mtx_plain 1
#define mtx_timed 2
#define mtx_try 4
#define mtx_recursive 8
/* Mutex */
#if defined(_TTHREAD_WIN32_)
typedef struct {
CRITICAL_SECTION mHandle; /* Critical section handle */
int mAlreadyLocked; /* TRUE if the mutex is already locked */
int mRecursive; /* TRUE if the mutex is recursive */
} mtx_t;
#else
typedef pthread_mutex_t mtx_t;
#endif
/** Create a mutex object.
* @param mtx A mutex object.
* @param type Bit-mask that must have one of the following six values:
* @li @c mtx_plain for a simple non-recursive mutex
* @li @c mtx_timed for a non-recursive mutex that supports timeout
* @li @c mtx_try for a non-recursive mutex that supports test and return
* @li @c mtx_plain | @c mtx_recursive (same as @c mtx_plain, but recursive)
* @li @c mtx_timed | @c mtx_recursive (same as @c mtx_timed, but recursive)
* @li @c mtx_try | @c mtx_recursive (same as @c mtx_try, but recursive)
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
int mtx_init(mtx_t *mtx, int type);
/** Release any resources used by the given mutex.
* @param mtx A mutex object.
*/
void mtx_destroy(mtx_t *mtx);
/** Lock the given mutex.
* Blocks until the given mutex can be locked. If the mutex is non-recursive, and
* the calling thread already has a lock on the mutex, this call will block
* forever.
* @param mtx A mutex object.
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
int mtx_lock(mtx_t *mtx);
/** NOT YET IMPLEMENTED.
*/
int mtx_timedlock(mtx_t *mtx, const struct timespec *ts);
/** Try to lock the given mutex.
* The specified mutex shall support either test and return or timeout. If the
* mutex is already locked, the function returns without blocking.
* @param mtx A mutex object.
* @return @ref thrd_success on success, or @ref thrd_busy if the resource
* requested is already in use, or @ref thrd_error if the request could not be
* honored.
*/
int mtx_trylock(mtx_t *mtx);
/** Unlock the given mutex.
* @param mtx A mutex object.
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
int mtx_unlock(mtx_t *mtx);
/* Condition variable */
#if defined(_TTHREAD_WIN32_)
typedef struct {
HANDLE mEvents[2]; /* Signal and broadcast event HANDLEs. */
unsigned int mWaitersCount; /* Count of the number of waiters. */
CRITICAL_SECTION mWaitersCountLock; /* Serialize access to mWaitersCount. */
} cnd_t;
#else
typedef pthread_cond_t cnd_t;
#endif
/** Create a condition variable object.
* @param cond A condition variable object.
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
int cnd_init(cnd_t *cond);
/** Release any resources used by the given condition variable.
* @param cond A condition variable object.
*/
void cnd_destroy(cnd_t *cond);
/** Signal a condition variable.
* Unblocks one of the threads that are blocked on the given condition variable
* at the time of the call. If no threads are blocked on the condition variable
* at the time of the call, the function does nothing and return success.
* @param cond A condition variable object.
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
int cnd_signal(cnd_t *cond);
/** Broadcast a condition variable.
* Unblocks all of the threads that are blocked on the given condition variable
* at the time of the call. If no threads are blocked on the condition variable
* at the time of the call, the function does nothing and return success.
* @param cond A condition variable object.
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
int cnd_broadcast(cnd_t *cond);
/** Wait for a condition variable to become signaled.
* The function atomically unlocks the given mutex and endeavors to block until
* the given condition variable is signaled by a call to cnd_signal or to
* cnd_broadcast. When the calling thread becomes unblocked it locks the mutex
* before it returns.
* @param cond A condition variable object.
* @param mtx A mutex object.
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
int cnd_wait(cnd_t *cond, mtx_t *mtx);
/** Wait for a condition variable to become signaled.
* The function atomically unlocks the given mutex and endeavors to block until
* the given condition variable is signaled by a call to cnd_signal or to
* cnd_broadcast, or until after the specified time. When the calling thread
* becomes unblocked it locks the mutex before it returns.
* @param cond A condition variable object.
* @param mtx A mutex object.
* @param xt A point in time at which the request will time out (absolute time).
* @return @ref thrd_success upon success, or @ref thrd_timeout if the time
* specified in the call was reached without acquiring the requested resource, or
* @ref thrd_error if the request could not be honored.
*/
int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts);
/* Thread */
#if defined(_TTHREAD_WIN32_)
typedef HANDLE thrd_t;
#else
typedef pthread_t thrd_t;
#endif
/** Thread start function.
* Any thread that is started with the @ref thrd_create() function must be
* started through a function of this type.
* @param arg The thread argument (the @c arg argument of the corresponding
* @ref thrd_create() call).
* @return The thread return value, which can be obtained by another thread
* by using the @ref thrd_join() function.
*/
typedef int (*thrd_start_t)(void *arg);
/** Create a new thread.
* @param thr Identifier of the newly created thread.
* @param func A function pointer to the function that will be executed in
* the new thread.
* @param arg An argument to the thread function.
* @return @ref thrd_success on success, or @ref thrd_nomem if no memory could
* be allocated for the thread requested, or @ref thrd_error if the request
* could not be honored.
* @note A threads identifier may be reused for a different thread once the
* original thread has exited and either been detached or joined to another
* thread.
*/
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
/** Identify the calling thread.
* @return The identifier of the calling thread.
*/
thrd_t thrd_current(void);
/** NOT YET IMPLEMENTED.
*/
int thrd_detach(thrd_t thr);
/** Compare two thread identifiers.
* The function determines if two thread identifiers refer to the same thread.
* @return Zero if the two thread identifiers refer to different threads.
* Otherwise a nonzero value is returned.
*/
int thrd_equal(thrd_t thr0, thrd_t thr1);
/** Terminate execution of the calling thread.
* @param res Result code of the calling thread.
*/
void thrd_exit(int res);
/** Wait for a thread to terminate.
* The function joins the given thread with the current thread by blocking
* until the other thread has terminated.
* @param thr The thread to join with.
* @param res If this pointer is not NULL, the function will store the result
* code of the given thread in the integer pointed to by @c res.
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
int thrd_join(thrd_t thr, int *res);
/** Put the calling thread to sleep.
* Suspend execution of the calling thread.
* @param time_point A point in time at which the thread will resume (absolute time).
* @param remaining If non-NULL, this parameter will hold the remaining time until
* time_point upon return. This will typically be zero, but if
* the thread was woken up by a signal that is not ignored before
* time_point was reached @c remaining will hold a positive
* time.
* @return 0 (zero) on successful sleep, or -1 if an interrupt occurred.
*/
int thrd_sleep(const struct timespec *time_point, struct timespec *remaining);
/** Yield execution to another thread.
* Permit other threads to run, even if the current thread would ordinarily
* continue to run.
*/
void thrd_yield(void);
/* Thread local storage */
#if defined(_TTHREAD_WIN32_)
typedef DWORD tss_t;
#else
typedef pthread_key_t tss_t;
#endif
/** Destructor function for a thread-specific storage.
* @param val The value of the destructed thread-specific storage.
*/
typedef void (*tss_dtor_t)(void *val);
/** Create a thread-specific storage.
* @param key The unique key identifier that will be set if the function is
* successful.
* @param dtor Destructor function. This can be NULL.
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
* @note The destructor function is not supported under Windows. If @c dtor is
* not NULL when calling this function under Windows, the function will fail
* and return @ref thrd_error.
*/
int tss_create(tss_t *key, tss_dtor_t dtor);
/** Delete a thread-specific storage.
* The function releases any resources used by the given thread-specific
* storage.
* @param key The key that shall be deleted.
*/
void tss_delete(tss_t key);
/** Get the value for a thread-specific storage.
* @param key The thread-specific storage identifier.
* @return The value for the current thread held in the given thread-specific
* storage.
*/
void *tss_get(tss_t key);
/** Set the value for a thread-specific storage.
* @param key The thread-specific storage identifier.
* @param val The value of the thread-specific storage to set for the current
* thread.
* @return @ref thrd_success on success, or @ref thrd_error if the request could
* not be honored.
*/
int tss_set(tss_t key, void *val);
#endif /* _TINYTHREAD_H_ */

247
deps/vs2008/stdint.h vendored
View File

@ -1,247 +0,0 @@
// ISO C9x compliant stdint.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
//
// Copyright (c) 2006-2008 Alexander Chemeris
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The name of the author may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef _MSC_STDINT_H_ // [
#define _MSC_STDINT_H_
#if _MSC_VER > 1000
#pragma once
#endif
#include <limits.h>
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
// or compiler give many errors like this:
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
#ifdef __cplusplus
extern "C" {
#endif
# include <wchar.h>
#ifdef __cplusplus
}
#endif
// Define _W64 macros to mark types changing their size, like intptr_t.
#ifndef _W64
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
# define _W64 __w64
# else
# define _W64
# endif
#endif
// 7.18.1 Integer types
// 7.18.1.1 Exact-width integer types
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
// realize that, e.g. char has the same size as __int8
// so we give up on __intX for them.
#if (_MSC_VER < 1300)
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#else
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
#endif
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
// 7.18.1.2 Minimum-width integer types
typedef int8_t int_least8_t;
typedef int16_t int_least16_t;
typedef int32_t int_least32_t;
typedef int64_t int_least64_t;
typedef uint8_t uint_least8_t;
typedef uint16_t uint_least16_t;
typedef uint32_t uint_least32_t;
typedef uint64_t uint_least64_t;
// 7.18.1.3 Fastest minimum-width integer types
typedef int8_t int_fast8_t;
typedef int16_t int_fast16_t;
typedef int32_t int_fast32_t;
typedef int64_t int_fast64_t;
typedef uint8_t uint_fast8_t;
typedef uint16_t uint_fast16_t;
typedef uint32_t uint_fast32_t;
typedef uint64_t uint_fast64_t;
// 7.18.1.4 Integer types capable of holding object pointers
#ifdef _WIN64 // [
typedef signed __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
#else // _WIN64 ][
typedef _W64 signed int intptr_t;
typedef _W64 unsigned int uintptr_t;
#endif // _WIN64 ]
// 7.18.1.5 Greatest-width integer types
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
// 7.18.2 Limits of specified-width integer types
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
// 7.18.2.1 Limits of exact-width integer types
#define INT8_MIN ((int8_t)_I8_MIN)
#define INT8_MAX _I8_MAX
#define INT16_MIN ((int16_t)_I16_MIN)
#define INT16_MAX _I16_MAX
#define INT32_MIN ((int32_t)_I32_MIN)
#define INT32_MAX _I32_MAX
#define INT64_MIN ((int64_t)_I64_MIN)
#define INT64_MAX _I64_MAX
#define UINT8_MAX _UI8_MAX
#define UINT16_MAX _UI16_MAX
#define UINT32_MAX _UI32_MAX
#define UINT64_MAX _UI64_MAX
// 7.18.2.2 Limits of minimum-width integer types
#define INT_LEAST8_MIN INT8_MIN
#define INT_LEAST8_MAX INT8_MAX
#define INT_LEAST16_MIN INT16_MIN
#define INT_LEAST16_MAX INT16_MAX
#define INT_LEAST32_MIN INT32_MIN
#define INT_LEAST32_MAX INT32_MAX
#define INT_LEAST64_MIN INT64_MIN
#define INT_LEAST64_MAX INT64_MAX
#define UINT_LEAST8_MAX UINT8_MAX
#define UINT_LEAST16_MAX UINT16_MAX
#define UINT_LEAST32_MAX UINT32_MAX
#define UINT_LEAST64_MAX UINT64_MAX
// 7.18.2.3 Limits of fastest minimum-width integer types
#define INT_FAST8_MIN INT8_MIN
#define INT_FAST8_MAX INT8_MAX
#define INT_FAST16_MIN INT16_MIN
#define INT_FAST16_MAX INT16_MAX
#define INT_FAST32_MIN INT32_MIN
#define INT_FAST32_MAX INT32_MAX
#define INT_FAST64_MIN INT64_MIN
#define INT_FAST64_MAX INT64_MAX
#define UINT_FAST8_MAX UINT8_MAX
#define UINT_FAST16_MAX UINT16_MAX
#define UINT_FAST32_MAX UINT32_MAX
#define UINT_FAST64_MAX UINT64_MAX
// 7.18.2.4 Limits of integer types capable of holding object pointers
#ifdef _WIN64 // [
# define INTPTR_MIN INT64_MIN
# define INTPTR_MAX INT64_MAX
# define UINTPTR_MAX UINT64_MAX
#else // _WIN64 ][
# define INTPTR_MIN INT32_MIN
# define INTPTR_MAX INT32_MAX
# define UINTPTR_MAX UINT32_MAX
#endif // _WIN64 ]
// 7.18.2.5 Limits of greatest-width integer types
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX
// 7.18.3 Limits of other integer types
#ifdef _WIN64 // [
# define PTRDIFF_MIN _I64_MIN
# define PTRDIFF_MAX _I64_MAX
#else // _WIN64 ][
# define PTRDIFF_MIN _I32_MIN
# define PTRDIFF_MAX _I32_MAX
#endif // _WIN64 ]
#define SIG_ATOMIC_MIN INT_MIN
#define SIG_ATOMIC_MAX INT_MAX
#ifndef SIZE_MAX // [
# ifdef _WIN64 // [
# define SIZE_MAX _UI64_MAX
# else // _WIN64 ][
# define SIZE_MAX _UI32_MAX
# endif // _WIN64 ]
#endif // SIZE_MAX ]
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
#ifndef WCHAR_MIN // [
# define WCHAR_MIN 0
#endif // WCHAR_MIN ]
#ifndef WCHAR_MAX // [
# define WCHAR_MAX _UI16_MAX
#endif // WCHAR_MAX ]
#define WINT_MIN 0
#define WINT_MAX _UI16_MAX
#endif // __STDC_LIMIT_MACROS ]
// 7.18.4 Limits of other integer types
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
// 7.18.4.1 Macros for minimum-width integer constants
#define INT8_C(val) val##i8
#define INT16_C(val) val##i16
#define INT32_C(val) val##i32
#define INT64_C(val) val##i64
#define UINT8_C(val) val##ui8
#define UINT16_C(val) val##ui16
#define UINT32_C(val) val##ui32
#define UINT64_C(val) val##ui64
// 7.18.4.2 Macros for greatest-width integer constants
#define INTMAX_C INT64_C
#define UINTMAX_C UINT64_C
#endif // __STDC_CONSTANT_MACROS ]
#endif // _MSC_STDINT_H_ ]

View File

@ -1,83 +0,0 @@
link_libraries(glfw)
include_directories("${GLFW_SOURCE_DIR}/deps")
if (MATH_LIBRARY)
link_libraries("${MATH_LIBRARY}")
endif()
# Workaround for the MS CRT deprecating parts of the standard library
if (MSVC OR CMAKE_C_SIMULATE_ID STREQUAL "MSVC")
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
if (WIN32)
set(ICON glfw.rc)
elseif (APPLE)
set(ICON glfw.icns)
endif()
set(GLAD_GL "${GLFW_SOURCE_DIR}/deps/glad/gl.h")
set(GLAD_GLES2 "${GLFW_SOURCE_DIR}/deps/glad/gles2.h")
set(GETOPT "${GLFW_SOURCE_DIR}/deps/getopt.h"
"${GLFW_SOURCE_DIR}/deps/getopt.c")
set(TINYCTHREAD "${GLFW_SOURCE_DIR}/deps/tinycthread.h"
"${GLFW_SOURCE_DIR}/deps/tinycthread.c")
add_executable(boing WIN32 MACOSX_BUNDLE boing.c ${ICON} ${GLAD_GL})
add_executable(gears WIN32 MACOSX_BUNDLE gears.c ${ICON} ${GLAD_GL})
add_executable(heightmap WIN32 MACOSX_BUNDLE heightmap.c ${ICON} ${GLAD_GL})
add_executable(offscreen offscreen.c ${ICON} ${GLAD_GL})
add_executable(particles WIN32 MACOSX_BUNDLE particles.c ${ICON} ${TINYCTHREAD} ${GETOPT} ${GLAD_GL})
add_executable(sharing WIN32 MACOSX_BUNDLE sharing.c ${ICON} ${GLAD_GL})
add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c ${ICON} ${GLAD_GL})
add_executable(triangle-opengl WIN32 MACOSX_BUNDLE triangle-opengl.c ${ICON} ${GLAD_GL})
add_executable(triangle-opengles WIN32 MACOSX_BUNDLE triangle-opengles.c ${ICON} ${GLAD_GLES2})
add_executable(wave WIN32 MACOSX_BUNDLE wave.c ${ICON} ${GLAD_GL})
add_executable(windows WIN32 MACOSX_BUNDLE windows.c ${ICON} ${GLAD_GL})
target_link_libraries(particles Threads::Threads)
if (RT_LIBRARY)
target_link_libraries(particles "${RT_LIBRARY}")
endif()
set(GUI_ONLY_BINARIES boing gears heightmap particles sharing splitview
triangle-opengl triangle-opengles wave windows)
set(CONSOLE_BINARIES offscreen)
set_target_properties(${GUI_ONLY_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
C_STANDARD 99
FOLDER "GLFW3/Examples")
if (MSVC)
# Tell MSVC to use main instead of WinMain
set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES
LINK_FLAGS "/ENTRY:mainCRTStartup")
elseif (CMAKE_C_SIMULATE_ID STREQUAL "MSVC")
# Tell Clang using MS CRT to use main instead of WinMain
set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES
LINK_FLAGS "-Wl,/entry:mainCRTStartup")
endif()
if (APPLE)
set_target_properties(boing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Boing")
set_target_properties(gears PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gears")
set_target_properties(heightmap PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Heightmap")
set_target_properties(particles PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Particles")
set_target_properties(sharing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Sharing")
set_target_properties(triangle-opengl PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "OpenGL Triangle")
set_target_properties(triangle-opengles PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "OpenGL ES Triangle")
set_target_properties(splitview PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "SplitView")
set_target_properties(wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave")
set_target_properties(windows PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Windows")
set_source_files_properties(glfw.icns PROPERTIES
MACOSX_PACKAGE_LOCATION "Resources")
set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}
MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION}
MACOSX_BUNDLE_ICON_FILE glfw.icns
MACOSX_BUNDLE_INFO_PLIST "${GLFW_SOURCE_DIR}/CMake/Info.plist.in")
endif()

View File

@ -1,680 +0,0 @@
/*****************************************************************************
* Title: GLBoing
* Desc: Tribute to Amiga Boing.
* Author: Jim Brooks <gfx@jimbrooks.org>
* Original Amiga authors were R.J. Mical and Dale Luck.
* GLFW conversion by Marcus Geelnard
* Notes: - 360' = 2*PI [radian]
*
* - Distances between objects are created by doing a relative
* Z translations.
*
* - Although OpenGL enticingly supports alpha-blending,
* the shadow of the original Boing didn't affect the color
* of the grid.
*
* - [Marcus] Changed timing scheme from interval driven to frame-
* time based animation steps (which results in much smoother
* movement)
*
* History of Amiga Boing:
*
* Boing was demonstrated on the prototype Amiga (codenamed "Lorraine") in
* 1985. According to legend, it was written ad-hoc in one night by
* R. J. Mical and Dale Luck. Because the bouncing ball animation was so fast
* and smooth, attendees did not believe the Amiga prototype was really doing
* the rendering. Suspecting a trick, they began looking around the booth for
* a hidden computer or VCR.
*****************************************************************************/
#if defined(_MSC_VER)
// Make MS math.h define M_PI
#define _USE_MATH_DEFINES
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <linmath.h>
/*****************************************************************************
* Various declarations and macros
*****************************************************************************/
/* Prototypes */
void init( void );
void display( void );
void reshape( GLFWwindow* window, int w, int h );
void key_callback( GLFWwindow* window, int key, int scancode, int action, int mods );
void mouse_button_callback( GLFWwindow* window, int button, int action, int mods );
void cursor_position_callback( GLFWwindow* window, double x, double y );
void DrawBoingBall( void );
void BounceBall( double dt );
void DrawBoingBallBand( GLfloat long_lo, GLfloat long_hi );
void DrawGrid( void );
#define RADIUS 70.f
#define STEP_LONGITUDE 22.5f /* 22.5 makes 8 bands like original Boing */
#define STEP_LATITUDE 22.5f
#define DIST_BALL (RADIUS * 2.f + RADIUS * 0.1f)
#define VIEW_SCENE_DIST (DIST_BALL * 3.f + 200.f)/* distance from viewer to middle of boing area */
#define GRID_SIZE (RADIUS * 4.5f) /* length (width) of grid */
#define BOUNCE_HEIGHT (RADIUS * 2.1f)
#define BOUNCE_WIDTH (RADIUS * 2.1f)
#define SHADOW_OFFSET_X -20.f
#define SHADOW_OFFSET_Y 10.f
#define SHADOW_OFFSET_Z 0.f
#define WALL_L_OFFSET 0.f
#define WALL_R_OFFSET 5.f
/* Animation speed (50.0 mimics the original GLUT demo speed) */
#define ANIMATION_SPEED 50.f
/* Maximum allowed delta time per physics iteration */
#define MAX_DELTA_T 0.02f
/* Draw ball, or its shadow */
typedef enum { DRAW_BALL, DRAW_BALL_SHADOW } DRAW_BALL_ENUM;
/* Vertex type */
typedef struct {float x; float y; float z;} vertex_t;
/* Global vars */
int windowed_xpos, windowed_ypos, windowed_width, windowed_height;
int width, height;
GLfloat deg_rot_y = 0.f;
GLfloat deg_rot_y_inc = 2.f;
int override_pos = GLFW_FALSE;
GLfloat cursor_x = 0.f;
GLfloat cursor_y = 0.f;
GLfloat ball_x = -RADIUS;
GLfloat ball_y = -RADIUS;
GLfloat ball_x_inc = 1.f;
GLfloat ball_y_inc = 2.f;
DRAW_BALL_ENUM drawBallHow;
double t;
double t_old = 0.f;
double dt;
/* Random number generator */
#ifndef RAND_MAX
#define RAND_MAX 4095
#endif
/*****************************************************************************
* Truncate a degree.
*****************************************************************************/
GLfloat TruncateDeg( GLfloat deg )
{
if ( deg >= 360.f )
return (deg - 360.f);
else
return deg;
}
/*****************************************************************************
* Convert a degree (360-based) into a radian.
* 360' = 2 * PI
*****************************************************************************/
double deg2rad( double deg )
{
return deg / 360 * (2 * M_PI);
}
/*****************************************************************************
* 360' sin().
*****************************************************************************/
double sin_deg( double deg )
{
return sin( deg2rad( deg ) );
}
/*****************************************************************************
* 360' cos().
*****************************************************************************/
double cos_deg( double deg )
{
return cos( deg2rad( deg ) );
}
/*****************************************************************************
* Compute a cross product (for a normal vector).
*
* c = a x b
*****************************************************************************/
void CrossProduct( vertex_t a, vertex_t b, vertex_t c, vertex_t *n )
{
GLfloat u1, u2, u3;
GLfloat v1, v2, v3;
u1 = b.x - a.x;
u2 = b.y - a.y;
u3 = b.y - a.z;
v1 = c.x - a.x;
v2 = c.y - a.y;
v3 = c.z - a.z;
n->x = u2 * v3 - v2 * u3;
n->y = u3 * v1 - v3 * u1;
n->z = u1 * v2 - v1 * u2;
}
#define BOING_DEBUG 0
/*****************************************************************************
* init()
*****************************************************************************/
void init( void )
{
/*
* Clear background.
*/
glClearColor( 0.55f, 0.55f, 0.55f, 0.f );
glShadeModel( GL_FLAT );
}
/*****************************************************************************
* display()
*****************************************************************************/
void display(void)
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glPushMatrix();
drawBallHow = DRAW_BALL_SHADOW;
DrawBoingBall();
DrawGrid();
drawBallHow = DRAW_BALL;
DrawBoingBall();
glPopMatrix();
glFlush();
}
/*****************************************************************************
* reshape()
*****************************************************************************/
void reshape( GLFWwindow* window, int w, int h )
{
mat4x4 projection, view;
glViewport( 0, 0, (GLsizei)w, (GLsizei)h );
glMatrixMode( GL_PROJECTION );
mat4x4_perspective( projection,
2.f * (float) atan2( RADIUS, 200.f ),
(float)w / (float)h,
1.f, VIEW_SCENE_DIST );
glLoadMatrixf((const GLfloat*) projection);
glMatrixMode( GL_MODELVIEW );
{
vec3 eye = { 0.f, 0.f, VIEW_SCENE_DIST };
vec3 center = { 0.f, 0.f, 0.f };
vec3 up = { 0.f, -1.f, 0.f };
mat4x4_look_at( view, eye, center, up );
}
glLoadMatrixf((const GLfloat*) view);
}
void key_callback( GLFWwindow* window, int key, int scancode, int action, int mods )
{
if (action != GLFW_PRESS)
return;
if (key == GLFW_KEY_ESCAPE && mods == 0)
glfwSetWindowShouldClose(window, GLFW_TRUE);
if ((key == GLFW_KEY_ENTER && mods == GLFW_MOD_ALT) ||
(key == GLFW_KEY_F11 && mods == GLFW_MOD_ALT))
{
if (glfwGetWindowMonitor(window))
{
glfwSetWindowMonitor(window, NULL,
windowed_xpos, windowed_ypos,
windowed_width, windowed_height, 0);
}
else
{
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
if (monitor)
{
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwGetWindowPos(window, &windowed_xpos, &windowed_ypos);
glfwGetWindowSize(window, &windowed_width, &windowed_height);
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
}
}
}
}
static void set_ball_pos ( GLfloat x, GLfloat y )
{
ball_x = (width / 2) - x;
ball_y = y - (height / 2);
}
void mouse_button_callback( GLFWwindow* window, int button, int action, int mods )
{
if (button != GLFW_MOUSE_BUTTON_LEFT)
return;
if (action == GLFW_PRESS)
{
override_pos = GLFW_TRUE;
set_ball_pos(cursor_x, cursor_y);
}
else
{
override_pos = GLFW_FALSE;
}
}
void cursor_position_callback( GLFWwindow* window, double x, double y )
{
cursor_x = (float) x;
cursor_y = (float) y;
if ( override_pos )
set_ball_pos(cursor_x, cursor_y);
}
/*****************************************************************************
* Draw the Boing ball.
*
* The Boing ball is sphere in which each facet is a rectangle.
* Facet colors alternate between red and white.
* The ball is built by stacking latitudinal circles. Each circle is composed
* of a widely-separated set of points, so that each facet is noticeably large.
*****************************************************************************/
void DrawBoingBall( void )
{
GLfloat lon_deg; /* degree of longitude */
double dt_total, dt2;
glPushMatrix();
glMatrixMode( GL_MODELVIEW );
/*
* Another relative Z translation to separate objects.
*/
glTranslatef( 0.0, 0.0, DIST_BALL );
/* Update ball position and rotation (iterate if necessary) */
dt_total = dt;
while( dt_total > 0.0 )
{
dt2 = dt_total > MAX_DELTA_T ? MAX_DELTA_T : dt_total;
dt_total -= dt2;
BounceBall( dt2 );
deg_rot_y = TruncateDeg( deg_rot_y + deg_rot_y_inc*((float)dt2*ANIMATION_SPEED) );
}
/* Set ball position */
glTranslatef( ball_x, ball_y, 0.0 );
/*
* Offset the shadow.
*/
if ( drawBallHow == DRAW_BALL_SHADOW )
{
glTranslatef( SHADOW_OFFSET_X,
SHADOW_OFFSET_Y,
SHADOW_OFFSET_Z );
}
/*
* Tilt the ball.
*/
glRotatef( -20.0, 0.0, 0.0, 1.0 );
/*
* Continually rotate ball around Y axis.
*/
glRotatef( deg_rot_y, 0.0, 1.0, 0.0 );
/*
* Set OpenGL state for Boing ball.
*/
glCullFace( GL_FRONT );
glEnable( GL_CULL_FACE );
glEnable( GL_NORMALIZE );
/*
* Build a faceted latitude slice of the Boing ball,
* stepping same-sized vertical bands of the sphere.
*/
for ( lon_deg = 0;
lon_deg < 180;
lon_deg += STEP_LONGITUDE )
{
/*
* Draw a latitude circle at this longitude.
*/
DrawBoingBallBand( lon_deg,
lon_deg + STEP_LONGITUDE );
}
glPopMatrix();
return;
}
/*****************************************************************************
* Bounce the ball.
*****************************************************************************/
void BounceBall( double delta_t )
{
GLfloat sign;
GLfloat deg;
if ( override_pos )
return;
/* Bounce on walls */
if ( ball_x > (BOUNCE_WIDTH/2 + WALL_R_OFFSET ) )
{
ball_x_inc = -0.5f - 0.75f * (GLfloat)rand() / (GLfloat)RAND_MAX;
deg_rot_y_inc = -deg_rot_y_inc;
}
if ( ball_x < -(BOUNCE_HEIGHT/2 + WALL_L_OFFSET) )
{
ball_x_inc = 0.5f + 0.75f * (GLfloat)rand() / (GLfloat)RAND_MAX;
deg_rot_y_inc = -deg_rot_y_inc;
}
/* Bounce on floor / roof */
if ( ball_y > BOUNCE_HEIGHT/2 )
{
ball_y_inc = -0.75f - 1.f * (GLfloat)rand() / (GLfloat)RAND_MAX;
}
if ( ball_y < -BOUNCE_HEIGHT/2*0.85 )
{
ball_y_inc = 0.75f + 1.f * (GLfloat)rand() / (GLfloat)RAND_MAX;
}
/* Update ball position */
ball_x += ball_x_inc * ((float)delta_t*ANIMATION_SPEED);
ball_y += ball_y_inc * ((float)delta_t*ANIMATION_SPEED);
/*
* Simulate the effects of gravity on Y movement.
*/
if ( ball_y_inc < 0 ) sign = -1.0; else sign = 1.0;
deg = (ball_y + BOUNCE_HEIGHT/2) * 90 / BOUNCE_HEIGHT;
if ( deg > 80 ) deg = 80;
if ( deg < 10 ) deg = 10;
ball_y_inc = sign * 4.f * (float) sin_deg( deg );
}
/*****************************************************************************
* Draw a faceted latitude band of the Boing ball.
*
* Parms: long_lo, long_hi
* Low and high longitudes of slice, resp.
*****************************************************************************/
void DrawBoingBallBand( GLfloat long_lo,
GLfloat long_hi )
{
vertex_t vert_ne; /* "ne" means south-east, so on */
vertex_t vert_nw;
vertex_t vert_sw;
vertex_t vert_se;
vertex_t vert_norm;
GLfloat lat_deg;
static int colorToggle = 0;
/*
* Iterate through the points of a latitude circle.
* A latitude circle is a 2D set of X,Z points.
*/
for ( lat_deg = 0;
lat_deg <= (360 - STEP_LATITUDE);
lat_deg += STEP_LATITUDE )
{
/*
* Color this polygon with red or white.
*/
if ( colorToggle )
glColor3f( 0.8f, 0.1f, 0.1f );
else
glColor3f( 0.95f, 0.95f, 0.95f );
#if 0
if ( lat_deg >= 180 )
if ( colorToggle )
glColor3f( 0.1f, 0.8f, 0.1f );
else
glColor3f( 0.5f, 0.5f, 0.95f );
#endif
colorToggle = ! colorToggle;
/*
* Change color if drawing shadow.
*/
if ( drawBallHow == DRAW_BALL_SHADOW )
glColor3f( 0.35f, 0.35f, 0.35f );
/*
* Assign each Y.
*/
vert_ne.y = vert_nw.y = (float) cos_deg(long_hi) * RADIUS;
vert_sw.y = vert_se.y = (float) cos_deg(long_lo) * RADIUS;
/*
* Assign each X,Z with sin,cos values scaled by latitude radius indexed by longitude.
* Eg, long=0 and long=180 are at the poles, so zero scale is sin(longitude),
* while long=90 (sin(90)=1) is at equator.
*/
vert_ne.x = (float) cos_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
vert_se.x = (float) cos_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo ));
vert_nw.x = (float) cos_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
vert_sw.x = (float) cos_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo ));
vert_ne.z = (float) sin_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
vert_se.z = (float) sin_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo ));
vert_nw.z = (float) sin_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
vert_sw.z = (float) sin_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo ));
/*
* Draw the facet.
*/
glBegin( GL_POLYGON );
CrossProduct( vert_ne, vert_nw, vert_sw, &vert_norm );
glNormal3f( vert_norm.x, vert_norm.y, vert_norm.z );
glVertex3f( vert_ne.x, vert_ne.y, vert_ne.z );
glVertex3f( vert_nw.x, vert_nw.y, vert_nw.z );
glVertex3f( vert_sw.x, vert_sw.y, vert_sw.z );
glVertex3f( vert_se.x, vert_se.y, vert_se.z );
glEnd();
#if BOING_DEBUG
printf( "----------------------------------------------------------- \n" );
printf( "lat = %f long_lo = %f long_hi = %f \n", lat_deg, long_lo, long_hi );
printf( "vert_ne x = %.8f y = %.8f z = %.8f \n", vert_ne.x, vert_ne.y, vert_ne.z );
printf( "vert_nw x = %.8f y = %.8f z = %.8f \n", vert_nw.x, vert_nw.y, vert_nw.z );
printf( "vert_se x = %.8f y = %.8f z = %.8f \n", vert_se.x, vert_se.y, vert_se.z );
printf( "vert_sw x = %.8f y = %.8f z = %.8f \n", vert_sw.x, vert_sw.y, vert_sw.z );
#endif
}
/*
* Toggle color so that next band will opposite red/white colors than this one.
*/
colorToggle = ! colorToggle;
/*
* This circular band is done.
*/
return;
}
/*****************************************************************************
* Draw the purple grid of lines, behind the Boing ball.
* When the Workbench is dropped to the bottom, Boing shows 12 rows.
*****************************************************************************/
void DrawGrid( void )
{
int row, col;
const int rowTotal = 12; /* must be divisible by 2 */
const int colTotal = rowTotal; /* must be same as rowTotal */
const GLfloat widthLine = 2.0; /* should be divisible by 2 */
const GLfloat sizeCell = GRID_SIZE / rowTotal;
const GLfloat z_offset = -40.0;
GLfloat xl, xr;
GLfloat yt, yb;
glPushMatrix();
glDisable( GL_CULL_FACE );
/*
* Another relative Z translation to separate objects.
*/
glTranslatef( 0.0, 0.0, DIST_BALL );
/*
* Draw vertical lines (as skinny 3D rectangles).
*/
for ( col = 0; col <= colTotal; col++ )
{
/*
* Compute co-ords of line.
*/
xl = -GRID_SIZE / 2 + col * sizeCell;
xr = xl + widthLine;
yt = GRID_SIZE / 2;
yb = -GRID_SIZE / 2 - widthLine;
glBegin( GL_POLYGON );
glColor3f( 0.6f, 0.1f, 0.6f ); /* purple */
glVertex3f( xr, yt, z_offset ); /* NE */
glVertex3f( xl, yt, z_offset ); /* NW */
glVertex3f( xl, yb, z_offset ); /* SW */
glVertex3f( xr, yb, z_offset ); /* SE */
glEnd();
}
/*
* Draw horizontal lines (as skinny 3D rectangles).
*/
for ( row = 0; row <= rowTotal; row++ )
{
/*
* Compute co-ords of line.
*/
yt = GRID_SIZE / 2 - row * sizeCell;
yb = yt - widthLine;
xl = -GRID_SIZE / 2;
xr = GRID_SIZE / 2 + widthLine;
glBegin( GL_POLYGON );
glColor3f( 0.6f, 0.1f, 0.6f ); /* purple */
glVertex3f( xr, yt, z_offset ); /* NE */
glVertex3f( xl, yt, z_offset ); /* NW */
glVertex3f( xl, yb, z_offset ); /* SW */
glVertex3f( xr, yb, z_offset ); /* SE */
glEnd();
}
glPopMatrix();
return;
}
/*======================================================================*
* main()
*======================================================================*/
int main( void )
{
GLFWwindow* window;
/* Init GLFW */
if( !glfwInit() )
exit( EXIT_FAILURE );
window = glfwCreateWindow( 400, 400, "Boing (classic Amiga demo)", NULL, NULL );
if (!window)
{
glfwTerminate();
exit( EXIT_FAILURE );
}
glfwSetWindowAspectRatio(window, 1, 1);
glfwSetFramebufferSizeCallback(window, reshape);
glfwSetKeyCallback(window, key_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwSetCursorPosCallback(window, cursor_position_callback);
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval( 1 );
glfwGetFramebufferSize(window, &width, &height);
reshape(window, width, height);
glfwSetTime( 0.0 );
init();
/* Main loop */
for (;;)
{
/* Timing */
t = glfwGetTime();
dt = t - t_old;
t_old = t;
/* Draw one frame */
display();
/* Swap buffers */
glfwSwapBuffers(window);
glfwPollEvents();
/* Check if we are still running */
if (glfwWindowShouldClose(window))
break;
}
glfwTerminate();
exit( EXIT_SUCCESS );
}

View File

@ -1,361 +0,0 @@
/*
* 3-D gear wheels. This program is in the public domain.
*
* Command line options:
* -info print GL implementation information
* -exit automatically exit after 30 seconds
*
*
* Brian Paul
*
*
* Marcus Geelnard:
* - Conversion to GLFW
* - Time based rendering (frame rate independent)
* - Slightly modified camera that should work better for stereo viewing
*
*
* Camilla Löwy:
* - Removed FPS counter (this is not a benchmark)
* - Added a few comments
* - Enabled vsync
*/
#if defined(_MSC_VER)
// Make MS math.h define M_PI
#define _USE_MATH_DEFINES
#endif
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
/**
Draw a gear wheel. You'll probably want to call this function when
building a display list since we do a lot of trig here.
Input: inner_radius - radius of hole at center
outer_radius - radius at center of teeth
width - width of gear teeth - number of teeth
tooth_depth - depth of tooth
**/
static void
gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
GLint teeth, GLfloat tooth_depth)
{
GLint i;
GLfloat r0, r1, r2;
GLfloat angle, da;
GLfloat u, v, len;
r0 = inner_radius;
r1 = outer_radius - tooth_depth / 2.f;
r2 = outer_radius + tooth_depth / 2.f;
da = 2.f * (float) M_PI / teeth / 4.f;
glShadeModel(GL_FLAT);
glNormal3f(0.f, 0.f, 1.f);
/* draw front face */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++) {
angle = i * 2.f * (float) M_PI / teeth;
glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), width * 0.5f);
glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), width * 0.5f);
if (i < teeth) {
glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), width * 0.5f);
glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), width * 0.5f);
}
}
glEnd();
/* draw front sides of teeth */
glBegin(GL_QUADS);
da = 2.f * (float) M_PI / teeth / 4.f;
for (i = 0; i < teeth; i++) {
angle = i * 2.f * (float) M_PI / teeth;
glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), width * 0.5f);
glVertex3f(r2 * (float) cos(angle + da), r2 * (float) sin(angle + da), width * 0.5f);
glVertex3f(r2 * (float) cos(angle + 2 * da), r2 * (float) sin(angle + 2 * da), width * 0.5f);
glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), width * 0.5f);
}
glEnd();
glNormal3f(0.0, 0.0, -1.0);
/* draw back face */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++) {
angle = i * 2.f * (float) M_PI / teeth;
glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), -width * 0.5f);
glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), -width * 0.5f);
if (i < teeth) {
glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), -width * 0.5f);
glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), -width * 0.5f);
}
}
glEnd();
/* draw back sides of teeth */
glBegin(GL_QUADS);
da = 2.f * (float) M_PI / teeth / 4.f;
for (i = 0; i < teeth; i++) {
angle = i * 2.f * (float) M_PI / teeth;
glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), -width * 0.5f);
glVertex3f(r2 * (float) cos(angle + 2 * da), r2 * (float) sin(angle + 2 * da), -width * 0.5f);
glVertex3f(r2 * (float) cos(angle + da), r2 * (float) sin(angle + da), -width * 0.5f);
glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), -width * 0.5f);
}
glEnd();
/* draw outward faces of teeth */
glBegin(GL_QUAD_STRIP);
for (i = 0; i < teeth; i++) {
angle = i * 2.f * (float) M_PI / teeth;
glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), width * 0.5f);
glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), -width * 0.5f);
u = r2 * (float) cos(angle + da) - r1 * (float) cos(angle);
v = r2 * (float) sin(angle + da) - r1 * (float) sin(angle);
len = (float) sqrt(u * u + v * v);
u /= len;
v /= len;
glNormal3f(v, -u, 0.0);
glVertex3f(r2 * (float) cos(angle + da), r2 * (float) sin(angle + da), width * 0.5f);
glVertex3f(r2 * (float) cos(angle + da), r2 * (float) sin(angle + da), -width * 0.5f);
glNormal3f((float) cos(angle), (float) sin(angle), 0.f);
glVertex3f(r2 * (float) cos(angle + 2 * da), r2 * (float) sin(angle + 2 * da), width * 0.5f);
glVertex3f(r2 * (float) cos(angle + 2 * da), r2 * (float) sin(angle + 2 * da), -width * 0.5f);
u = r1 * (float) cos(angle + 3 * da) - r2 * (float) cos(angle + 2 * da);
v = r1 * (float) sin(angle + 3 * da) - r2 * (float) sin(angle + 2 * da);
glNormal3f(v, -u, 0.f);
glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), width * 0.5f);
glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), -width * 0.5f);
glNormal3f((float) cos(angle), (float) sin(angle), 0.f);
}
glVertex3f(r1 * (float) cos(0), r1 * (float) sin(0), width * 0.5f);
glVertex3f(r1 * (float) cos(0), r1 * (float) sin(0), -width * 0.5f);
glEnd();
glShadeModel(GL_SMOOTH);
/* draw inside radius cylinder */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++) {
angle = i * 2.f * (float) M_PI / teeth;
glNormal3f(-(float) cos(angle), -(float) sin(angle), 0.f);
glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), -width * 0.5f);
glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), width * 0.5f);
}
glEnd();
}
static GLfloat view_rotx = 20.f, view_roty = 30.f, view_rotz = 0.f;
static GLint gear1, gear2, gear3;
static GLfloat angle = 0.f;
/* OpenGL draw function & timing */
static void draw(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(view_rotx, 1.0, 0.0, 0.0);
glRotatef(view_roty, 0.0, 1.0, 0.0);
glRotatef(view_rotz, 0.0, 0.0, 1.0);
glPushMatrix();
glTranslatef(-3.0, -2.0, 0.0);
glRotatef(angle, 0.0, 0.0, 1.0);
glCallList(gear1);
glPopMatrix();
glPushMatrix();
glTranslatef(3.1f, -2.f, 0.f);
glRotatef(-2.f * angle - 9.f, 0.f, 0.f, 1.f);
glCallList(gear2);
glPopMatrix();
glPushMatrix();
glTranslatef(-3.1f, 4.2f, 0.f);
glRotatef(-2.f * angle - 25.f, 0.f, 0.f, 1.f);
glCallList(gear3);
glPopMatrix();
glPopMatrix();
}
/* update animation parameters */
static void animate(void)
{
angle = 100.f * (float) glfwGetTime();
}
/* change view angle, exit upon ESC */
void key( GLFWwindow* window, int k, int s, int action, int mods )
{
if( action != GLFW_PRESS ) return;
switch (k) {
case GLFW_KEY_Z:
if( mods & GLFW_MOD_SHIFT )
view_rotz -= 5.0;
else
view_rotz += 5.0;
break;
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
case GLFW_KEY_UP:
view_rotx += 5.0;
break;
case GLFW_KEY_DOWN:
view_rotx -= 5.0;
break;
case GLFW_KEY_LEFT:
view_roty += 5.0;
break;
case GLFW_KEY_RIGHT:
view_roty -= 5.0;
break;
default:
return;
}
}
/* new window size */
void reshape( GLFWwindow* window, int width, int height )
{
GLfloat h = (GLfloat) height / (GLfloat) width;
GLfloat xmax, znear, zfar;
znear = 5.0f;
zfar = 30.0f;
xmax = znear * 0.5f;
glViewport( 0, 0, (GLint) width, (GLint) height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glFrustum( -xmax, xmax, -xmax*h, xmax*h, znear, zfar );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0.0, 0.0, -20.0 );
}
/* program & OpenGL initialization */
static void init(void)
{
static GLfloat pos[4] = {5.f, 5.f, 10.f, 0.f};
static GLfloat red[4] = {0.8f, 0.1f, 0.f, 1.f};
static GLfloat green[4] = {0.f, 0.8f, 0.2f, 1.f};
static GLfloat blue[4] = {0.2f, 0.2f, 1.f, 1.f};
glLightfv(GL_LIGHT0, GL_POSITION, pos);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
/* make the gears */
gear1 = glGenLists(1);
glNewList(gear1, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
gear(1.f, 4.f, 1.f, 20, 0.7f);
glEndList();
gear2 = glGenLists(1);
glNewList(gear2, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
gear(0.5f, 2.f, 2.f, 10, 0.7f);
glEndList();
gear3 = glGenLists(1);
glNewList(gear3, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
gear(1.3f, 2.f, 0.5f, 10, 0.7f);
glEndList();
glEnable(GL_NORMALIZE);
}
/* program entry */
int main(int argc, char *argv[])
{
GLFWwindow* window;
int width, height;
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
exit( EXIT_FAILURE );
}
glfwWindowHint(GLFW_DEPTH_BITS, 16);
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
window = glfwCreateWindow( 300, 300, "Gears", NULL, NULL );
if (!window)
{
fprintf( stderr, "Failed to open GLFW window\n" );
glfwTerminate();
exit( EXIT_FAILURE );
}
// Set callback functions
glfwSetFramebufferSizeCallback(window, reshape);
glfwSetKeyCallback(window, key);
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval( 1 );
glfwGetFramebufferSize(window, &width, &height);
reshape(window, width, height);
// Parse command-line options
init();
// Main loop
while( !glfwWindowShouldClose(window) )
{
// Draw gears
draw();
// Update animation
animate();
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
}
// Terminate GLFW
glfwTerminate();
// Exit program
exit( EXIT_SUCCESS );
}

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View File

@ -1,3 +0,0 @@
GLFW_ICON ICON "glfw.ico"

View File

@ -1,513 +0,0 @@
//========================================================================
// Heightmap example program using OpenGL 3 core profile
// Copyright (c) 2010 Olivier Delannoy
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <stddef.h>
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
/* Map height updates */
#define MAX_CIRCLE_SIZE (5.0f)
#define MAX_DISPLACEMENT (1.0f)
#define DISPLACEMENT_SIGN_LIMIT (0.3f)
#define MAX_ITER (200)
#define NUM_ITER_AT_A_TIME (1)
/* Map general information */
#define MAP_SIZE (10.0f)
#define MAP_NUM_VERTICES (80)
#define MAP_NUM_TOTAL_VERTICES (MAP_NUM_VERTICES*MAP_NUM_VERTICES)
#define MAP_NUM_LINES (3* (MAP_NUM_VERTICES - 1) * (MAP_NUM_VERTICES - 1) + \
2 * (MAP_NUM_VERTICES - 1))
/**********************************************************************
* Default shader programs
*********************************************************************/
static const char* vertex_shader_text =
"#version 150\n"
"uniform mat4 project;\n"
"uniform mat4 modelview;\n"
"in float x;\n"
"in float y;\n"
"in float z;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = project * modelview * vec4(x, y, z, 1.0);\n"
"}\n";
static const char* fragment_shader_text =
"#version 150\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
" color = vec4(0.2, 1.0, 0.2, 1.0); \n"
"}\n";
/**********************************************************************
* Values for shader uniforms
*********************************************************************/
/* Frustum configuration */
static GLfloat view_angle = 45.0f;
static GLfloat aspect_ratio = 4.0f/3.0f;
static GLfloat z_near = 1.0f;
static GLfloat z_far = 100.f;
/* Projection matrix */
static GLfloat projection_matrix[16] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
/* Model view matrix */
static GLfloat modelview_matrix[16] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
/**********************************************************************
* Heightmap vertex and index data
*********************************************************************/
static GLfloat map_vertices[3][MAP_NUM_TOTAL_VERTICES];
static GLuint map_line_indices[2*MAP_NUM_LINES];
/* Store uniform location for the shaders
* Those values are setup as part of the process of creating
* the shader program. They should not be used before creating
* the program.
*/
static GLuint mesh;
static GLuint mesh_vbo[4];
/**********************************************************************
* OpenGL helper functions
*********************************************************************/
/* Creates a shader object of the specified type using the specified text
*/
static GLuint make_shader(GLenum type, const char* text)
{
GLuint shader;
GLint shader_ok;
GLsizei log_length;
char info_log[8192];
shader = glCreateShader(type);
if (shader != 0)
{
glShaderSource(shader, 1, (const GLchar**)&text, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &shader_ok);
if (shader_ok != GL_TRUE)
{
fprintf(stderr, "ERROR: Failed to compile %s shader\n", (type == GL_FRAGMENT_SHADER) ? "fragment" : "vertex" );
glGetShaderInfoLog(shader, 8192, &log_length,info_log);
fprintf(stderr, "ERROR: \n%s\n\n", info_log);
glDeleteShader(shader);
shader = 0;
}
}
return shader;
}
/* Creates a program object using the specified vertex and fragment text
*/
static GLuint make_shader_program(const char* vs_text, const char* fs_text)
{
GLuint program = 0u;
GLint program_ok;
GLuint vertex_shader = 0u;
GLuint fragment_shader = 0u;
GLsizei log_length;
char info_log[8192];
vertex_shader = make_shader(GL_VERTEX_SHADER, vs_text);
if (vertex_shader != 0u)
{
fragment_shader = make_shader(GL_FRAGMENT_SHADER, fs_text);
if (fragment_shader != 0u)
{
/* make the program that connect the two shader and link it */
program = glCreateProgram();
if (program != 0u)
{
/* attach both shader and link */
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &program_ok);
if (program_ok != GL_TRUE)
{
fprintf(stderr, "ERROR, failed to link shader program\n");
glGetProgramInfoLog(program, 8192, &log_length, info_log);
fprintf(stderr, "ERROR: \n%s\n\n", info_log);
glDeleteProgram(program);
glDeleteShader(fragment_shader);
glDeleteShader(vertex_shader);
program = 0u;
}
}
}
else
{
fprintf(stderr, "ERROR: Unable to load fragment shader\n");
glDeleteShader(vertex_shader);
}
}
else
{
fprintf(stderr, "ERROR: Unable to load vertex shader\n");
}
return program;
}
/**********************************************************************
* Geometry creation functions
*********************************************************************/
/* Generate vertices and indices for the heightmap
*/
static void init_map(void)
{
int i;
int j;
int k;
GLfloat step = MAP_SIZE / (MAP_NUM_VERTICES - 1);
GLfloat x = 0.0f;
GLfloat z = 0.0f;
/* Create a flat grid */
k = 0;
for (i = 0 ; i < MAP_NUM_VERTICES ; ++i)
{
for (j = 0 ; j < MAP_NUM_VERTICES ; ++j)
{
map_vertices[0][k] = x;
map_vertices[1][k] = 0.0f;
map_vertices[2][k] = z;
z += step;
++k;
}
x += step;
z = 0.0f;
}
#if DEBUG_ENABLED
for (i = 0 ; i < MAP_NUM_TOTAL_VERTICES ; ++i)
{
printf ("Vertice %d (%f, %f, %f)\n",
i, map_vertices[0][i], map_vertices[1][i], map_vertices[2][i]);
}
#endif
/* create indices */
/* line fan based on i
* i+1
* | / i + n + 1
* | /
* |/
* i --- i + n
*/
/* close the top of the square */
k = 0;
for (i = 0 ; i < MAP_NUM_VERTICES -1 ; ++i)
{
map_line_indices[k++] = (i + 1) * MAP_NUM_VERTICES -1;
map_line_indices[k++] = (i + 2) * MAP_NUM_VERTICES -1;
}
/* close the right of the square */
for (i = 0 ; i < MAP_NUM_VERTICES -1 ; ++i)
{
map_line_indices[k++] = (MAP_NUM_VERTICES - 1) * MAP_NUM_VERTICES + i;
map_line_indices[k++] = (MAP_NUM_VERTICES - 1) * MAP_NUM_VERTICES + i + 1;
}
for (i = 0 ; i < (MAP_NUM_VERTICES - 1) ; ++i)
{
for (j = 0 ; j < (MAP_NUM_VERTICES - 1) ; ++j)
{
int ref = i * (MAP_NUM_VERTICES) + j;
map_line_indices[k++] = ref;
map_line_indices[k++] = ref + 1;
map_line_indices[k++] = ref;
map_line_indices[k++] = ref + MAP_NUM_VERTICES;
map_line_indices[k++] = ref;
map_line_indices[k++] = ref + MAP_NUM_VERTICES + 1;
}
}
#ifdef DEBUG_ENABLED
for (k = 0 ; k < 2 * MAP_NUM_LINES ; k += 2)
{
int beg, end;
beg = map_line_indices[k];
end = map_line_indices[k+1];
printf ("Line %d: %d -> %d (%f, %f, %f) -> (%f, %f, %f)\n",
k / 2, beg, end,
map_vertices[0][beg], map_vertices[1][beg], map_vertices[2][beg],
map_vertices[0][end], map_vertices[1][end], map_vertices[2][end]);
}
#endif
}
static void generate_heightmap__circle(float* center_x, float* center_y,
float* size, float* displacement)
{
float sign;
/* random value for element in between [0-1.0] */
*center_x = (MAP_SIZE * rand()) / (float) RAND_MAX;
*center_y = (MAP_SIZE * rand()) / (float) RAND_MAX;
*size = (MAX_CIRCLE_SIZE * rand()) / (float) RAND_MAX;
sign = (1.0f * rand()) / (float) RAND_MAX;
sign = (sign < DISPLACEMENT_SIGN_LIMIT) ? -1.0f : 1.0f;
*displacement = (sign * (MAX_DISPLACEMENT * rand())) / (float) RAND_MAX;
}
/* Run the specified number of iterations of the generation process for the
* heightmap
*/
static void update_map(int num_iter)
{
assert(num_iter > 0);
while(num_iter)
{
/* center of the circle */
float center_x;
float center_z;
float circle_size;
float disp;
size_t ii;
generate_heightmap__circle(&center_x, &center_z, &circle_size, &disp);
disp = disp / 2.0f;
for (ii = 0u ; ii < MAP_NUM_TOTAL_VERTICES ; ++ii)
{
GLfloat dx = center_x - map_vertices[0][ii];
GLfloat dz = center_z - map_vertices[2][ii];
GLfloat pd = (2.0f * (float) sqrt((dx * dx) + (dz * dz))) / circle_size;
if (fabs(pd) <= 1.0f)
{
/* tx,tz is within the circle */
GLfloat new_height = disp + (float) (cos(pd*3.14f)*disp);
map_vertices[1][ii] += new_height;
}
}
--num_iter;
}
}
/**********************************************************************
* OpenGL helper functions
*********************************************************************/
/* Create VBO, IBO and VAO objects for the heightmap geometry and bind them to
* the specified program object
*/
static void make_mesh(GLuint program)
{
GLuint attrloc;
glGenVertexArrays(1, &mesh);
glGenBuffers(4, mesh_vbo);
glBindVertexArray(mesh);
/* Prepare the data for drawing through a buffer inidices */
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh_vbo[3]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)* MAP_NUM_LINES * 2, map_line_indices, GL_STATIC_DRAW);
/* Prepare the attributes for rendering */
attrloc = glGetAttribLocation(program, "x");
glBindBuffer(GL_ARRAY_BUFFER, mesh_vbo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * MAP_NUM_TOTAL_VERTICES, &map_vertices[0][0], GL_STATIC_DRAW);
glEnableVertexAttribArray(attrloc);
glVertexAttribPointer(attrloc, 1, GL_FLOAT, GL_FALSE, 0, 0);
attrloc = glGetAttribLocation(program, "z");
glBindBuffer(GL_ARRAY_BUFFER, mesh_vbo[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * MAP_NUM_TOTAL_VERTICES, &map_vertices[2][0], GL_STATIC_DRAW);
glEnableVertexAttribArray(attrloc);
glVertexAttribPointer(attrloc, 1, GL_FLOAT, GL_FALSE, 0, 0);
attrloc = glGetAttribLocation(program, "y");
glBindBuffer(GL_ARRAY_BUFFER, mesh_vbo[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * MAP_NUM_TOTAL_VERTICES, &map_vertices[1][0], GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(attrloc);
glVertexAttribPointer(attrloc, 1, GL_FLOAT, GL_FALSE, 0, 0);
}
/* Update VBO vertices from source data
*/
static void update_mesh(void)
{
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * MAP_NUM_TOTAL_VERTICES, &map_vertices[1][0]);
}
/**********************************************************************
* GLFW callback functions
*********************************************************************/
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
switch(key)
{
case GLFW_KEY_ESCAPE:
/* Exit program on Escape */
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
}
}
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
int main(int argc, char** argv)
{
GLFWwindow* window;
int iter;
double dt;
double last_update_time;
int frame;
float f;
GLint uloc_modelview;
GLint uloc_project;
int width, height;
GLuint shader_program;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
window = glfwCreateWindow(800, 600, "GLFW OpenGL3 Heightmap demo", NULL, NULL);
if (! window )
{
glfwTerminate();
exit(EXIT_FAILURE);
}
/* Register events callback */
glfwSetKeyCallback(window, key_callback);
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
/* Prepare opengl resources for rendering */
shader_program = make_shader_program(vertex_shader_text, fragment_shader_text);
if (shader_program == 0u)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glUseProgram(shader_program);
uloc_project = glGetUniformLocation(shader_program, "project");
uloc_modelview = glGetUniformLocation(shader_program, "modelview");
/* Compute the projection matrix */
f = 1.0f / tanf(view_angle / 2.0f);
projection_matrix[0] = f / aspect_ratio;
projection_matrix[5] = f;
projection_matrix[10] = (z_far + z_near)/ (z_near - z_far);
projection_matrix[11] = -1.0f;
projection_matrix[14] = 2.0f * (z_far * z_near) / (z_near - z_far);
glUniformMatrix4fv(uloc_project, 1, GL_FALSE, projection_matrix);
/* Set the camera position */
modelview_matrix[12] = -5.0f;
modelview_matrix[13] = -5.0f;
modelview_matrix[14] = -20.0f;
glUniformMatrix4fv(uloc_modelview, 1, GL_FALSE, modelview_matrix);
/* Create mesh data */
init_map();
make_mesh(shader_program);
/* Create vao + vbo to store the mesh */
/* Create the vbo to store all the information for the grid and the height */
/* setup the scene ready for rendering */
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
/* main loop */
frame = 0;
iter = 0;
last_update_time = glfwGetTime();
while (!glfwWindowShouldClose(window))
{
++frame;
/* render the next frame */
glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_LINES, 2* MAP_NUM_LINES , GL_UNSIGNED_INT, 0);
/* display and process events through callbacks */
glfwSwapBuffers(window);
glfwPollEvents();
/* Check the frame rate and update the heightmap if needed */
dt = glfwGetTime();
if ((dt - last_update_time) > 0.2)
{
/* generate the next iteration of the heightmap */
if (iter < MAX_ITER)
{
update_map(NUM_ITER_AT_A_TIME);
update_mesh();
iter += NUM_ITER_AT_A_TIME;
}
last_update_time = dt;
frame = 0;
}
}
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,165 +0,0 @@
//========================================================================
// Offscreen rendering example
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include "linmath.h"
#include <stdlib.h>
#include <stdio.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>
static const struct
{
float x, y;
float r, g, b;
} vertices[3] =
{
{ -0.6f, -0.4f, 1.f, 0.f, 0.f },
{ 0.6f, -0.4f, 0.f, 1.f, 0.f },
{ 0.f, 0.6f, 0.f, 0.f, 1.f }
};
static const char* vertex_shader_text =
"#version 110\n"
"uniform mat4 MVP;\n"
"attribute vec3 vCol;\n"
"attribute vec2 vPos;\n"
"varying vec3 color;\n"
"void main()\n"
"{\n"
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
" color = vCol;\n"
"}\n";
static const char* fragment_shader_text =
"#version 110\n"
"varying vec3 color;\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(color, 1.0);\n"
"}\n";
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
int main(void)
{
GLFWwindow* window;
GLuint vertex_buffer, vertex_shader, fragment_shader, program;
GLint mvp_location, vpos_location, vcol_location;
float ratio;
int width, height;
mat4x4 mvp;
char* buffer;
glfwSetErrorCallback(error_callback);
glfwInitHint(GLFW_COCOA_MENUBAR, GLFW_FALSE);
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
// NOTE: OpenGL error checks have been omitted for brevity
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
glCompileShader(vertex_shader);
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
glCompileShader(fragment_shader);
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
mvp_location = glGetUniformLocation(program, "MVP");
vpos_location = glGetAttribLocation(program, "vPos");
vcol_location = glGetAttribLocation(program, "vCol");
glEnableVertexAttribArray(vpos_location);
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
sizeof(vertices[0]), (void*) 0);
glEnableVertexAttribArray(vcol_location);
glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,
sizeof(vertices[0]), (void*) (sizeof(float) * 2));
glfwGetFramebufferSize(window, &width, &height);
ratio = width / (float) height;
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
mat4x4_ortho(mvp, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);
glUseProgram(program);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
glDrawArrays(GL_TRIANGLES, 0, 3);
glFinish();
buffer = calloc(4, width * height);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// Write image Y-flipped because OpenGL
stbi_write_png("offscreen.png",
width, height, 4,
buffer + (width * 4 * (height - 1)),
-width * 4);
free(buffer);
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,235 +0,0 @@
//========================================================================
// Context sharing example
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include "getopt.h"
#include "linmath.h"
static const char* vertex_shader_text =
"#version 110\n"
"uniform mat4 MVP;\n"
"attribute vec2 vPos;\n"
"varying vec2 texcoord;\n"
"void main()\n"
"{\n"
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
" texcoord = vPos;\n"
"}\n";
static const char* fragment_shader_text =
"#version 110\n"
"uniform sampler2D texture;\n"
"uniform vec3 color;\n"
"varying vec2 texcoord;\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(color * texture2D(texture, texcoord).rgb, 1.0);\n"
"}\n";
static const vec2 vertices[4] =
{
{ 0.f, 0.f },
{ 1.f, 0.f },
{ 1.f, 1.f },
{ 0.f, 1.f }
};
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action == GLFW_PRESS && key == GLFW_KEY_ESCAPE)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
int main(int argc, char** argv)
{
GLFWwindow* windows[2];
GLuint texture, program, vertex_buffer;
GLint mvp_location, vpos_location, color_location, texture_location;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
windows[0] = glfwCreateWindow(400, 400, "First", NULL, NULL);
if (!windows[0])
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetKeyCallback(windows[0], key_callback);
glfwMakeContextCurrent(windows[0]);
// Only enable vsync for the first of the windows to be swapped to
// avoid waiting out the interval for each window
glfwSwapInterval(1);
// The contexts are created with the same APIs so the function
// pointers should be re-usable between them
gladLoadGL(glfwGetProcAddress);
// Create the OpenGL objects inside the first context, created above
// All objects will be shared with the second context, created below
{
int x, y;
char pixels[16 * 16];
GLuint vertex_shader, fragment_shader;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
srand((unsigned int) glfwGetTimerValue());
for (y = 0; y < 16; y++)
{
for (x = 0; x < 16; x++)
pixels[y * 16 + x] = rand() % 256;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 16, 16, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
glCompileShader(vertex_shader);
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
glCompileShader(fragment_shader);
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
mvp_location = glGetUniformLocation(program, "MVP");
color_location = glGetUniformLocation(program, "color");
texture_location = glGetUniformLocation(program, "texture");
vpos_location = glGetAttribLocation(program, "vPos");
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
}
glUseProgram(program);
glUniform1i(texture_location, 0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glEnableVertexAttribArray(vpos_location);
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
sizeof(vertices[0]), (void*) 0);
windows[1] = glfwCreateWindow(400, 400, "Second", NULL, windows[0]);
if (!windows[1])
{
glfwTerminate();
exit(EXIT_FAILURE);
}
// Place the second window to the right of the first
{
int xpos, ypos, left, right, width;
glfwGetWindowSize(windows[0], &width, NULL);
glfwGetWindowFrameSize(windows[0], &left, NULL, &right, NULL);
glfwGetWindowPos(windows[0], &xpos, &ypos);
glfwSetWindowPos(windows[1], xpos + width + left + right, ypos);
}
glfwSetKeyCallback(windows[1], key_callback);
glfwMakeContextCurrent(windows[1]);
// While objects are shared, the global context state is not and will
// need to be set up for each context
glUseProgram(program);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glEnableVertexAttribArray(vpos_location);
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
sizeof(vertices[0]), (void*) 0);
while (!glfwWindowShouldClose(windows[0]) &&
!glfwWindowShouldClose(windows[1]))
{
int i;
const vec3 colors[2] =
{
{ 0.8f, 0.4f, 1.f },
{ 0.3f, 0.4f, 1.f }
};
for (i = 0; i < 2; i++)
{
int width, height;
mat4x4 mvp;
glfwGetFramebufferSize(windows[i], &width, &height);
glfwMakeContextCurrent(windows[i]);
glViewport(0, 0, width, height);
mat4x4_ortho(mvp, 0.f, 1.f, 0.f, 1.f, 0.f, 1.f);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
glUniform3fv(color_location, 1, colors[i]);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glfwSwapBuffers(windows[i]);
}
glfwWaitEvents();
}
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,547 +0,0 @@
//========================================================================
// 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. useful for 3D modelling software). This
// demo uses scissors to separate the four different rendering areas from
// each other.
//
// (If the code seems a little bit strange here and there, it may be
// because I am not a friend of orthogonal projections)
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#if defined(_MSC_VER)
// Make MS math.h define M_PI
#define _USE_MATH_DEFINES
#endif
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <linmath.h>
//========================================================================
// Global variables
//========================================================================
// Mouse position
static double xpos = 0, ypos = 0;
// Window size
static int width, height;
// Active view: 0 = none, 1 = upper left, 2 = upper right, 3 = lower left,
// 4 = lower right
static int active_view = 0;
// Rotation around each axis
static int rot_x = 0, rot_y = 0, rot_z = 0;
// Do redraw?
static int do_redraw = 1;
//========================================================================
// Draw a solid torus (use a display list for the model)
//========================================================================
#define TORUS_MAJOR 1.5
#define TORUS_MINOR 0.5
#define TORUS_MAJOR_RES 32
#define TORUS_MINOR_RES 32
static void drawTorus(void)
{
static GLuint torus_list = 0;
int i, j, k;
double s, t, x, y, z, nx, ny, nz, scale, twopi;
if (!torus_list)
{
// Start recording displaylist
torus_list = glGenLists(1);
glNewList(torus_list, GL_COMPILE_AND_EXECUTE);
// Draw torus
twopi = 2.0 * M_PI;
for (i = 0; i < TORUS_MINOR_RES; i++)
{
glBegin(GL_QUAD_STRIP);
for (j = 0; j <= TORUS_MAJOR_RES; j++)
{
for (k = 1; k >= 0; k--)
{
s = (i + k) % TORUS_MINOR_RES + 0.5;
t = j % TORUS_MAJOR_RES;
// Calculate point on surface
x = (TORUS_MAJOR + TORUS_MINOR * cos(s * twopi / TORUS_MINOR_RES)) * cos(t * twopi / TORUS_MAJOR_RES);
y = TORUS_MINOR * sin(s * twopi / TORUS_MINOR_RES);
z = (TORUS_MAJOR + TORUS_MINOR * cos(s * twopi / TORUS_MINOR_RES)) * sin(t * twopi / TORUS_MAJOR_RES);
// Calculate surface normal
nx = x - TORUS_MAJOR * cos(t * twopi / TORUS_MAJOR_RES);
ny = y;
nz = z - TORUS_MAJOR * sin(t * twopi / TORUS_MAJOR_RES);
scale = 1.0 / sqrt(nx*nx + ny*ny + nz*nz);
nx *= scale;
ny *= scale;
nz *= scale;
glNormal3f((float) nx, (float) ny, (float) nz);
glVertex3f((float) x, (float) y, (float) z);
}
}
glEnd();
}
// Stop recording displaylist
glEndList();
}
else
{
// Playback displaylist
glCallList(torus_list);
}
}
//========================================================================
// Draw the scene (a rotating torus)
//========================================================================
static void drawScene(void)
{
const GLfloat model_diffuse[4] = {1.0f, 0.8f, 0.8f, 1.0f};
const GLfloat model_specular[4] = {0.6f, 0.6f, 0.6f, 1.0f};
const GLfloat model_shininess = 20.0f;
glPushMatrix();
// Rotate the object
glRotatef((GLfloat) rot_x * 0.5f, 1.0f, 0.0f, 0.0f);
glRotatef((GLfloat) rot_y * 0.5f, 0.0f, 1.0f, 0.0f);
glRotatef((GLfloat) rot_z * 0.5f, 0.0f, 0.0f, 1.0f);
// Set model color (used for orthogonal views, lighting disabled)
glColor4fv(model_diffuse);
// Set model material (used for perspective view, lighting enabled)
glMaterialfv(GL_FRONT, GL_DIFFUSE, model_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, model_specular);
glMaterialf(GL_FRONT, GL_SHININESS, model_shininess);
// Draw torus
drawTorus();
glPopMatrix();
}
//========================================================================
// Draw a 2D grid (used for orthogonal views)
//========================================================================
static void drawGrid(float scale, int steps)
{
int i;
float x, y;
mat4x4 view;
glPushMatrix();
// Set background to some dark bluish grey
glClearColor(0.05f, 0.05f, 0.2f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Setup modelview matrix (flat XY view)
{
vec3 eye = { 0.f, 0.f, 1.f };
vec3 center = { 0.f, 0.f, 0.f };
vec3 up = { 0.f, 1.f, 0.f };
mat4x4_look_at(view, eye, center, up);
}
glLoadMatrixf((const GLfloat*) view);
// We don't want to update the Z-buffer
glDepthMask(GL_FALSE);
// Set grid color
glColor3f(0.0f, 0.5f, 0.5f);
glBegin(GL_LINES);
// Horizontal lines
x = scale * 0.5f * (float) (steps - 1);
y = -scale * 0.5f * (float) (steps - 1);
for (i = 0; i < steps; i++)
{
glVertex3f(-x, y, 0.0f);
glVertex3f(x, y, 0.0f);
y += scale;
}
// Vertical lines
x = -scale * 0.5f * (float) (steps - 1);
y = scale * 0.5f * (float) (steps - 1);
for (i = 0; i < steps; i++)
{
glVertex3f(x, -y, 0.0f);
glVertex3f(x, y, 0.0f);
x += scale;
}
glEnd();
// Enable Z-buffer writing again
glDepthMask(GL_TRUE);
glPopMatrix();
}
//========================================================================
// Draw all views
//========================================================================
static void drawAllViews(void)
{
const GLfloat light_position[4] = {0.0f, 8.0f, 8.0f, 1.0f};
const GLfloat light_diffuse[4] = {1.0f, 1.0f, 1.0f, 1.0f};
const GLfloat light_specular[4] = {1.0f, 1.0f, 1.0f, 1.0f};
const GLfloat light_ambient[4] = {0.2f, 0.2f, 0.3f, 1.0f};
float aspect;
mat4x4 view, projection;
// Calculate aspect of window
if (height > 0)
aspect = (float) width / (float) height;
else
aspect = 1.f;
// Clear screen
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Enable scissor test
glEnable(GL_SCISSOR_TEST);
// Enable depth test
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
// ** ORTHOGONAL VIEWS **
// For orthogonal views, use wireframe rendering
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// Enable line anti-aliasing
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Setup orthogonal projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-3.0 * aspect, 3.0 * aspect, -3.0, 3.0, 1.0, 50.0);
// Upper left view (TOP VIEW)
glViewport(0, height / 2, width / 2, height / 2);
glScissor(0, height / 2, width / 2, height / 2);
glMatrixMode(GL_MODELVIEW);
{
vec3 eye = { 0.f, 10.f, 1e-3f };
vec3 center = { 0.f, 0.f, 0.f };
vec3 up = { 0.f, 1.f, 0.f };
mat4x4_look_at( view, eye, center, up );
}
glLoadMatrixf((const GLfloat*) view);
drawGrid(0.5, 12);
drawScene();
// Lower left view (FRONT VIEW)
glViewport(0, 0, width / 2, height / 2);
glScissor(0, 0, width / 2, height / 2);
glMatrixMode(GL_MODELVIEW);
{
vec3 eye = { 0.f, 0.f, 10.f };
vec3 center = { 0.f, 0.f, 0.f };
vec3 up = { 0.f, 1.f, 0.f };
mat4x4_look_at( view, eye, center, up );
}
glLoadMatrixf((const GLfloat*) view);
drawGrid(0.5, 12);
drawScene();
// Lower right view (SIDE VIEW)
glViewport(width / 2, 0, width / 2, height / 2);
glScissor(width / 2, 0, width / 2, height / 2);
glMatrixMode(GL_MODELVIEW);
{
vec3 eye = { 10.f, 0.f, 0.f };
vec3 center = { 0.f, 0.f, 0.f };
vec3 up = { 0.f, 1.f, 0.f };
mat4x4_look_at( view, eye, center, up );
}
glLoadMatrixf((const GLfloat*) view);
drawGrid(0.5, 12);
drawScene();
// Disable line anti-aliasing
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
// ** PERSPECTIVE VIEW **
// For perspective view, use solid rendering
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// Enable face culling (faster rendering)
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
// Setup perspective projection matrix
glMatrixMode(GL_PROJECTION);
mat4x4_perspective(projection,
65.f * (float) M_PI / 180.f,
aspect,
1.f, 50.f);
glLoadMatrixf((const GLfloat*) projection);
// Upper right view (PERSPECTIVE VIEW)
glViewport(width / 2, height / 2, width / 2, height / 2);
glScissor(width / 2, height / 2, width / 2, height / 2);
glMatrixMode(GL_MODELVIEW);
{
vec3 eye = { 3.f, 1.5f, 3.f };
vec3 center = { 0.f, 0.f, 0.f };
vec3 up = { 0.f, 1.f, 0.f };
mat4x4_look_at( view, eye, center, up );
}
glLoadMatrixf((const GLfloat*) view);
// Configure and enable light source 1
glLightfv(GL_LIGHT1, GL_POSITION, light_position);
glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHTING);
// Draw scene
drawScene();
// Disable lighting
glDisable(GL_LIGHTING);
// Disable face culling
glDisable(GL_CULL_FACE);
// Disable depth test
glDisable(GL_DEPTH_TEST);
// Disable scissor test
glDisable(GL_SCISSOR_TEST);
// Draw a border around the active view
if (active_view > 0 && active_view != 2)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 2.0, 0.0, 2.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef((GLfloat) ((active_view - 1) & 1), (GLfloat) (1 - (active_view - 1) / 2), 0.0f);
glColor3f(1.0f, 1.0f, 0.6f);
glBegin(GL_LINE_STRIP);
glVertex2i(0, 0);
glVertex2i(1, 0);
glVertex2i(1, 1);
glVertex2i(0, 1);
glVertex2i(0, 0);
glEnd();
}
}
//========================================================================
// Framebuffer size callback function
//========================================================================
static void framebufferSizeFun(GLFWwindow* window, int w, int h)
{
width = w;
height = h > 0 ? h : 1;
do_redraw = 1;
}
//========================================================================
// Window refresh callback function
//========================================================================
static void windowRefreshFun(GLFWwindow* window)
{
drawAllViews();
glfwSwapBuffers(window);
do_redraw = 0;
}
//========================================================================
// Mouse position callback function
//========================================================================
static void cursorPosFun(GLFWwindow* window, double x, double y)
{
int wnd_width, wnd_height, fb_width, fb_height;
double scale;
glfwGetWindowSize(window, &wnd_width, &wnd_height);
glfwGetFramebufferSize(window, &fb_width, &fb_height);
scale = (double) fb_width / (double) wnd_width;
x *= scale;
y *= scale;
// Depending on which view was selected, rotate around different axes
switch (active_view)
{
case 1:
rot_x += (int) (y - ypos);
rot_z += (int) (x - xpos);
do_redraw = 1;
break;
case 3:
rot_x += (int) (y - ypos);
rot_y += (int) (x - xpos);
do_redraw = 1;
break;
case 4:
rot_y += (int) (x - xpos);
rot_z += (int) (y - ypos);
do_redraw = 1;
break;
default:
// Do nothing for perspective view, or if no view is selected
break;
}
// Remember cursor position
xpos = x;
ypos = y;
}
//========================================================================
// Mouse button callback function
//========================================================================
static void mouseButtonFun(GLFWwindow* window, int button, int action, int mods)
{
if ((button == GLFW_MOUSE_BUTTON_LEFT) && action == GLFW_PRESS)
{
// Detect which of the four views was clicked
active_view = 1;
if (xpos >= width / 2)
active_view += 1;
if (ypos >= height / 2)
active_view += 2;
}
else if (button == GLFW_MOUSE_BUTTON_LEFT)
{
// Deselect any previously selected view
active_view = 0;
}
do_redraw = 1;
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
//========================================================================
// main
//========================================================================
int main(void)
{
GLFWwindow* window;
// Initialise GLFW
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_SAMPLES, 4);
// Open OpenGL window
window = glfwCreateWindow(500, 500, "Split view demo", NULL, NULL);
if (!window)
{
fprintf(stderr, "Failed to open GLFW window\n");
glfwTerminate();
exit(EXIT_FAILURE);
}
// Set callback functions
glfwSetFramebufferSizeCallback(window, framebufferSizeFun);
glfwSetWindowRefreshCallback(window, windowRefreshFun);
glfwSetCursorPosCallback(window, cursorPosFun);
glfwSetMouseButtonCallback(window, mouseButtonFun);
glfwSetKeyCallback(window, key_callback);
// Enable vsync
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(1);
if (GLAD_GL_ARB_multisample || GLAD_GL_VERSION_1_3)
glEnable(GL_MULTISAMPLE_ARB);
glfwGetFramebufferSize(window, &width, &height);
framebufferSizeFun(window, width, height);
// Main loop
for (;;)
{
// Only redraw if we need to
if (do_redraw)
windowRefreshFun(window);
// Wait for new events
glfwWaitEvents();
// Check if the window should be closed
if (glfwWindowShouldClose(window))
break;
}
// Close OpenGL window and terminate GLFW
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,171 +0,0 @@
//========================================================================
// OpenGL triangle example
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//! [code]
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include "linmath.h"
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
typedef struct Vertex
{
vec2 pos;
vec3 col;
} Vertex;
static const Vertex vertices[3] =
{
{ { -0.6f, -0.4f }, { 1.f, 0.f, 0.f } },
{ { 0.6f, -0.4f }, { 0.f, 1.f, 0.f } },
{ { 0.f, 0.6f }, { 0.f, 0.f, 1.f } }
};
static const char* vertex_shader_text =
"#version 330\n"
"uniform mat4 MVP;\n"
"in vec3 vCol;\n"
"in vec2 vPos;\n"
"out vec3 color;\n"
"void main()\n"
"{\n"
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
" color = vCol;\n"
"}\n";
static const char* fragment_shader_text =
"#version 330\n"
"in vec3 color;\n"
"out vec4 fragment;\n"
"void main()\n"
"{\n"
" fragment = vec4(color, 1.0);\n"
"}\n";
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
int main(void)
{
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(640, 480, "OpenGL Triangle", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetKeyCallback(window, key_callback);
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(1);
// NOTE: OpenGL error checks have been omitted for brevity
GLuint vertex_buffer;
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
const GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
glCompileShader(vertex_shader);
const GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
glCompileShader(fragment_shader);
const GLuint program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
const GLint mvp_location = glGetUniformLocation(program, "MVP");
const GLint vpos_location = glGetAttribLocation(program, "vPos");
const GLint vcol_location = glGetAttribLocation(program, "vCol");
GLuint vertex_array;
glGenVertexArrays(1, &vertex_array);
glBindVertexArray(vertex_array);
glEnableVertexAttribArray(vpos_location);
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
sizeof(Vertex), (void*) offsetof(Vertex, pos));
glEnableVertexAttribArray(vcol_location);
glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,
sizeof(Vertex), (void*) offsetof(Vertex, col));
while (!glfwWindowShouldClose(window))
{
int width, height;
glfwGetFramebufferSize(window, &width, &height);
const float ratio = width / (float) height;
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
mat4x4 m, p, mvp;
mat4x4_identity(m);
mat4x4_rotate_Z(m, m, (float) glfwGetTime());
mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);
mat4x4_mul(mvp, p, m);
glUseProgram(program);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) &mvp);
glBindVertexArray(vertex_array);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
//! [code]

View File

@ -1,170 +0,0 @@
//========================================================================
// OpenGL ES 2.0 triangle example
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#define GLAD_GLES2_IMPLEMENTATION
#include <glad/gles2.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include "linmath.h"
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
typedef struct Vertex
{
vec2 pos;
vec3 col;
} Vertex;
static const Vertex vertices[3] =
{
{ { -0.6f, -0.4f }, { 1.f, 0.f, 0.f } },
{ { 0.6f, -0.4f }, { 0.f, 1.f, 0.f } },
{ { 0.f, 0.6f }, { 0.f, 0.f, 1.f } }
};
static const char* vertex_shader_text =
"#version 100\n"
"precision mediump float;\n"
"uniform mat4 MVP;\n"
"attribute vec3 vCol;\n"
"attribute vec2 vPos;\n"
"varying vec3 color;\n"
"void main()\n"
"{\n"
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
" color = vCol;\n"
"}\n";
static const char* fragment_shader_text =
"#version 100\n"
"precision mediump float;\n"
"varying vec3 color;\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(color, 1.0);\n"
"}\n";
static void error_callback(int error, const char* description)
{
fprintf(stderr, "GLFW Error: %s\n", description);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
int main(void)
{
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
GLFWwindow* window = glfwCreateWindow(640, 480, "OpenGL ES 2.0 Triangle (EGL)", NULL, NULL);
if (!window)
{
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_NATIVE_CONTEXT_API);
window = glfwCreateWindow(640, 480, "OpenGL ES 2.0 Triangle", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
}
glfwSetKeyCallback(window, key_callback);
glfwMakeContextCurrent(window);
gladLoadGLES2(glfwGetProcAddress);
glfwSwapInterval(1);
GLuint vertex_buffer;
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
const GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
glCompileShader(vertex_shader);
const GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
glCompileShader(fragment_shader);
const GLuint program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
const GLint mvp_location = glGetUniformLocation(program, "MVP");
const GLint vpos_location = glGetAttribLocation(program, "vPos");
const GLint vcol_location = glGetAttribLocation(program, "vCol");
glEnableVertexAttribArray(vpos_location);
glEnableVertexAttribArray(vcol_location);
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
sizeof(Vertex), (void*) offsetof(Vertex, pos));
glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,
sizeof(Vertex), (void*) offsetof(Vertex, col));
while (!glfwWindowShouldClose(window))
{
int width, height;
glfwGetFramebufferSize(window, &width, &height);
const float ratio = width / (float) height;
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
mat4x4 m, p, mvp;
mat4x4_identity(m);
mat4x4_rotate_Z(m, m, (float) glfwGetTime());
mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);
mat4x4_mul(mvp, p, m);
glUseProgram(program);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) &mvp);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,463 +0,0 @@
/*****************************************************************************
* Wave Simulation in OpenGL
* (C) 2002 Jakob Thomsen
* http://home.in.tum.de/~thomsen
* Modified for GLFW by Sylvain Hellegouarch - sh@programmationworld.com
* Modified for variable frame rate by Marcus Geelnard
* 2003-Jan-31: Minor cleanups and speedups / MG
* 2010-10-24: Formatting and cleanup - Camilla Löwy
*****************************************************************************/
#if defined(_MSC_VER)
// Make MS math.h define M_PI
#define _USE_MATH_DEFINES
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <linmath.h>
// Maximum delta T to allow for differential calculations
#define MAX_DELTA_T 0.01
// Animation speed (10.0 looks good)
#define ANIMATION_SPEED 10.0
GLfloat alpha = 210.f, beta = -70.f;
GLfloat zoom = 2.f;
double cursorX;
double cursorY;
struct Vertex
{
GLfloat x, y, z;
GLfloat r, g, b;
};
#define GRIDW 50
#define GRIDH 50
#define VERTEXNUM (GRIDW*GRIDH)
#define QUADW (GRIDW - 1)
#define QUADH (GRIDH - 1)
#define QUADNUM (QUADW*QUADH)
GLuint quad[4 * QUADNUM];
struct Vertex vertex[VERTEXNUM];
/* The grid will look like this:
*
* 3 4 5
* *---*---*
* | | |
* | 0 | 1 |
* | | |
* *---*---*
* 0 1 2
*/
//========================================================================
// Initialize grid geometry
//========================================================================
void init_vertices(void)
{
int x, y, p;
// Place the vertices in a grid
for (y = 0; y < GRIDH; y++)
{
for (x = 0; x < GRIDW; x++)
{
p = y * GRIDW + x;
vertex[p].x = (GLfloat) (x - GRIDW / 2) / (GLfloat) (GRIDW / 2);
vertex[p].y = (GLfloat) (y - GRIDH / 2) / (GLfloat) (GRIDH / 2);
vertex[p].z = 0;
if ((x % 4 < 2) ^ (y % 4 < 2))
vertex[p].r = 0.0;
else
vertex[p].r = 1.0;
vertex[p].g = (GLfloat) y / (GLfloat) GRIDH;
vertex[p].b = 1.f - ((GLfloat) x / (GLfloat) GRIDW + (GLfloat) y / (GLfloat) GRIDH) / 2.f;
}
}
for (y = 0; y < QUADH; y++)
{
for (x = 0; x < QUADW; x++)
{
p = 4 * (y * QUADW + x);
quad[p + 0] = y * GRIDW + x; // Some point
quad[p + 1] = y * GRIDW + x + 1; // Neighbor at the right side
quad[p + 2] = (y + 1) * GRIDW + x + 1; // Upper right neighbor
quad[p + 3] = (y + 1) * GRIDW + x; // Upper neighbor
}
}
}
double dt;
double p[GRIDW][GRIDH];
double vx[GRIDW][GRIDH], vy[GRIDW][GRIDH];
double ax[GRIDW][GRIDH], ay[GRIDW][GRIDH];
//========================================================================
// Initialize grid
//========================================================================
void init_grid(void)
{
int x, y;
double dx, dy, d;
for (y = 0; y < GRIDH; y++)
{
for (x = 0; x < GRIDW; x++)
{
dx = (double) (x - GRIDW / 2);
dy = (double) (y - GRIDH / 2);
d = sqrt(dx * dx + dy * dy);
if (d < 0.1 * (double) (GRIDW / 2))
{
d = d * 10.0;
p[x][y] = -cos(d * (M_PI / (double)(GRIDW * 4))) * 100.0;
}
else
p[x][y] = 0.0;
vx[x][y] = 0.0;
vy[x][y] = 0.0;
}
}
}
//========================================================================
// Draw scene
//========================================================================
void draw_scene(GLFWwindow* window)
{
// Clear the color and depth buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// We don't want to modify the projection matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Move back
glTranslatef(0.0, 0.0, -zoom);
// Rotate the view
glRotatef(beta, 1.0, 0.0, 0.0);
glRotatef(alpha, 0.0, 0.0, 1.0);
glDrawElements(GL_QUADS, 4 * QUADNUM, GL_UNSIGNED_INT, quad);
glfwSwapBuffers(window);
}
//========================================================================
// Initialize Miscellaneous OpenGL state
//========================================================================
void init_opengl(void)
{
// Use Gouraud (smooth) shading
glShadeModel(GL_SMOOTH);
// Switch on the z-buffer
glEnable(GL_DEPTH_TEST);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(struct Vertex), vertex);
glColorPointer(3, GL_FLOAT, sizeof(struct Vertex), &vertex[0].r); // Pointer to the first color
glPointSize(2.0);
// Background color is black
glClearColor(0, 0, 0, 0);
}
//========================================================================
// Modify the height of each vertex according to the pressure
//========================================================================
void adjust_grid(void)
{
int pos;
int x, y;
for (y = 0; y < GRIDH; y++)
{
for (x = 0; x < GRIDW; x++)
{
pos = y * GRIDW + x;
vertex[pos].z = (float) (p[x][y] * (1.0 / 50.0));
}
}
}
//========================================================================
// Calculate wave propagation
//========================================================================
void calc_grid(void)
{
int x, y, x2, y2;
double time_step = dt * ANIMATION_SPEED;
// Compute accelerations
for (x = 0; x < GRIDW; x++)
{
x2 = (x + 1) % GRIDW;
for(y = 0; y < GRIDH; y++)
ax[x][y] = p[x][y] - p[x2][y];
}
for (y = 0; y < GRIDH; y++)
{
y2 = (y + 1) % GRIDH;
for(x = 0; x < GRIDW; x++)
ay[x][y] = p[x][y] - p[x][y2];
}
// Compute speeds
for (x = 0; x < GRIDW; x++)
{
for (y = 0; y < GRIDH; y++)
{
vx[x][y] = vx[x][y] + ax[x][y] * time_step;
vy[x][y] = vy[x][y] + ay[x][y] * time_step;
}
}
// Compute pressure
for (x = 1; x < GRIDW; x++)
{
x2 = x - 1;
for (y = 1; y < GRIDH; y++)
{
y2 = y - 1;
p[x][y] = p[x][y] + (vx[x2][y] - vx[x][y] + vy[x][y2] - vy[x][y]) * time_step;
}
}
}
//========================================================================
// Print errors
//========================================================================
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
//========================================================================
// Handle key strokes
//========================================================================
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action != GLFW_PRESS)
return;
switch (key)
{
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
case GLFW_KEY_SPACE:
init_grid();
break;
case GLFW_KEY_LEFT:
alpha += 5;
break;
case GLFW_KEY_RIGHT:
alpha -= 5;
break;
case GLFW_KEY_UP:
beta -= 5;
break;
case GLFW_KEY_DOWN:
beta += 5;
break;
case GLFW_KEY_PAGE_UP:
zoom -= 0.25f;
if (zoom < 0.f)
zoom = 0.f;
break;
case GLFW_KEY_PAGE_DOWN:
zoom += 0.25f;
break;
default:
break;
}
}
//========================================================================
// Callback function for mouse button events
//========================================================================
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
if (button != GLFW_MOUSE_BUTTON_LEFT)
return;
if (action == GLFW_PRESS)
{
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwGetCursorPos(window, &cursorX, &cursorY);
}
else
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
//========================================================================
// Callback function for cursor motion events
//========================================================================
void cursor_position_callback(GLFWwindow* window, double x, double y)
{
if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
{
alpha += (GLfloat) (x - cursorX) / 10.f;
beta += (GLfloat) (y - cursorY) / 10.f;
cursorX = x;
cursorY = y;
}
}
//========================================================================
// Callback function for scroll events
//========================================================================
void scroll_callback(GLFWwindow* window, double x, double y)
{
zoom += (float) y / 4.f;
if (zoom < 0)
zoom = 0;
}
//========================================================================
// Callback function for framebuffer resize events
//========================================================================
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
float ratio = 1.f;
mat4x4 projection;
if (height > 0)
ratio = (float) width / (float) height;
// Setup viewport
glViewport(0, 0, width, height);
// Change to the projection matrix and set our viewing volume
glMatrixMode(GL_PROJECTION);
mat4x4_perspective(projection,
60.f * (float) M_PI / 180.f,
ratio,
1.f, 1024.f);
glLoadMatrixf((const GLfloat*) projection);
}
//========================================================================
// main
//========================================================================
int main(int argc, char* argv[])
{
GLFWwindow* window;
double t, dt_total, t_old;
int width, height;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
window = glfwCreateWindow(640, 480, "Wave Simulation", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetKeyCallback(window, key_callback);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwSetCursorPosCallback(window, cursor_position_callback);
glfwSetScrollCallback(window, scroll_callback);
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(1);
glfwGetFramebufferSize(window, &width, &height);
framebuffer_size_callback(window, width, height);
// Initialize OpenGL
init_opengl();
// Initialize simulation
init_vertices();
init_grid();
adjust_grid();
// Initialize timer
t_old = glfwGetTime() - 0.01;
while (!glfwWindowShouldClose(window))
{
t = glfwGetTime();
dt_total = t - t_old;
t_old = t;
// Safety - iterate if dt_total is too large
while (dt_total > 0.f)
{
// Select iteration time step
dt = dt_total > MAX_DELTA_T ? MAX_DELTA_T : dt_total;
dt_total -= dt;
// Calculate wave propagation
calc_grid();
}
// Compute height of each vertex
adjust_grid();
// Draw wave grid to OpenGL display
draw_scene(window);
glfwPollEvents();
}
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,106 +0,0 @@
//========================================================================
// Simple multi-window example
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
int xpos, ypos, height;
const char* description;
GLFWwindow* windows[4];
if (!glfwInit())
{
glfwGetError(&description);
printf("Error: %s\n", description);
exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
glfwGetMonitorWorkarea(glfwGetPrimaryMonitor(), &xpos, &ypos, NULL, &height);
for (int i = 0; i < 4; i++)
{
const int size = height / 5;
const struct
{
float r, g, b;
} colors[] =
{
{ 0.95f, 0.32f, 0.11f },
{ 0.50f, 0.80f, 0.16f },
{ 0.f, 0.68f, 0.94f },
{ 0.98f, 0.74f, 0.04f }
};
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])
{
glfwGetError(&description);
printf("Error: %s\n", description);
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetInputMode(windows[i], GLFW_STICKY_KEYS, GLFW_TRUE);
glfwMakeContextCurrent(windows[i]);
gladLoadGL(glfwGetProcAddress);
glClearColor(colors[i].r, colors[i].g, colors[i].b, 1.f);
}
for (;;)
{
for (int i = 0; i < 4; i++)
{
glfwMakeContextCurrent(windows[i]);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(windows[i]);
if (glfwWindowShouldClose(windows[i]) ||
glfwGetKey(windows[i], GLFW_KEY_ESCAPE))
{
glfwTerminate();
exit(EXIT_SUCCESS);
}
}
glfwWaitEvents();
}
}

View File

@ -1,96 +0,0 @@
link_libraries(glfw)
include_directories("${GLFW_SOURCE_DIR}/deps")
if (MATH_LIBRARY)
link_libraries("${MATH_LIBRARY}")
endif()
# Workaround for the MS CRT deprecating parts of the standard library
if (MSVC OR CMAKE_C_SIMULATE_ID STREQUAL "MSVC")
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
set(GLAD_GL "${GLFW_SOURCE_DIR}/deps/glad/gl.h")
set(GLAD_VULKAN "${GLFW_SOURCE_DIR}/deps/glad/vulkan.h")
set(GETOPT "${GLFW_SOURCE_DIR}/deps/getopt.h"
"${GLFW_SOURCE_DIR}/deps/getopt.c")
set(TINYCTHREAD "${GLFW_SOURCE_DIR}/deps/tinycthread.h"
"${GLFW_SOURCE_DIR}/deps/tinycthread.c")
add_executable(allocator allocator.c ${GLAD_GL})
add_executable(clipboard clipboard.c ${GETOPT} ${GLAD_GL})
add_executable(events events.c ${GETOPT} ${GLAD_GL})
add_executable(msaa msaa.c ${GETOPT} ${GLAD_GL})
add_executable(glfwinfo glfwinfo.c ${GETOPT} ${GLAD_GL} ${GLAD_VULKAN})
add_executable(iconify iconify.c ${GETOPT} ${GLAD_GL})
add_executable(monitors monitors.c ${GETOPT} ${GLAD_GL})
add_executable(reopen reopen.c ${GLAD_GL})
add_executable(cursor cursor.c ${GLAD_GL})
add_executable(empty WIN32 MACOSX_BUNDLE empty.c ${TINYCTHREAD} ${GLAD_GL})
add_executable(gamma WIN32 MACOSX_BUNDLE gamma.c ${GLAD_GL})
add_executable(icon WIN32 MACOSX_BUNDLE icon.c ${GLAD_GL})
add_executable(input_text WIN32 MACOSX_BUNDLE input_text.c ${GETOPT} ${GLAD_GL})
add_executable(inputlag WIN32 MACOSX_BUNDLE inputlag.c ${GETOPT} ${GLAD_GL})
add_executable(joysticks WIN32 MACOSX_BUNDLE joysticks.c ${GLAD_GL})
add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c ${GLAD_GL})
add_executable(threads WIN32 MACOSX_BUNDLE threads.c ${TINYCTHREAD} ${GLAD_GL})
add_executable(timeout WIN32 MACOSX_BUNDLE timeout.c ${GLAD_GL})
add_executable(title WIN32 MACOSX_BUNDLE title.c ${GLAD_GL})
add_executable(triangle-vulkan WIN32 triangle-vulkan.c ${GLAD_VULKAN})
add_executable(window WIN32 MACOSX_BUNDLE window.c ${GLAD_GL})
target_link_libraries(empty Threads::Threads)
target_link_libraries(threads Threads::Threads)
if (RT_LIBRARY)
target_link_libraries(empty "${RT_LIBRARY}")
target_link_libraries(threads "${RT_LIBRARY}")
endif()
if (GLFW_BUILD_X11 OR GLFW_BUILD_WAYLAND)
find_package(Fontconfig)
if (FONTCONFIG_FOUND)
target_compile_definitions(input_text PRIVATE FONTCONFIG_ENABLED)
target_link_libraries(input_text fontconfig)
endif()
endif()
set(GUI_ONLY_BINARIES empty gamma icon input_text inputlag joysticks tearing
threads timeout title triangle-vulkan window)
set(CONSOLE_BINARIES allocator clipboard events msaa glfwinfo iconify monitors
reopen cursor)
set_target_properties(${GUI_ONLY_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
C_STANDARD 99
FOLDER "GLFW3/Tests")
if (MSVC)
# Tell MSVC to use main instead of WinMain
set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES
LINK_FLAGS "/ENTRY:mainCRTStartup")
elseif (CMAKE_C_SIMULATE_ID STREQUAL "MSVC")
# Tell Clang using MS CRT to use main instead of WinMain
set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES
LINK_FLAGS "-Wl,/entry:mainCRTStartup")
endif()
if (APPLE)
set_target_properties(empty PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Empty Event")
set_target_properties(gamma PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gamma")
set_target_properties(input_text PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Input Text")
set_target_properties(inputlag PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Input Lag")
set_target_properties(joysticks PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Joysticks")
set_target_properties(tearing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Tearing")
set_target_properties(threads PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Threads")
set_target_properties(timeout PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Timeout")
set_target_properties(title PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Title")
set_target_properties(window PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Window")
set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}
MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION}
MACOSX_BUNDLE_INFO_PLIST "${GLFW_SOURCE_DIR}/CMake/Info.plist.in")
endif()

View File

@ -1,142 +0,0 @@
//========================================================================
// Custom heap allocator test
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define CALL(x) (function_name = #x, x)
static const char* function_name = NULL;
struct allocator_stats
{
size_t total;
size_t current;
size_t maximum;
};
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void* allocate(size_t size, void* user)
{
struct allocator_stats* stats = user;
assert(size > 0);
stats->total += size;
stats->current += size;
if (stats->current > stats->maximum)
stats->maximum = stats->current;
printf("%s: allocate %zu bytes (current %zu maximum %zu total %zu)\n",
function_name, size, stats->current, stats->maximum, stats->total);
size_t* real_block = malloc(size + sizeof(size_t));
assert(real_block != NULL);
*real_block = size;
return real_block + 1;
}
static void deallocate(void* block, void* user)
{
struct allocator_stats* stats = user;
assert(block != NULL);
size_t* real_block = (size_t*) block - 1;
stats->current -= *real_block;
printf("%s: deallocate %zu bytes (current %zu maximum %zu total %zu)\n",
function_name, *real_block, stats->current, stats->maximum, stats->total);
free(real_block);
}
static void* reallocate(void* block, size_t size, void* user)
{
struct allocator_stats* stats = user;
assert(block != NULL);
assert(size > 0);
size_t* real_block = (size_t*) block - 1;
stats->total += size;
stats->current += size - *real_block;
if (stats->current > stats->maximum)
stats->maximum = stats->current;
printf("%s: reallocate %zu bytes to %zu bytes (current %zu maximum %zu total %zu)\n",
function_name, *real_block, size, stats->current, stats->maximum, stats->total);
real_block = realloc(real_block, size + sizeof(size_t));
assert(real_block != NULL);
*real_block = size;
return real_block + 1;
}
int main(void)
{
struct allocator_stats stats = {0};
const GLFWallocator allocator =
{
.allocate = allocate,
.deallocate = deallocate,
.reallocate = reallocate,
.user = &stats
};
glfwSetErrorCallback(error_callback);
glfwInitAllocator(&allocator);
if (!CALL(glfwInit)())
exit(EXIT_FAILURE);
GLFWwindow* window = CALL(glfwCreateWindow)(400, 400, "Custom allocator test", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
CALL(glfwMakeContextCurrent)(window);
gladLoadGL(glfwGetProcAddress);
CALL(glfwSwapInterval)(1);
while (!CALL(glfwWindowShouldClose)(window))
{
glClear(GL_COLOR_BUFFER_BIT);
CALL(glfwSwapBuffers)(window);
CALL(glfwWaitEvents)();
}
CALL(glfwTerminate)();
exit(EXIT_SUCCESS);
}

View File

@ -1,146 +0,0 @@
//========================================================================
// Clipboard test program
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This program is used to test the clipboard functionality.
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include "getopt.h"
#if defined(__APPLE__)
#define MODIFIER GLFW_MOD_SUPER
#else
#define MODIFIER GLFW_MOD_CONTROL
#endif
static void usage(void)
{
printf("Usage: clipboard [-h]\n");
}
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action != GLFW_PRESS)
return;
switch (key)
{
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
case GLFW_KEY_V:
if (mods == MODIFIER)
{
const char* string;
string = glfwGetClipboardString(NULL);
if (string)
printf("Clipboard contains \"%s\"\n", string);
else
printf("Clipboard does not contain a string\n");
}
break;
case GLFW_KEY_C:
if (mods == MODIFIER)
{
const char* string = "Hello GLFW World!";
glfwSetClipboardString(NULL, string);
printf("Setting clipboard to \"%s\"\n", string);
}
break;
}
}
int main(int argc, char** argv)
{
int ch;
GLFWwindow* window;
while ((ch = getopt(argc, argv, "h")) != -1)
{
switch (ch)
{
case 'h':
usage();
exit(EXIT_SUCCESS);
default:
usage();
exit(EXIT_FAILURE);
}
}
glfwSetErrorCallback(error_callback);
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
exit(EXIT_FAILURE);
}
window = glfwCreateWindow(200, 200, "Clipboard Test", NULL, NULL);
if (!window)
{
glfwTerminate();
fprintf(stderr, "Failed to open GLFW window\n");
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(1);
glfwSetKeyCallback(window, key_callback);
glClearColor(0.5f, 0.5f, 0.5f, 0);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,495 +0,0 @@
//========================================================================
// Cursor & input mode tests
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test provides an interface to the cursor image and cursor mode
// parts of the API.
//
// Custom cursor image generation by urraka.
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#if defined(_MSC_VER)
// Make MS math.h define M_PI
#define _USE_MATH_DEFINES
#endif
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "linmath.h"
#define CURSOR_FRAME_COUNT 60
static const char* vertex_shader_text =
"#version 110\n"
"uniform mat4 MVP;\n"
"attribute vec2 vPos;\n"
"void main()\n"
"{\n"
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
"}\n";
static const char* fragment_shader_text =
"#version 110\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(1.0);\n"
"}\n";
static double cursor_x;
static double cursor_y;
static int swap_interval = 1;
static int wait_events = GLFW_TRUE;
static int animate_cursor = GLFW_FALSE;
static int track_cursor = GLFW_FALSE;
static GLFWcursor* standard_cursors[10];
static GLFWcursor* tracking_cursor = NULL;
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static float star(int x, int y, float t)
{
const float c = 64 / 2.f;
const float i = (0.25f * (float) sin(2.f * M_PI * t) + 0.75f);
const float k = 64 * 0.046875f * i;
const float dist = (float) sqrt((x - c) * (x - c) + (y - c) * (y - c));
const float salpha = 1.f - dist / c;
const float xalpha = (float) x == c ? c : k / (float) fabs(x - c);
const float yalpha = (float) y == c ? c : k / (float) fabs(y - c);
return (float) fmax(0.f, fmin(1.f, i * salpha * 0.2f + salpha * xalpha * yalpha));
}
static GLFWcursor* create_cursor_frame(float t)
{
int i = 0, x, y;
unsigned char buffer[64 * 64 * 4];
const GLFWimage image = { 64, 64, buffer };
for (y = 0; y < image.width; y++)
{
for (x = 0; x < image.height; x++)
{
buffer[i++] = 255;
buffer[i++] = 255;
buffer[i++] = 255;
buffer[i++] = (unsigned char) (255 * star(x, y, t));
}
}
return glfwCreateCursor(&image, image.width / 2, image.height / 2);
}
static GLFWcursor* create_tracking_cursor(void)
{
int i = 0, x, y;
unsigned char buffer[32 * 32 * 4];
const GLFWimage image = { 32, 32, buffer };
for (y = 0; y < image.width; y++)
{
for (x = 0; x < image.height; x++)
{
if (x == 7 || y == 7)
{
buffer[i++] = 255;
buffer[i++] = 0;
buffer[i++] = 0;
buffer[i++] = 255;
}
else
{
buffer[i++] = 0;
buffer[i++] = 0;
buffer[i++] = 0;
buffer[i++] = 0;
}
}
}
return glfwCreateCursor(&image, 7, 7);
}
static void cursor_position_callback(GLFWwindow* window, double x, double y)
{
printf("%0.3f: Cursor position: %f %f (%+f %+f)\n",
glfwGetTime(),
x, y, x - cursor_x, y - cursor_y);
cursor_x = x;
cursor_y = y;
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action != GLFW_PRESS)
return;
switch (key)
{
case GLFW_KEY_A:
{
animate_cursor = !animate_cursor;
if (!animate_cursor)
glfwSetCursor(window, NULL);
break;
}
case GLFW_KEY_ESCAPE:
{
const int mode = glfwGetInputMode(window, GLFW_CURSOR);
if (mode != GLFW_CURSOR_DISABLED && mode != GLFW_CURSOR_CAPTURED)
{
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
}
/* FALLTHROUGH */
}
case GLFW_KEY_N:
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
glfwGetCursorPos(window, &cursor_x, &cursor_y);
printf("(( cursor is normal ))\n");
break;
case GLFW_KEY_D:
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
printf("(( cursor is disabled ))\n");
break;
case GLFW_KEY_H:
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
printf("(( cursor is hidden ))\n");
break;
case GLFW_KEY_C:
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_CAPTURED);
printf("(( cursor is captured ))\n");
break;
case GLFW_KEY_R:
if (!glfwRawMouseMotionSupported())
break;
if (glfwGetInputMode(window, GLFW_RAW_MOUSE_MOTION))
{
glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_FALSE);
printf("(( raw input is disabled ))\n");
}
else
{
glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
printf("(( raw input is enabled ))\n");
}
break;
case GLFW_KEY_SPACE:
swap_interval = 1 - swap_interval;
printf("(( swap interval: %i ))\n", swap_interval);
glfwSwapInterval(swap_interval);
break;
case GLFW_KEY_W:
wait_events = !wait_events;
printf("(( %sing for events ))\n", wait_events ? "wait" : "poll");
break;
case GLFW_KEY_T:
track_cursor = !track_cursor;
if (track_cursor)
glfwSetCursor(window, tracking_cursor);
else
glfwSetCursor(window, NULL);
break;
case GLFW_KEY_P:
{
double x, y;
glfwGetCursorPos(window, &x, &y);
printf("Query before set: %f %f (%+f %+f)\n",
x, y, x - cursor_x, y - cursor_y);
cursor_x = x;
cursor_y = y;
glfwSetCursorPos(window, cursor_x, cursor_y);
glfwGetCursorPos(window, &x, &y);
printf("Query after set: %f %f (%+f %+f)\n",
x, y, x - cursor_x, y - cursor_y);
cursor_x = x;
cursor_y = y;
break;
}
case GLFW_KEY_UP:
glfwSetCursorPos(window, 0, 0);
glfwGetCursorPos(window, &cursor_x, &cursor_y);
break;
case GLFW_KEY_DOWN:
{
int width, height;
glfwGetWindowSize(window, &width, &height);
glfwSetCursorPos(window, width - 1, height - 1);
glfwGetCursorPos(window, &cursor_x, &cursor_y);
break;
}
case GLFW_KEY_0:
glfwSetCursor(window, NULL);
break;
case GLFW_KEY_1:
case GLFW_KEY_2:
case GLFW_KEY_3:
case GLFW_KEY_4:
case GLFW_KEY_5:
case GLFW_KEY_6:
case GLFW_KEY_7:
case GLFW_KEY_8:
case GLFW_KEY_9:
{
int index = key - GLFW_KEY_1;
if (mods & GLFW_MOD_SHIFT)
index += 9;
if (index < sizeof(standard_cursors) / sizeof(standard_cursors[0]))
glfwSetCursor(window, standard_cursors[index]);
break;
}
case GLFW_KEY_F11:
case GLFW_KEY_ENTER:
{
static int x, y, width, height;
if (mods != GLFW_MOD_ALT)
return;
if (glfwGetWindowMonitor(window))
glfwSetWindowMonitor(window, NULL, x, y, width, height, 0);
else
{
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwGetWindowPos(window, &x, &y);
glfwGetWindowSize(window, &width, &height);
glfwSetWindowMonitor(window, monitor,
0, 0, mode->width, mode->height,
mode->refreshRate);
}
glfwGetCursorPos(window, &cursor_x, &cursor_y);
break;
}
}
}
int main(void)
{
int i;
GLFWwindow* window;
GLFWcursor* star_cursors[CURSOR_FRAME_COUNT];
GLFWcursor* current_frame = NULL;
GLuint vertex_buffer, vertex_shader, fragment_shader, program;
GLint mvp_location, vpos_location;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
tracking_cursor = create_tracking_cursor();
if (!tracking_cursor)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
for (i = 0; i < CURSOR_FRAME_COUNT; i++)
{
star_cursors[i] = create_cursor_frame(i / (float) CURSOR_FRAME_COUNT);
if (!star_cursors[i])
{
glfwTerminate();
exit(EXIT_FAILURE);
}
}
for (i = 0; i < sizeof(standard_cursors) / sizeof(standard_cursors[0]); i++)
{
const int shapes[] = {
GLFW_ARROW_CURSOR,
GLFW_IBEAM_CURSOR,
GLFW_CROSSHAIR_CURSOR,
GLFW_POINTING_HAND_CURSOR,
GLFW_RESIZE_EW_CURSOR,
GLFW_RESIZE_NS_CURSOR,
GLFW_RESIZE_NWSE_CURSOR,
GLFW_RESIZE_NESW_CURSOR,
GLFW_RESIZE_ALL_CURSOR,
GLFW_NOT_ALLOWED_CURSOR
};
standard_cursors[i] = glfwCreateStandardCursor(shapes[i]);
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(640, 480, "Cursor Test", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
glCompileShader(vertex_shader);
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
glCompileShader(fragment_shader);
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
mvp_location = glGetUniformLocation(program, "MVP");
vpos_location = glGetAttribLocation(program, "vPos");
glEnableVertexAttribArray(vpos_location);
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
sizeof(vec2), (void*) 0);
glUseProgram(program);
glfwGetCursorPos(window, &cursor_x, &cursor_y);
printf("Cursor position: %f %f\n", cursor_x, cursor_y);
glfwSetCursorPosCallback(window, cursor_position_callback);
glfwSetKeyCallback(window, key_callback);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
if (track_cursor)
{
int wnd_width, wnd_height, fb_width, fb_height;
float scale;
vec2 vertices[4];
mat4x4 mvp;
glfwGetWindowSize(window, &wnd_width, &wnd_height);
glfwGetFramebufferSize(window, &fb_width, &fb_height);
glViewport(0, 0, fb_width, fb_height);
scale = (float) fb_width / (float) wnd_width;
vertices[0][0] = 0.5f;
vertices[0][1] = (float) (fb_height - floor(cursor_y * scale) - 1.f + 0.5f);
vertices[1][0] = (float) fb_width + 0.5f;
vertices[1][1] = (float) (fb_height - floor(cursor_y * scale) - 1.f + 0.5f);
vertices[2][0] = (float) floor(cursor_x * scale) + 0.5f;
vertices[2][1] = 0.5f;
vertices[3][0] = (float) floor(cursor_x * scale) + 0.5f;
vertices[3][1] = (float) fb_height + 0.5f;
glBufferData(GL_ARRAY_BUFFER,
sizeof(vertices),
vertices,
GL_STREAM_DRAW);
mat4x4_ortho(mvp, 0.f, (float) fb_width, 0.f, (float) fb_height, 0.f, 1.f);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
glDrawArrays(GL_LINES, 0, 4);
}
glfwSwapBuffers(window);
if (animate_cursor)
{
const int i = (int) (glfwGetTime() * 30.0) % CURSOR_FRAME_COUNT;
if (current_frame != star_cursors[i])
{
glfwSetCursor(window, star_cursors[i]);
current_frame = star_cursors[i];
}
}
else
current_frame = NULL;
if (wait_events)
{
if (animate_cursor)
glfwWaitEventsTimeout(1.0 / 30.0);
else
glfwWaitEvents();
}
else
glfwPollEvents();
// Workaround for an issue with msvcrt and mintty
fflush(stdout);
}
glfwDestroyWindow(window);
for (i = 0; i < CURSOR_FRAME_COUNT; i++)
glfwDestroyCursor(star_cursors[i]);
for (i = 0; i < sizeof(standard_cursors) / sizeof(standard_cursors[0]); i++)
glfwDestroyCursor(standard_cursors[i]);
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,133 +0,0 @@
//========================================================================
// Empty event test
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test is intended to verify that posting of empty events works
//
//========================================================================
#include "tinycthread.h"
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
static volatile int running = GLFW_TRUE;
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static int thread_main(void* data)
{
struct timespec time;
while (running)
{
clock_gettime(CLOCK_REALTIME, &time);
time.tv_sec += 1;
thrd_sleep(&time, NULL);
glfwPostEmptyEvent();
}
return 0;
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
static float nrand(void)
{
return (float) rand() / (float) RAND_MAX;
}
int main(void)
{
int result;
thrd_t thread;
GLFWwindow* window;
srand((unsigned int) time(NULL));
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
window = glfwCreateWindow(640, 480, "Empty Event Test", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSetKeyCallback(window, key_callback);
if (thrd_create(&thread, thread_main, NULL) != thrd_success)
{
fprintf(stderr, "Failed to create secondary thread\n");
glfwTerminate();
exit(EXIT_FAILURE);
}
while (running)
{
int width, height;
float r = nrand(), g = nrand(), b = nrand();
float l = (float) sqrt(r * r + g * g + b * b);
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClearColor(r / l, g / l, b / l, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
if (glfwWindowShouldClose(window))
running = GLFW_FALSE;
}
glfwHideWindow(window);
thrd_join(thread, &result);
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,726 +0,0 @@
//========================================================================
// Event linter (event spewer)
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test hooks every available callback and outputs their arguments
//
// Log messages go to stdout, error messages to stderr
//
// Every event also gets a (sequential) number to aid discussion of logs
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <locale.h>
#include "getopt.h"
// Event index
static unsigned int counter = 0;
typedef struct
{
GLFWwindow* window;
int number;
int closeable;
} Slot;
static void usage(void)
{
printf("Usage: events [-f] [-h] [-n WINDOWS]\n");
printf("Options:\n");
printf(" -f use full screen\n");
printf(" -h show this help\n");
printf(" -n the number of windows to create\n");
}
static const char* get_key_name(int key)
{
switch (key)
{
// Printable keys
case GLFW_KEY_A: return "A";
case GLFW_KEY_B: return "B";
case GLFW_KEY_C: return "C";
case GLFW_KEY_D: return "D";
case GLFW_KEY_E: return "E";
case GLFW_KEY_F: return "F";
case GLFW_KEY_G: return "G";
case GLFW_KEY_H: return "H";
case GLFW_KEY_I: return "I";
case GLFW_KEY_J: return "J";
case GLFW_KEY_K: return "K";
case GLFW_KEY_L: return "L";
case GLFW_KEY_M: return "M";
case GLFW_KEY_N: return "N";
case GLFW_KEY_O: return "O";
case GLFW_KEY_P: return "P";
case GLFW_KEY_Q: return "Q";
case GLFW_KEY_R: return "R";
case GLFW_KEY_S: return "S";
case GLFW_KEY_T: return "T";
case GLFW_KEY_U: return "U";
case GLFW_KEY_V: return "V";
case GLFW_KEY_W: return "W";
case GLFW_KEY_X: return "X";
case GLFW_KEY_Y: return "Y";
case GLFW_KEY_Z: return "Z";
case GLFW_KEY_1: return "1";
case GLFW_KEY_2: return "2";
case GLFW_KEY_3: return "3";
case GLFW_KEY_4: return "4";
case GLFW_KEY_5: return "5";
case GLFW_KEY_6: return "6";
case GLFW_KEY_7: return "7";
case GLFW_KEY_8: return "8";
case GLFW_KEY_9: return "9";
case GLFW_KEY_0: return "0";
case GLFW_KEY_SPACE: return "SPACE";
case GLFW_KEY_MINUS: return "MINUS";
case GLFW_KEY_EQUAL: return "EQUAL";
case GLFW_KEY_LEFT_BRACKET: return "LEFT BRACKET";
case GLFW_KEY_RIGHT_BRACKET: return "RIGHT BRACKET";
case GLFW_KEY_BACKSLASH: return "BACKSLASH";
case GLFW_KEY_SEMICOLON: return "SEMICOLON";
case GLFW_KEY_APOSTROPHE: return "APOSTROPHE";
case GLFW_KEY_GRAVE_ACCENT: return "GRAVE ACCENT";
case GLFW_KEY_COMMA: return "COMMA";
case GLFW_KEY_PERIOD: return "PERIOD";
case GLFW_KEY_SLASH: return "SLASH";
case GLFW_KEY_WORLD_1: return "WORLD 1";
case GLFW_KEY_WORLD_2: return "WORLD 2";
// Function keys
case GLFW_KEY_ESCAPE: return "ESCAPE";
case GLFW_KEY_F1: return "F1";
case GLFW_KEY_F2: return "F2";
case GLFW_KEY_F3: return "F3";
case GLFW_KEY_F4: return "F4";
case GLFW_KEY_F5: return "F5";
case GLFW_KEY_F6: return "F6";
case GLFW_KEY_F7: return "F7";
case GLFW_KEY_F8: return "F8";
case GLFW_KEY_F9: return "F9";
case GLFW_KEY_F10: return "F10";
case GLFW_KEY_F11: return "F11";
case GLFW_KEY_F12: return "F12";
case GLFW_KEY_F13: return "F13";
case GLFW_KEY_F14: return "F14";
case GLFW_KEY_F15: return "F15";
case GLFW_KEY_F16: return "F16";
case GLFW_KEY_F17: return "F17";
case GLFW_KEY_F18: return "F18";
case GLFW_KEY_F19: return "F19";
case GLFW_KEY_F20: return "F20";
case GLFW_KEY_F21: return "F21";
case GLFW_KEY_F22: return "F22";
case GLFW_KEY_F23: return "F23";
case GLFW_KEY_F24: return "F24";
case GLFW_KEY_F25: return "F25";
case GLFW_KEY_UP: return "UP";
case GLFW_KEY_DOWN: return "DOWN";
case GLFW_KEY_LEFT: return "LEFT";
case GLFW_KEY_RIGHT: return "RIGHT";
case GLFW_KEY_LEFT_SHIFT: return "LEFT SHIFT";
case GLFW_KEY_RIGHT_SHIFT: return "RIGHT SHIFT";
case GLFW_KEY_LEFT_CONTROL: return "LEFT CONTROL";
case GLFW_KEY_RIGHT_CONTROL: return "RIGHT CONTROL";
case GLFW_KEY_LEFT_ALT: return "LEFT ALT";
case GLFW_KEY_RIGHT_ALT: return "RIGHT ALT";
case GLFW_KEY_TAB: return "TAB";
case GLFW_KEY_ENTER: return "ENTER";
case GLFW_KEY_BACKSPACE: return "BACKSPACE";
case GLFW_KEY_INSERT: return "INSERT";
case GLFW_KEY_DELETE: return "DELETE";
case GLFW_KEY_PAGE_UP: return "PAGE UP";
case GLFW_KEY_PAGE_DOWN: return "PAGE DOWN";
case GLFW_KEY_HOME: return "HOME";
case GLFW_KEY_END: return "END";
case GLFW_KEY_KP_0: return "KEYPAD 0";
case GLFW_KEY_KP_1: return "KEYPAD 1";
case GLFW_KEY_KP_2: return "KEYPAD 2";
case GLFW_KEY_KP_3: return "KEYPAD 3";
case GLFW_KEY_KP_4: return "KEYPAD 4";
case GLFW_KEY_KP_5: return "KEYPAD 5";
case GLFW_KEY_KP_6: return "KEYPAD 6";
case GLFW_KEY_KP_7: return "KEYPAD 7";
case GLFW_KEY_KP_8: return "KEYPAD 8";
case GLFW_KEY_KP_9: return "KEYPAD 9";
case GLFW_KEY_KP_DIVIDE: return "KEYPAD DIVIDE";
case GLFW_KEY_KP_MULTIPLY: return "KEYPAD MULTIPLY";
case GLFW_KEY_KP_SUBTRACT: return "KEYPAD SUBTRACT";
case GLFW_KEY_KP_ADD: return "KEYPAD ADD";
case GLFW_KEY_KP_DECIMAL: return "KEYPAD DECIMAL";
case GLFW_KEY_KP_EQUAL: return "KEYPAD EQUAL";
case GLFW_KEY_KP_ENTER: return "KEYPAD ENTER";
case GLFW_KEY_PRINT_SCREEN: return "PRINT SCREEN";
case GLFW_KEY_NUM_LOCK: return "NUM LOCK";
case GLFW_KEY_CAPS_LOCK: return "CAPS LOCK";
case GLFW_KEY_SCROLL_LOCK: return "SCROLL LOCK";
case GLFW_KEY_PAUSE: return "PAUSE";
case GLFW_KEY_LEFT_SUPER: return "LEFT SUPER";
case GLFW_KEY_RIGHT_SUPER: return "RIGHT SUPER";
case GLFW_KEY_MENU: return "MENU";
default: return "UNKNOWN";
}
}
static const char* get_action_name(int action)
{
switch (action)
{
case GLFW_PRESS:
return "pressed";
case GLFW_RELEASE:
return "released";
case GLFW_REPEAT:
return "repeated";
}
return "caused unknown action";
}
static const char* get_button_name(int button)
{
switch (button)
{
case GLFW_MOUSE_BUTTON_LEFT:
return "left";
case GLFW_MOUSE_BUTTON_RIGHT:
return "right";
case GLFW_MOUSE_BUTTON_MIDDLE:
return "middle";
default:
{
static char name[16];
snprintf(name, sizeof(name), "%i", button);
return name;
}
}
}
static const char* get_mods_name(int mods)
{
static char name[512];
if (mods == 0)
return " no mods";
name[0] = '\0';
if (mods & GLFW_MOD_SHIFT)
strcat(name, " shift");
if (mods & GLFW_MOD_CONTROL)
strcat(name, " control");
if (mods & GLFW_MOD_ALT)
strcat(name, " alt");
if (mods & GLFW_MOD_SUPER)
strcat(name, " super");
if (mods & GLFW_MOD_CAPS_LOCK)
strcat(name, " capslock-on");
if (mods & GLFW_MOD_NUM_LOCK)
strcat(name, " numlock-on");
return name;
}
static size_t encode_utf8(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;
}
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void window_pos_callback(GLFWwindow* window, int x, int y)
{
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Window position: %i %i\n",
counter++, slot->number, glfwGetTime(), x, y);
}
static void window_size_callback(GLFWwindow* window, int width, int height)
{
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Window size: %i %i\n",
counter++, slot->number, glfwGetTime(), width, height);
}
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Framebuffer size: %i %i\n",
counter++, slot->number, glfwGetTime(), width, height);
}
static void window_content_scale_callback(GLFWwindow* window, float xscale, float yscale)
{
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Window content scale: %0.3f %0.3f\n",
counter++, slot->number, glfwGetTime(), xscale, yscale);
}
static void window_close_callback(GLFWwindow* window)
{
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Window close\n",
counter++, slot->number, glfwGetTime());
if (!slot->closeable)
{
printf("(( closing is disabled, press %s to re-enable )\n",
glfwGetKeyName(GLFW_KEY_C, 0));
}
glfwSetWindowShouldClose(window, slot->closeable);
}
static void window_refresh_callback(GLFWwindow* window)
{
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Window refresh\n",
counter++, slot->number, glfwGetTime());
glfwMakeContextCurrent(window);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
}
static void window_focus_callback(GLFWwindow* window, int focused)
{
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Window %s\n",
counter++, slot->number, glfwGetTime(),
focused ? "focused" : "defocused");
}
static void window_iconify_callback(GLFWwindow* window, int iconified)
{
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Window was %s\n",
counter++, slot->number, glfwGetTime(),
iconified ? "iconified" : "uniconified");
}
static void window_maximize_callback(GLFWwindow* window, int maximized)
{
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Window was %s\n",
counter++, slot->number, glfwGetTime(),
maximized ? "maximized" : "unmaximized");
}
static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Mouse button %i (%s) (with%s) was %s\n",
counter++, slot->number, glfwGetTime(), button,
get_button_name(button),
get_mods_name(mods),
get_action_name(action));
}
static void cursor_position_callback(GLFWwindow* window, double x, double y)
{
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Cursor position: %f %f\n",
counter++, slot->number, glfwGetTime(), x, y);
}
static void cursor_enter_callback(GLFWwindow* window, int entered)
{
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Cursor %s window\n",
counter++, slot->number, glfwGetTime(),
entered ? "entered" : "left");
}
static void scroll_callback(GLFWwindow* window, double x, double y)
{
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Scroll: %0.3f %0.3f\n",
counter++, slot->number, glfwGetTime(), x, y);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
Slot* slot = glfwGetWindowUserPointer(window);
const char* name = glfwGetKeyName(key, scancode);
if (name)
{
printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x (%s) (%s) (with%s) was %s\n",
counter++, slot->number, glfwGetTime(), key, scancode,
get_key_name(key),
name,
get_mods_name(mods),
get_action_name(action));
}
else
{
printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x (%s) (with%s) was %s\n",
counter++, slot->number, glfwGetTime(), key, scancode,
get_key_name(key),
get_mods_name(mods),
get_action_name(action));
}
if (action != GLFW_PRESS)
return;
switch (key)
{
case GLFW_KEY_C:
{
slot->closeable = !slot->closeable;
printf("(( closing %s ))\n", slot->closeable ? "enabled" : "disabled");
break;
}
case GLFW_KEY_L:
{
const int state = glfwGetInputMode(window, GLFW_LOCK_KEY_MODS);
glfwSetInputMode(window, GLFW_LOCK_KEY_MODS, !state);
printf("(( lock key mods %s ))\n", !state ? "enabled" : "disabled");
break;
}
}
}
static void char_callback(GLFWwindow* window, unsigned int codepoint)
{
Slot* slot = glfwGetWindowUserPointer(window);
char string[5] = "";
encode_utf8(string, codepoint);
printf("%08x to %i at %0.3f: Character 0x%08x (%s) input\n",
counter++, slot->number, glfwGetTime(), codepoint, string);
}
static void preedit_callback(GLFWwindow* window, int preeditCount,
unsigned int* preeditString, int blockCount,
int* blockSizes, int focusedBlock, int caret)
{
Slot* slot = glfwGetWindowUserPointer(window);
int i, blockIndex = -1, remainingBlockSize = 0;
int width, height;
char encoded[5] = "";
size_t encodedCount = 0;
printf("%08x to %i at %0.3f: Preedit text ",
counter++, slot->number, glfwGetTime());
if (preeditCount == 0 || blockCount == 0)
{
printf("(empty)\n");
}
else
{
for (i = 0; i < preeditCount; i++)
{
if (remainingBlockSize == 0)
{
if (blockIndex == focusedBlock)
printf("]");
blockIndex++;
remainingBlockSize = blockSizes[blockIndex];
printf("\n block %d: ", blockIndex);
if (blockIndex == focusedBlock)
printf("[");
}
if (i == caret)
printf("|");
encodedCount = encode_utf8(encoded, preeditString[i]);
encoded[encodedCount] = '\0';
printf("%s", encoded);
remainingBlockSize--;
}
if (blockIndex == focusedBlock)
printf("]");
if (caret == preeditCount)
printf("|");
printf("\n");
glfwGetWindowSize(window, &width, &height);
glfwSetPreeditCursorRectangle(window, width/2, height/2, 1, 20);
}
}
static void ime_callback(GLFWwindow* window)
{
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: IME switched\n",
counter++, slot->number, glfwGetTime());
}
static void drop_callback(GLFWwindow* window, int count, const char* paths[])
{
int i;
Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Drop input\n",
counter++, slot->number, glfwGetTime());
for (i = 0; i < count; i++)
printf(" %i: \"%s\"\n", i, paths[i]);
}
static void monitor_callback(GLFWmonitor* monitor, int event)
{
if (event == GLFW_CONNECTED)
{
int x, y, widthMM, heightMM;
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwGetMonitorPos(monitor, &x, &y);
glfwGetMonitorPhysicalSize(monitor, &widthMM, &heightMM);
printf("%08x at %0.3f: Monitor %s (%ix%i at %ix%i, %ix%i mm) was connected\n",
counter++,
glfwGetTime(),
glfwGetMonitorName(monitor),
mode->width, mode->height,
x, y,
widthMM, heightMM);
}
else if (event == GLFW_DISCONNECTED)
{
printf("%08x at %0.3f: Monitor %s was disconnected\n",
counter++,
glfwGetTime(),
glfwGetMonitorName(monitor));
}
}
static void joystick_callback(int jid, int event)
{
if (event == GLFW_CONNECTED)
{
int axisCount, buttonCount, hatCount;
glfwGetJoystickAxes(jid, &axisCount);
glfwGetJoystickButtons(jid, &buttonCount);
glfwGetJoystickHats(jid, &hatCount);
printf("%08x at %0.3f: Joystick %i (%s) was connected with %i axes, %i buttons, and %i hats\n",
counter++, glfwGetTime(),
jid,
glfwGetJoystickName(jid),
axisCount,
buttonCount,
hatCount);
if (glfwJoystickIsGamepad(jid))
{
printf(" Joystick %i (%s) has a gamepad mapping (%s)\n",
jid,
glfwGetJoystickGUID(jid),
glfwGetGamepadName(jid));
}
else
{
printf(" Joystick %i (%s) has no gamepad mapping\n",
jid,
glfwGetJoystickGUID(jid));
}
}
else
{
printf("%08x at %0.3f: Joystick %i was disconnected\n",
counter++, glfwGetTime(), jid);
}
}
int main(int argc, char** argv)
{
Slot* slots;
GLFWmonitor* monitor = NULL;
int ch, i, width, height, count = 1;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
printf("Library initialized\n");
glfwSetMonitorCallback(monitor_callback);
glfwSetJoystickCallback(joystick_callback);
while ((ch = getopt(argc, argv, "hfn:")) != -1)
{
switch (ch)
{
case 'h':
usage();
exit(EXIT_SUCCESS);
case 'f':
monitor = glfwGetPrimaryMonitor();
break;
case 'n':
count = (int) strtoul(optarg, NULL, 10);
break;
default:
usage();
exit(EXIT_FAILURE);
}
}
if (monitor)
{
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
glfwWindowHint(GLFW_RED_BITS, mode->redBits);
glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
width = mode->width;
height = mode->height;
}
else
{
width = 640;
height = 480;
}
slots = calloc(count, sizeof(Slot));
for (i = 0; i < count; i++)
{
char title[128];
slots[i].closeable = GLFW_TRUE;
slots[i].number = i + 1;
snprintf(title, sizeof(title), "Event Linter (Window %i)", slots[i].number);
if (monitor)
{
printf("Creating full screen window %i (%ix%i on %s)\n",
slots[i].number,
width, height,
glfwGetMonitorName(monitor));
}
else
{
printf("Creating windowed mode window %i (%ix%i)\n",
slots[i].number,
width, height);
}
slots[i].window = glfwCreateWindow(width, height, title, monitor, NULL);
if (!slots[i].window)
{
free(slots);
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetWindowUserPointer(slots[i].window, slots + i);
glfwSetWindowPosCallback(slots[i].window, window_pos_callback);
glfwSetWindowSizeCallback(slots[i].window, window_size_callback);
glfwSetFramebufferSizeCallback(slots[i].window, framebuffer_size_callback);
glfwSetWindowContentScaleCallback(slots[i].window, window_content_scale_callback);
glfwSetWindowCloseCallback(slots[i].window, window_close_callback);
glfwSetWindowRefreshCallback(slots[i].window, window_refresh_callback);
glfwSetWindowFocusCallback(slots[i].window, window_focus_callback);
glfwSetWindowIconifyCallback(slots[i].window, window_iconify_callback);
glfwSetWindowMaximizeCallback(slots[i].window, window_maximize_callback);
glfwSetMouseButtonCallback(slots[i].window, mouse_button_callback);
glfwSetCursorPosCallback(slots[i].window, cursor_position_callback);
glfwSetCursorEnterCallback(slots[i].window, cursor_enter_callback);
glfwSetScrollCallback(slots[i].window, scroll_callback);
glfwSetKeyCallback(slots[i].window, key_callback);
glfwSetCharCallback(slots[i].window, char_callback);
glfwSetPreeditCallback(slots[i].window, preedit_callback);
glfwSetIMEStatusCallback(slots[i].window, ime_callback);
glfwSetDropCallback(slots[i].window, drop_callback);
glfwMakeContextCurrent(slots[i].window);
gladLoadGL(glfwGetProcAddress);
glfwSwapBuffers(slots[i].window);
}
printf("Main loop starting\n");
for (;;)
{
for (i = 0; i < count; i++)
{
if (glfwWindowShouldClose(slots[i].window))
break;
}
if (i < count)
break;
glfwWaitEvents();
// Workaround for an issue with msvcrt and mintty
fflush(stdout);
}
free(slots);
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,187 +0,0 @@
//========================================================================
// Gamma correction test program
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This program is used to test the gamma correction functionality for
// both full screen and windowed mode windows
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#define NK_IMPLEMENTATION
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_BUTTON_TRIGGER_ON_RELEASE
#include <nuklear.h>
#define NK_GLFW_GL2_IMPLEMENTATION
#include <nuklear_glfw_gl2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action == GLFW_PRESS && key == GLFW_KEY_ESCAPE)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
static void chart_ramp_array(struct nk_context* nk,
struct nk_color color,
int count, unsigned short int* values)
{
if (nk_chart_begin_colored(nk, NK_CHART_LINES,
color, nk_rgb(255, 255, 255),
count, 0, 65535))
{
int i;
for (i = 0; i < count; i++)
{
char buffer[1024];
if (nk_chart_push(nk, values[i]))
{
snprintf(buffer, sizeof(buffer), "#%u: %u (%0.5f) ",
i, values[i], values[i] / 65535.f);
nk_tooltip(nk, buffer);
}
}
nk_chart_end(nk);
}
}
int main(int argc, char** argv)
{
GLFWmonitor* monitor = NULL;
GLFWwindow* window;
GLFWgammaramp orig_ramp;
struct nk_context* nk;
struct nk_font_atlas* atlas;
float gamma_value = 1.f;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
monitor = glfwGetPrimaryMonitor();
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
glfwWindowHint(GLFW_WIN32_KEYBOARD_MENU, GLFW_TRUE);
window = glfwCreateWindow(800, 400, "Gamma Test", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
{
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);
orig_ramp.green = malloc(array_size);
orig_ramp.blue = malloc(array_size);
memcpy(orig_ramp.red, ramp->red, array_size);
memcpy(orig_ramp.green, ramp->green, array_size);
memcpy(orig_ramp.blue, ramp->blue, array_size);
}
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(1);
nk = nk_glfw3_init(window, NK_GLFW3_INSTALL_CALLBACKS);
nk_glfw3_font_stash_begin(&atlas);
nk_glfw3_font_stash_end();
glfwSetKeyCallback(window, key_callback);
while (!glfwWindowShouldClose(window))
{
int width, height;
struct nk_rect area;
glfwGetWindowSize(window, &width, &height);
area = nk_rect(0.f, 0.f, (float) width, (float) height);
nk_window_set_bounds(nk, "", area);
glClear(GL_COLOR_BUFFER_BIT);
nk_glfw3_new_frame();
if (nk_begin(nk, "", area, 0))
{
const GLFWgammaramp* ramp;
nk_layout_row_dynamic(nk, 30, 3);
if (nk_slider_float(nk, 0.1f, &gamma_value, 5.f, 0.1f))
glfwSetGamma(monitor, gamma_value);
nk_labelf(nk, NK_TEXT_LEFT, "%0.1f", gamma_value);
if (nk_button_label(nk, "Revert"))
glfwSetGammaRamp(monitor, &orig_ramp);
ramp = glfwGetGammaRamp(monitor);
nk_layout_row_dynamic(nk, height - 60.f, 3);
chart_ramp_array(nk, nk_rgb(255, 0, 0), ramp->size, ramp->red);
chart_ramp_array(nk, nk_rgb(0, 255, 0), ramp->size, ramp->green);
chart_ramp_array(nk, nk_rgb(0, 0, 255), ramp->size, ramp->blue);
}
nk_end(nk);
nk_glfw3_render(NK_ANTI_ALIASING_ON);
glfwSwapBuffers(window);
glfwWaitEventsTimeout(1.0);
}
free(orig_ramp.red);
free(orig_ramp.green);
free(orig_ramp.blue);
nk_glfw3_shutdown();
glfwTerminate();
exit(EXIT_SUCCESS);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,150 +0,0 @@
//========================================================================
// Window icon test program
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This program is used to test the icon feature.
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// a simple glfw logo
const char* const logo[] =
{
"................",
"................",
"...0000..0......",
"...0.....0......",
"...0.00..0......",
"...0..0..0......",
"...0000..0000...",
"................",
"................",
"...000..0...0...",
"...0....0...0...",
"...000..0.0.0...",
"...0....0.0.0...",
"...0....00000...",
"................",
"................"
};
const unsigned char icon_colors[5][4] =
{
{ 0, 0, 0, 255 }, // black
{ 255, 0, 0, 255 }, // red
{ 0, 255, 0, 255 }, // green
{ 0, 0, 255, 255 }, // blue
{ 255, 255, 255, 255 } // white
};
static int cur_icon_color = 0;
static void set_icon(GLFWwindow* window, int icon_color)
{
int x, y;
unsigned char pixels[16 * 16 * 4];
unsigned char* target = pixels;
GLFWimage img = { 16, 16, pixels };
for (y = 0; y < img.width; y++)
{
for (x = 0; x < img.height; x++)
{
if (logo[y][x] == '0')
memcpy(target, icon_colors[icon_color], 4);
else
memset(target, 0, 4);
target += 4;
}
}
glfwSetWindowIcon(window, 1, &img);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action != GLFW_PRESS)
return;
switch (key)
{
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
case GLFW_KEY_SPACE:
cur_icon_color = (cur_icon_color + 1) % 5;
set_icon(window, cur_icon_color);
break;
case GLFW_KEY_X:
glfwSetWindowIcon(window, 0, NULL);
break;
}
}
int main(int argc, char** argv)
{
GLFWwindow* window;
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
exit(EXIT_FAILURE);
}
window = glfwCreateWindow(200, 200, "Window Icon", NULL, NULL);
if (!window)
{
glfwTerminate();
fprintf(stderr, "Failed to open GLFW window\n");
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSetKeyCallback(window, key_callback);
set_icon(window, cur_icon_color);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,298 +0,0 @@
//========================================================================
// Iconify/restore test program
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This program is used to test the iconify/restore functionality for
// both full screen and windowed mode windows
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include "getopt.h"
static int windowed_xpos, windowed_ypos, windowed_width = 640, windowed_height = 480;
static void usage(void)
{
printf("Usage: iconify [-h] [-f [-a] [-n]]\n");
printf("Options:\n");
printf(" -a create windows for all monitors\n");
printf(" -f create full screen window(s)\n");
printf(" -h show this help\n");
}
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
printf("%0.2f Key %s\n",
glfwGetTime(),
action == GLFW_PRESS ? "pressed" : "released");
if (action != GLFW_PRESS)
return;
switch (key)
{
case GLFW_KEY_I:
glfwIconifyWindow(window);
break;
case GLFW_KEY_M:
glfwMaximizeWindow(window);
break;
case GLFW_KEY_R:
glfwRestoreWindow(window);
break;
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
case GLFW_KEY_A:
glfwSetWindowAttrib(window, GLFW_AUTO_ICONIFY, !glfwGetWindowAttrib(window, GLFW_AUTO_ICONIFY));
break;
case GLFW_KEY_B:
glfwSetWindowAttrib(window, GLFW_RESIZABLE, !glfwGetWindowAttrib(window, GLFW_RESIZABLE));
break;
case GLFW_KEY_D:
glfwSetWindowAttrib(window, GLFW_DECORATED, !glfwGetWindowAttrib(window, GLFW_DECORATED));
break;
case GLFW_KEY_F:
glfwSetWindowAttrib(window, GLFW_FLOATING, !glfwGetWindowAttrib(window, GLFW_FLOATING));
break;
case GLFW_KEY_F11:
case GLFW_KEY_ENTER:
{
if (mods != GLFW_MOD_ALT)
return;
if (glfwGetWindowMonitor(window))
{
glfwSetWindowMonitor(window, NULL,
windowed_xpos, windowed_ypos,
windowed_width, windowed_height,
0);
}
else
{
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
if (monitor)
{
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwGetWindowPos(window, &windowed_xpos, &windowed_ypos);
glfwGetWindowSize(window, &windowed_width, &windowed_height);
glfwSetWindowMonitor(window, monitor,
0, 0, mode->width, mode->height,
mode->refreshRate);
}
}
break;
}
}
}
static void window_size_callback(GLFWwindow* window, int width, int height)
{
printf("%0.2f Window resized to %ix%i\n", glfwGetTime(), width, height);
}
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
printf("%0.2f Framebuffer resized to %ix%i\n", glfwGetTime(), width, height);
}
static void window_focus_callback(GLFWwindow* window, int focused)
{
printf("%0.2f Window %s\n",
glfwGetTime(),
focused ? "focused" : "defocused");
}
static void window_iconify_callback(GLFWwindow* window, int iconified)
{
printf("%0.2f Window %s\n",
glfwGetTime(),
iconified ? "iconified" : "uniconified");
}
static void window_maximize_callback(GLFWwindow* window, int maximized)
{
printf("%0.2f Window %s\n",
glfwGetTime(),
maximized ? "maximized" : "unmaximized");
}
static void window_refresh_callback(GLFWwindow* window)
{
printf("%0.2f Window refresh\n", glfwGetTime());
glfwMakeContextCurrent(window);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
}
static GLFWwindow* create_window(GLFWmonitor* monitor)
{
int width, height;
GLFWwindow* window;
if (monitor)
{
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
glfwWindowHint(GLFW_RED_BITS, mode->redBits);
glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
width = mode->width;
height = mode->height;
}
else
{
width = windowed_width;
height = windowed_height;
}
window = glfwCreateWindow(width, height, "Iconify", monitor, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
return window;
}
int main(int argc, char** argv)
{
int ch, i, window_count;
int fullscreen = GLFW_FALSE, all_monitors = GLFW_FALSE;
GLFWwindow** windows;
while ((ch = getopt(argc, argv, "afhn")) != -1)
{
switch (ch)
{
case 'a':
all_monitors = GLFW_TRUE;
break;
case 'h':
usage();
exit(EXIT_SUCCESS);
case 'f':
fullscreen = GLFW_TRUE;
break;
default:
usage();
exit(EXIT_FAILURE);
}
}
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
if (fullscreen && all_monitors)
{
int monitor_count;
GLFWmonitor** monitors = glfwGetMonitors(&monitor_count);
window_count = monitor_count;
windows = calloc(window_count, sizeof(GLFWwindow*));
for (i = 0; i < monitor_count; i++)
{
windows[i] = create_window(monitors[i]);
if (!windows[i])
break;
}
}
else
{
GLFWmonitor* monitor = NULL;
if (fullscreen)
monitor = glfwGetPrimaryMonitor();
window_count = 1;
windows = calloc(window_count, sizeof(GLFWwindow*));
windows[0] = create_window(monitor);
}
for (i = 0; i < window_count; i++)
{
glfwSetKeyCallback(windows[i], key_callback);
glfwSetFramebufferSizeCallback(windows[i], framebuffer_size_callback);
glfwSetWindowSizeCallback(windows[i], window_size_callback);
glfwSetWindowFocusCallback(windows[i], window_focus_callback);
glfwSetWindowIconifyCallback(windows[i], window_iconify_callback);
glfwSetWindowMaximizeCallback(windows[i], window_maximize_callback);
glfwSetWindowRefreshCallback(windows[i], window_refresh_callback);
window_refresh_callback(windows[i]);
printf("Window is %s and %s\n",
glfwGetWindowAttrib(windows[i], GLFW_ICONIFIED) ? "iconified" : "restored",
glfwGetWindowAttrib(windows[i], GLFW_FOCUSED) ? "focused" : "defocused");
}
for (;;)
{
glfwWaitEvents();
for (i = 0; i < window_count; i++)
{
if (glfwWindowShouldClose(windows[i]))
break;
}
if (i < window_count)
break;
// Workaround for an issue with msvcrt and mintty
fflush(stdout);
}
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,838 +0,0 @@
//========================================================================
// Input Test
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) Daijiro Fukuda <fukuda@clear-code.com>
// Copyright (c) Takuro Ashie <ashie@clear-code.com>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// For font handiling, I reffered to https://github.com/Immediate-Mode-UI/Nuklear/wiki/Complete-font-guide.
// For nuklear handling, I reffered to tests/window.c.
//
// Currently, it is made for Japanese input only.
// You have to select the correct font to display Japanese texts.
// To handle other languages, you need to add correct ranges to nk_font_config.
//
// On X11 or Wayland, you can choose a font by GUI if "fontconfig" libarary is enabled.
//
// On Win32, "Yu Mincho" is selected by default if it is installed. This font is
// included in the FOD packages, so it will be installed automatically when you
// enable Japanese input on your environment, or you can install it by
// "Manage optional features" in "Apps & features".
// Refer: https://learn.microsoft.com/en-us/typography/fonts/windows_10_font_list#japanese-supplemental-fonts
//
// On macOS, "Arial Unicode MS" is selected by default if it is installed.
// I assume that this font is usually installed, but if it is not installed,
// please install it manually.
//
// You can also specify a TTF filepath and use your own favorite font by setting
// TTF_FONT_FILEPATH below.
//
//========================================================================
// Please comment out and set font filepath here to change default font
// #define TTF_FONT_FILEPATH ""
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <stdarg.h>
#define NK_IMPLEMENTATION
#define NK_INCLUDE_STANDARD_IO
#define NK_KEYSTATE_BASED_INPUT
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_BUTTON_TRIGGER_ON_RELEASE
// To increase the number of characters that can be entered at one time
#define NK_INPUT_MAX 64
#include <nuklear.h>
#define NK_GLFW_GL2_IMPLEMENTATION
#include <nuklear_glfw_gl2.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "getopt.h"
#if defined(FONTCONFIG_ENABLED)
#include <fontconfig/fontconfig.h>
#endif
#define MAX_BUFFER_LEN 1024
// https://github.com/Immediate-Mode-UI/Nuklear/wiki/Complete-font-guide
// https://unicode-table.com
// To handle other languages, you need to fix these ranges.
static nk_rune rangesJapan[] = {
0x0020, 0x007E, // Basic Latin
0x2000, 0x206F, // General Punctuation
0x3000, 0x303F, // CJK Symbols and Punctuation
0x3041, 0x309F, // Hiragana
0x30A0, 0x30FF, // Katakana
0x4E00, 0x9FFF, // All Kanji
0xFF01, 0xFFEF, // Halfwidth and Fullwidth Forms
0
};
#define MAX_FONTS_LEN 512
#define MAX_FONT_FAMILY_NAME_LEN 128
#define MAX_FONT_FILEPATH_LEN 256
static struct nk_font* currentFont;
static char** fontFamilyNames;
static char** fontFilePaths;
static int fontNum = 0;
static int currentFontIndex = 0;
static int currentIMEStatus = GLFW_FALSE;
#define MAX_PREEDIT_LEN 128
static char preeditBuf[MAX_PREEDIT_LEN] = "";
// Assuming that the page-size is 10 at most.
static char candidateBuf[9][MAX_PREEDIT_LEN];
static int candidatePageSize = 0;
void usage(void)
{
printf("Usage: input_text [-h] [-s] [-c]\n");
printf("Options:\n");
printf(" -s Use on-the-spot sytle on X11. This is ignored on other platforms.\n");
printf(" -c Use manage-preedit-candidate on Win32. This is ignored on other platforms.\n");
printf(" -h Show this help\n");
}
static size_t encode_utf8(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;
}
static int add_font(const char* familyName, const char* ttfFilePath, int checkExistence)
{
if (MAX_FONTS_LEN <= fontNum)
return GLFW_FALSE;
if (MAX_FONT_FAMILY_NAME_LEN <= strlen(familyName) || MAX_FONT_FILEPATH_LEN <= strlen(ttfFilePath))
return GLFW_FALSE;
if (checkExistence)
{
FILE* fp = fopen(ttfFilePath, "rb");
if (!fp)
return GLFW_FALSE;
fclose(fp);
}
fontFamilyNames[fontNum] = (char*) malloc(1 + strlen(familyName));
assert(fontFamilyNames[fontNum]);
strcpy(fontFamilyNames[fontNum], familyName);
fontFilePaths[fontNum] = (char*) malloc(1 + strlen(ttfFilePath));
assert(fontFilePaths[fontNum]);
strcpy(fontFilePaths[fontNum], ttfFilePath);
fontNum++;
return GLFW_TRUE;
}
static int replace_font(int index, const char* familyName, const char* ttfFilePath, int checkExistence)
{
if (index == 0 || fontNum <= index)
return GLFW_FALSE;
if (MAX_FONT_FAMILY_NAME_LEN <= strlen(familyName) || MAX_FONT_FILEPATH_LEN <= strlen(ttfFilePath))
return GLFW_FALSE;
if (checkExistence)
{
FILE* fp = fopen(ttfFilePath, "rb");
if (!fp)
return GLFW_FALSE;
fclose(fp);
}
free(fontFamilyNames[index]);
free(fontFilePaths[index]);
fontFamilyNames[index] = (char*) malloc(1 + strlen(familyName));
assert(fontFamilyNames[index]);
strcpy(fontFamilyNames[index], familyName);
fontFilePaths[index] = (char*) malloc(1 + strlen(ttfFilePath));
assert(fontFilePaths[index]);
strcpy(fontFilePaths[index], ttfFilePath);
return GLFW_TRUE;
}
#if defined(TTF_FONT_FILEPATH)
static int load_custom_font()
{
if (MAX_FONTS_LEN <= fontNum)
return GLFW_FALSE;
if (!(TTF_FONT_FILEPATH && *TTF_FONT_FILEPATH))
return GLFW_FALSE;
return add_font("Custom", TTF_FONT_FILEPATH, GLFW_TRUE);
}
#endif
#if defined(FONTCONFIG_ENABLED)
static void load_font_list_by_fontconfig()
{
FcConfig* config = FcInitLoadConfigAndFonts();
FcFontSet* fontset = FcConfigGetFonts(config, FcSetSystem);
if (!fontset)
{
printf("load_font_list_by_fontconfig failed.\n");
FcConfigDestroy(config);
return;
}
for (int i = 0; i < fontset->nfont; i++)
{
FcValue fvalue, dvalue;
if (FcResultMatch == FcPatternGet(fontset->fonts[i], FC_FAMILY, 0, &fvalue))
{
if (FcResultMatch == FcPatternGet(fontset->fonts[i], FC_FILE, 0, &dvalue))
{
const char* familyName = (const char*) fvalue.u.s;
const char* filePath = (const char*) dvalue.u.s;
int existsFamily = GLFW_FALSE;
int existingIndex = 0;
if (!strstr(filePath, ".ttf"))
{
continue;
}
for (int j = 1; j < fontNum; ++j)
{
if (strcmp(fontFamilyNames[j], familyName) == 0)
{
existsFamily = GLFW_TRUE;
existingIndex = j;
break;
}
}
if (existsFamily)
{
// Prefer "regular" to the others.
if (strstr(filePath, "regular") || strstr(filePath, "Regular"))
replace_font(existingIndex, familyName, filePath, GLFW_FALSE);
}
else
add_font(familyName, filePath, GLFW_FALSE);
if (MAX_FONTS_LEN <= fontNum)
{
printf("MAX_FONTS_LEN reached. Could not load some fonts.\n");
break;
}
}
}
}
FcConfigDestroy(config);
}
#endif
static void load_default_font_for_each_platform()
{
int hasSucceeded = GLFW_FALSE;
if (MAX_FONTS_LEN <= fontNum)
return;
if (glfwGetPlatform() == GLFW_PLATFORM_COCOA)
hasSucceeded = add_font("Arial Unicode MS", "/Library/Fonts/Arial Unicode.ttf", GLFW_TRUE);
else if(glfwGetPlatform() == GLFW_PLATFORM_WIN32)
{
// Use "Yu Mincho" since it is the only TTF for Japanese in the FOD packages on Windows10 and Windows11.
// https://learn.microsoft.com/en-us/typography/fonts/windows_10_font_list#japanese-supplemental-fonts
char filepath[MAX_FONT_FILEPATH_LEN];
char* winDir = getenv("systemroot");
if (winDir)
snprintf(filepath, MAX_FONT_FILEPATH_LEN, "%s\\Fonts\\Yumin.ttf", winDir);
else
strcpy(filepath, "C:\\Windows\\Fonts\\Yumin.ttf");
hasSucceeded = add_font("Yu Mincho Regular", filepath, GLFW_TRUE);
}
if (hasSucceeded)
currentFontIndex = fontNum - 1;
}
static void init_font_list()
{
int useCustomFont = GLFW_FALSE;
int customFontIndex = 0;
fontFamilyNames = (char**) malloc(sizeof(char*) * MAX_FONTS_LEN);
assert(fontFamilyNames);
fontFilePaths = (char**) malloc(sizeof(char*) * MAX_FONTS_LEN);
assert(fontFilePaths);
fontFamilyNames[0] = "GLFW default";
fontFilePaths[0] = "";
fontNum++;
#if defined(TTF_FONT_FILEPATH)
useCustomFont = load_custom_font();
if (useCustomFont)
customFontIndex = fontNum - 1;
#endif
load_default_font_for_each_platform();
#if defined(FONTCONFIG_ENABLED)
load_font_list_by_fontconfig();
#endif
if (useCustomFont)
currentFontIndex = customFontIndex;
}
static void deinit_font_list()
{
for (int i = 1; i < fontNum; ++i)
{
free(fontFamilyNames[i]);
free(fontFilePaths[i]);
}
free(fontFamilyNames);
free(fontFilePaths);
}
// https://github.com/Immediate-Mode-UI/Nuklear/wiki/Complete-font-guide
static void update_font(struct nk_context* nk, float height)
{
struct nk_font_atlas* atlas;
nk_glfw3_font_stash_begin(&atlas);
if (currentFontIndex == 0)
{
currentFont = nk_font_atlas_add_default(atlas, height, 0);
}
else
{
struct nk_font* new_font;
struct nk_font_config cfg;
cfg = nk_font_config(0);
cfg.range = rangesJapan;
cfg.oversample_h = 1;
cfg.oversample_v = 1;
cfg.pixel_snap = true;
new_font = nk_font_atlas_add_from_file(atlas, fontFilePaths[currentFontIndex], height, &cfg);
if (new_font)
{
currentFont = new_font;
printf("Succeeded to load font file: %s\n", fontFilePaths[currentFontIndex]);
}
else
printf("Failed to load font file: %s\n", fontFilePaths[currentFontIndex]);
}
nk_glfw3_font_stash_end();
nk_style_set_font(nk, &currentFont->handle);
}
static void set_menu_buttons(GLFWwindow* window, struct nk_context* nk, int height)
{
static int windowedX, windowedY, windowedWidth, windowedHeight;
nk_layout_row_dynamic(nk, height, 2);
if (nk_button_label(nk, "Toggle Fullscreen"))
{
if (glfwGetWindowMonitor(window))
{
glfwSetWindowMonitor(window, NULL,
windowedX, windowedY,
windowedWidth, windowedHeight, 0);
}
else
{
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwGetWindowPos(window, &windowedX, &windowedY);
glfwGetWindowSize(window, &windowedWidth, &windowedHeight);
glfwSetWindowMonitor(window, monitor,
0, 0, mode->width, mode->height,
mode->refreshRate);
}
}
{
int auto_iconify = glfwGetWindowAttrib(window, GLFW_AUTO_ICONIFY);
if (nk_checkbox_label(nk, "Auto Iconify", &auto_iconify))
glfwSetWindowAttrib(window, GLFW_AUTO_ICONIFY, auto_iconify);
}
}
static int set_font_selecter(GLFWwindow* window, struct nk_context* nk, int height, int fontHeight)
{
int newSelectedIndex;
nk_layout_row_begin(nk, NK_DYNAMIC, height, 2);
nk_layout_row_push(nk, 1.f / 3.f);
nk_label(nk, "Font", NK_TEXT_LEFT);
nk_layout_row_push(nk, 2.f / 3.f);
newSelectedIndex = nk_combo(nk, (const char**) fontFamilyNames, fontNum, currentFontIndex, fontHeight, nk_vec2(300, 400));
nk_layout_row_end(nk);
if (newSelectedIndex == currentFontIndex)
return GLFW_FALSE;
currentFontIndex = newSelectedIndex;
return GLFW_TRUE;
}
static void set_ime_buttons(GLFWwindow* window, struct nk_context* nk, int height)
{
nk_layout_row_dynamic(nk, height, 2);
if (nk_button_label(nk, "Toggle IME status"))
{
glfwSetInputMode(window, GLFW_IME, !currentIMEStatus);
}
if (nk_button_label(nk, "Reset preedit text"))
{
glfwResetPreeditText(window);
}
}
static void set_preedit_cursor_edit(GLFWwindow* window, struct nk_context* nk, int height, int* isAutoUpdating)
{
static int lastX = -1, lastY = -1, lastW = -1, lastH = -1;
static char xBuf[12] = "", yBuf[12] = "", wBuf[12] = "", hBuf[12] = "";
const nk_flags flags = NK_EDIT_FIELD |
NK_EDIT_SIG_ENTER |
NK_EDIT_GOTO_END_ON_ACTIVATE;
nk_flags events;
int x, y, w, h;
glfwGetPreeditCursorRectangle(window, &x, &y, &w, &h);
if (x != lastX)
sprintf(xBuf, "%i", x);
if (y != lastY)
sprintf(yBuf, "%i", y);
if (w != lastW)
sprintf(wBuf, "%i", w);
if (h != lastH)
sprintf(hBuf, "%i", h);
nk_layout_row_begin(nk, NK_DYNAMIC, height, 5);
nk_layout_row_push(nk, 4.f / 9.f);
nk_label(nk, "Preedit cursor (x,y,w,h)", NK_TEXT_LEFT);
nk_layout_row_push(nk, 1.f / 9.f);
events = nk_edit_string_zero_terminated(nk, flags, xBuf,
sizeof(xBuf),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
x = atoi(xBuf);
*isAutoUpdating = GLFW_FALSE;
glfwSetPreeditCursorRectangle(window, x, y, w, h);
}
else if (events & NK_EDIT_DEACTIVATED)
sprintf(xBuf, "%i", x);
nk_layout_row_push(nk, 1.f / 9.f);
events = nk_edit_string_zero_terminated(nk, flags, yBuf,
sizeof(yBuf),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
y = atoi(yBuf);
*isAutoUpdating = GLFW_FALSE;
glfwSetPreeditCursorRectangle(window, x, y, w, h);
}
else if (events & NK_EDIT_DEACTIVATED)
sprintf(yBuf, "%i", y);
nk_layout_row_push(nk, 1.f / 9.f);
events = nk_edit_string_zero_terminated(nk, flags, wBuf,
sizeof(wBuf),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
w = atoi(wBuf);
*isAutoUpdating = GLFW_FALSE;
glfwSetPreeditCursorRectangle(window, x, y, w, h);
}
else if (events & NK_EDIT_DEACTIVATED)
sprintf(wBuf, "%i", w);
nk_layout_row_push(nk, 1.f / 9.f);
events = nk_edit_string_zero_terminated(nk, flags, hBuf,
sizeof(hBuf),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
h = atoi(hBuf);
*isAutoUpdating = GLFW_FALSE;
glfwSetPreeditCursorRectangle(window, x, y, w, h);
}
else if (events & NK_EDIT_DEACTIVATED)
sprintf(hBuf, "%i", h);
nk_layout_row_push(nk, 1.f / 9.f);
nk_checkbox_label(nk, "Auto", isAutoUpdating);
nk_layout_row_end(nk);
lastX = x;
lastY = y;
lastW = w;
lastH = h;
}
static void set_ime_stauts_labels(GLFWwindow* window, struct nk_context* nk, int height)
{
nk_layout_row_dynamic(nk, height, 1);
nk_value_bool(nk, "IME status", currentIMEStatus);
}
static void set_preedit_labels(GLFWwindow* window, struct nk_context* nk, int height)
{
nk_layout_row_begin(nk, NK_DYNAMIC, height, 5);
nk_layout_row_push(nk, 1.f / 3.f);
nk_label(nk, "Preedit info:", NK_TEXT_LEFT);
nk_layout_row_push(nk, 2.f / 3.f);
nk_label(nk, (const char*) preeditBuf, NK_TEXT_LEFT);
nk_layout_row_end(nk);
}
static void set_candidate_labels(GLFWwindow* window, struct nk_context* nk)
{
for (int i = 0; i < 5; ++i)
{
nk_layout_row_begin(nk, NK_DYNAMIC, 30, 3);
nk_layout_row_push(nk, 1.f / 3.f);
if (i == 0)
nk_label(nk, "Candidates:", NK_TEXT_LEFT);
else
nk_label(nk, "", NK_TEXT_LEFT);
nk_layout_row_push(nk, 1.f / 3.f);
if (candidatePageSize > i)
nk_label(nk, (const char*) candidateBuf[i], NK_TEXT_LEFT);
nk_layout_row_push(nk, 1.f / 3.f);
if (candidatePageSize > i + 5)
nk_label(nk, (const char*) candidateBuf[i + 5], NK_TEXT_LEFT);
nk_layout_row_end(nk);
}
}
// If it is possible to take the text-cursor position calculated in `nk_do_edit` function in `deps/nuklear.h`,
// we can set preedit-cursor position more easily.
// However, there doesn't seem to be a way to do that, so this does a simplified calculation only for the end
// of the text. (Can not trace the cursor movement)
static void update_cursor_pos(GLFWwindow* window, struct nk_context* nk, struct nk_user_font* f,
char* boxBuffer, int boxLen, int boxX, int boxY)
{
float lineWidth = 0;
int totalLines = 1;
const char* text;
int textPos = 0;
struct nk_str nkString;
nk_str_init_fixed(&nkString, boxBuffer, (nk_size) MAX_BUFFER_LEN);
nkString.buffer.allocated = (nk_size) boxLen;
nkString.len = nk_utf_len(boxBuffer, boxLen);
text = nk_str_get_const(&nkString);
while (textPos < boxLen)
{
nk_rune unicode = 0;
int remainedBoxLen = boxLen - textPos;
int nextGlyphSize = nk_utf_decode(text + textPos, &unicode, remainedBoxLen);
if (!nextGlyphSize)
break;
if (unicode == '\n')
{
textPos++;
totalLines++;
lineWidth = 0;
continue;
}
textPos += nextGlyphSize;
lineWidth += f->width(f->userdata, f->height, text + textPos, nextGlyphSize);
}
{
int lineHeight = f->height + nk->style.edit.row_padding;
int cursorPosX = boxX + lineWidth;
int cursorPosY = boxY + lineHeight * (totalLines - 1);
int cursorHeight = lineHeight;
int cursorWidth;
// Keep the value of width since it doesn't need to be updated.
glfwGetPreeditCursorRectangle(window, NULL, NULL, &cursorWidth, NULL);
glfwSetPreeditCursorRectangle(window, cursorPosX, cursorPosY, cursorWidth, cursorHeight);
}
}
static void ime_callback(GLFWwindow* window)
{
currentIMEStatus = glfwGetInputMode(window, GLFW_IME);
printf("IME switched: %s\n", currentIMEStatus ? "ON" : "OFF");
}
static void preedit_callback(GLFWwindow* window, int preeditCount,
unsigned int* preeditString, int blockCount,
int* blockSizes, int focusedBlock, int caret)
{
int blockIndex = -1, remainingBlockSize = 0;
if (preeditCount == 0 || blockCount == 0)
{
strcpy(preeditBuf, "(empty)");
return;
}
strcpy(preeditBuf, "");
for (int i = 0; i < preeditCount; i++)
{
char encoded[5] = "";
size_t encodedCount = 0;
if (i == caret)
{
if (strlen(preeditBuf) + strlen("|") < MAX_PREEDIT_LEN)
strcat(preeditBuf, "|");
}
if (remainingBlockSize == 0)
{
if (blockIndex == focusedBlock)
{
if (strlen(preeditBuf) + strlen("]") < MAX_PREEDIT_LEN)
strcat(preeditBuf, "]");
}
blockIndex++;
remainingBlockSize = blockSizes[blockIndex];
if (blockIndex == focusedBlock)
{
if (strlen(preeditBuf) + strlen("[") < MAX_PREEDIT_LEN)
strcat(preeditBuf, "[");
}
}
encodedCount = encode_utf8(encoded, preeditString[i]);
encoded[encodedCount] = '\0';
if (strlen(preeditBuf) + strlen(encoded) < MAX_PREEDIT_LEN)
strcat(preeditBuf, encoded);
remainingBlockSize--;
}
if (blockIndex == focusedBlock)
{
if (strlen(preeditBuf) + strlen("]") < MAX_PREEDIT_LEN)
strcat(preeditBuf, "]");
}
if (caret == preeditCount)
{
if (strlen(preeditBuf) + strlen("|") < MAX_PREEDIT_LEN)
strcat(preeditBuf, "|");
}
}
static void candidate_callback(GLFWwindow* window, int candidates_count,
int selected_index, int page_start, int page_size)
{
int i, j;
candidatePageSize = page_size;
for (i = 0; i < page_size; ++i)
{
int index = i + page_start;
int textCount;
unsigned int* text = glfwGetPreeditCandidate(window, index, &textCount);
if (index == selected_index)
strcpy(candidateBuf[i], "> ");
else
strcpy(candidateBuf[i], "");
for (j = 0; j < textCount; ++j)
{
char encoded[5] = "";
encode_utf8(encoded, text[j]);
if (strlen(candidateBuf[i]) + strlen(encoded) < MAX_PREEDIT_LEN)
strcat(candidateBuf[i], encoded);
}
}
}
int main(int argc, char** argv)
{
GLFWwindow* window;
struct nk_context* nk;
int width, height;
char boxBuffer[MAX_BUFFER_LEN] = "Input text here.";
int boxLen = strlen(boxBuffer);
int isAutoUpdatingCursorPosEnabled = GLFW_TRUE;
int managePreeditCandidate = GLFW_FALSE;
int ch;
while ((ch = getopt(argc, argv, "hsc")) != -1)
{
switch (ch)
{
case 'h':
usage();
exit(EXIT_SUCCESS);
case 's':
glfwInitHint(GLFW_X11_ONTHESPOT, GLFW_TRUE);
break;
case 'c':
glfwInitHint(GLFW_MANAGE_PREEDIT_CANDIDATE, GLFW_TRUE);
managePreeditCandidate = GLFW_TRUE;
break;
}
}
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
glfwWindowHint(GLFW_WIN32_KEYBOARD_MENU, GLFW_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
window = glfwCreateWindow(600, 600, "Input Text", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
currentIMEStatus = glfwGetInputMode(window, GLFW_IME);
glfwSetPreeditCursorRectangle(window, 0, 0, 1, 1);
glfwSetIMEStatusCallback(window, ime_callback);
glfwSetPreeditCallback(window, preedit_callback);
glfwSetPreeditCandidateCallback(window, candidate_callback);
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(0);
nk = nk_glfw3_init(window, NK_GLFW3_INSTALL_CALLBACKS);
init_font_list();
update_font(nk, 18);
while (!glfwWindowShouldClose(window))
{
struct nk_rect area;
glfwGetWindowSize(window, &width, &height);
area = nk_rect(0.f, 0.f, (float) width, (float) height);
nk_window_set_bounds(nk, "main", area);
nk_glfw3_new_frame();
if (nk_begin(nk, "main", area, 0))
{
set_menu_buttons(window, nk, 30);
if (set_font_selecter(window, nk, 30, 18))
update_font(nk, 18);
set_ime_buttons(window, nk, 30);
set_preedit_cursor_edit(window, nk, 30, &isAutoUpdatingCursorPosEnabled);
set_ime_stauts_labels(window, nk, 30);
set_preedit_labels(window, nk, 30);
if (managePreeditCandidate)
set_candidate_labels(window, nk);
nk_layout_row_dynamic(nk, height - 250, 1);
nk_edit_string(nk, NK_EDIT_BOX, boxBuffer, &boxLen, MAX_BUFFER_LEN, nk_filter_default);
}
nk_end(nk);
glClear(GL_COLOR_BUFFER_BIT);
nk_glfw3_render(NK_ANTI_ALIASING_ON);
glfwSwapBuffers(window);
if (isAutoUpdatingCursorPosEnabled)
// I don't know how to get the layout info of `nk_edit_string`.
update_cursor_pos(window, nk, &currentFont->handle, boxBuffer, boxLen, 10,
managePreeditCandidate ? 385 : 220);
glfwWaitEvents();
}
deinit_font_list();
nk_glfw3_shutdown();
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,310 +0,0 @@
//========================================================================
// Input lag test
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test renders a marker at the cursor position reported by GLFW to
// check how much it lags behind the hardware mouse cursor
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#define NK_IMPLEMENTATION
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_STANDARD_VARARGS
#include <nuklear.h>
#define NK_GLFW_GL2_IMPLEMENTATION
#include <nuklear_glfw_gl2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "getopt.h"
void usage(void)
{
printf("Usage: inputlag [-h] [-f]\n");
printf("Options:\n");
printf(" -f create full screen window\n");
printf(" -h show this help\n");
}
struct nk_vec2 cursor_new, cursor_pos, cursor_vel;
enum { cursor_sync_query, cursor_input_message } cursor_method = cursor_sync_query;
void sample_input(GLFWwindow* window)
{
float a = .25; // exponential smoothing factor
if (cursor_method == cursor_sync_query) {
double x, y;
glfwGetCursorPos(window, &x, &y);
cursor_new.x = (float) x;
cursor_new.y = (float) y;
}
cursor_vel.x = (cursor_new.x - cursor_pos.x) * a + cursor_vel.x * (1 - a);
cursor_vel.y = (cursor_new.y - cursor_pos.y) * a + cursor_vel.y * (1 - a);
cursor_pos = cursor_new;
}
void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos)
{
cursor_new.x = (float) xpos;
cursor_new.y = (float) ypos;
}
int enable_vsync = nk_true;
void update_vsync()
{
glfwSwapInterval(enable_vsync == nk_true ? 1 : 0);
}
int swap_clear = nk_false;
int swap_finish = nk_true;
int swap_occlusion_query = nk_false;
int swap_read_pixels = nk_false;
GLuint occlusion_query;
void swap_buffers(GLFWwindow* window)
{
glfwSwapBuffers(window);
if (swap_clear)
glClear(GL_COLOR_BUFFER_BIT);
if (swap_finish)
glFinish();
if (swap_occlusion_query) {
GLint occlusion_result;
if (!occlusion_query)
glGenQueries(1, &occlusion_query);
glBeginQuery(GL_SAMPLES_PASSED, occlusion_query);
glBegin(GL_POINTS);
glVertex2f(0, 0);
glEnd();
glEndQuery(GL_SAMPLES_PASSED);
glGetQueryObjectiv(occlusion_query, GL_QUERY_RESULT, &occlusion_result);
}
if (swap_read_pixels) {
unsigned char rgba[4];
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba);
}
}
void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action != GLFW_PRESS)
return;
switch (key)
{
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, 1);
break;
}
}
void draw_marker(struct nk_command_buffer* canvas, int lead, struct nk_vec2 pos)
{
struct nk_color colors[4] = { nk_rgb(255,0,0), nk_rgb(255,255,0), nk_rgb(0,255,0), nk_rgb(0,96,255) };
struct nk_rect rect = { -5 + pos.x, -5 + pos.y, 10, 10 };
nk_fill_circle(canvas, rect, colors[lead]);
}
int main(int argc, char** argv)
{
int ch, width, height;
unsigned long frame_count = 0;
double last_time, current_time;
double frame_rate = 0;
int fullscreen = GLFW_FALSE;
GLFWmonitor* monitor = NULL;
GLFWwindow* window;
struct nk_context* nk;
struct nk_font_atlas* atlas;
int show_forecasts = nk_true;
while ((ch = getopt(argc, argv, "fh")) != -1)
{
switch (ch)
{
case 'h':
usage();
exit(EXIT_SUCCESS);
case 'f':
fullscreen = GLFW_TRUE;
break;
}
}
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
if (fullscreen)
{
const GLFWvidmode* mode;
monitor = glfwGetPrimaryMonitor();
mode = glfwGetVideoMode(monitor);
width = mode->width;
height = mode->height;
}
else
{
width = 640;
height = 480;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
glfwWindowHint(GLFW_WIN32_KEYBOARD_MENU, GLFW_TRUE);
window = glfwCreateWindow(width, height, "Input lag test", monitor, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
update_vsync();
last_time = glfwGetTime();
nk = nk_glfw3_init(window, NK_GLFW3_INSTALL_CALLBACKS);
nk_glfw3_font_stash_begin(&atlas);
nk_glfw3_font_stash_end();
glfwSetKeyCallback(window, key_callback);
glfwSetCursorPosCallback(window, cursor_pos_callback);
while (!glfwWindowShouldClose(window))
{
int width, height;
struct nk_rect area;
glfwPollEvents();
sample_input(window);
glfwGetWindowSize(window, &width, &height);
area = nk_rect(0.f, 0.f, (float) width, (float) height);
glClear(GL_COLOR_BUFFER_BIT);
nk_glfw3_new_frame();
if (nk_begin(nk, "", area, 0))
{
nk_flags align_left = NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE;
struct nk_command_buffer *canvas = nk_window_get_canvas(nk);
int lead;
for (lead = show_forecasts ? 3 : 0; lead >= 0; lead--)
draw_marker(canvas, lead, nk_vec2(cursor_pos.x + cursor_vel.x * lead,
cursor_pos.y + cursor_vel.y * lead));
// print instructions
nk_layout_row_dynamic(nk, 20, 1);
nk_label(nk, "Move mouse uniformly and check marker under cursor:", align_left);
for (lead = 0; lead <= 3; lead++) {
nk_layout_row_begin(nk, NK_STATIC, 12, 2);
nk_layout_row_push(nk, 25);
draw_marker(canvas, lead, nk_layout_space_to_screen(nk, nk_vec2(20, 5)));
nk_label(nk, "", 0);
nk_layout_row_push(nk, 500);
if (lead == 0)
nk_label(nk, "- current cursor position (no input lag)", align_left);
else
nk_labelf(nk, align_left, "- %d-frame forecast (input lag is %d frame)", lead, lead);
nk_layout_row_end(nk);
}
nk_layout_row_dynamic(nk, 20, 1);
nk_checkbox_label(nk, "Show forecasts", &show_forecasts);
nk_label(nk, "Input method:", align_left);
if (nk_option_label(nk, "glfwGetCursorPos (sync query)", cursor_method == cursor_sync_query))
cursor_method = cursor_sync_query;
if (nk_option_label(nk, "glfwSetCursorPosCallback (latest input message)", cursor_method == cursor_input_message))
cursor_method = cursor_input_message;
nk_label(nk, "", 0); // separator
nk_value_float(nk, "FPS", (float) frame_rate);
if (nk_checkbox_label(nk, "Enable vsync", &enable_vsync))
update_vsync();
nk_label(nk, "", 0); // separator
nk_label(nk, "After swap:", align_left);
nk_checkbox_label(nk, "glClear", &swap_clear);
nk_checkbox_label(nk, "glFinish", &swap_finish);
nk_checkbox_label(nk, "draw with occlusion query", &swap_occlusion_query);
nk_checkbox_label(nk, "glReadPixels", &swap_read_pixels);
}
nk_end(nk);
nk_glfw3_render(NK_ANTI_ALIASING_ON);
swap_buffers(window);
frame_count++;
current_time = glfwGetTime();
if (current_time - last_time > 1.0)
{
frame_rate = frame_count / (current_time - last_time);
frame_count = 0;
last_time = current_time;
}
}
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,346 +0,0 @@
//========================================================================
// Joystick input test
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test displays the state of every button and axis of every connected
// joystick and/or gamepad
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#define NK_IMPLEMENTATION
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_BUTTON_TRIGGER_ON_RELEASE
#include <nuklear.h>
#define NK_GLFW_GL2_IMPLEMENTATION
#include <nuklear_glfw_gl2.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef _MSC_VER
#define strdup(x) _strdup(x)
#endif
static GLFWwindow* window;
static int joysticks[GLFW_JOYSTICK_LAST + 1];
static int joystick_count = 0;
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void joystick_callback(int jid, int event)
{
if (event == GLFW_CONNECTED)
joysticks[joystick_count++] = jid;
else if (event == GLFW_DISCONNECTED)
{
int i;
for (i = 0; i < joystick_count; i++)
{
if (joysticks[i] == jid)
break;
}
for (i = i + 1; i < joystick_count; i++)
joysticks[i - 1] = joysticks[i];
joystick_count--;
}
if (!glfwGetWindowAttrib(window, GLFW_FOCUSED))
glfwRequestWindowAttention(window);
}
static void drop_callback(GLFWwindow* window, int count, const char* paths[])
{
int i;
for (i = 0; i < count; i++)
{
long size;
char* text;
FILE* stream = fopen(paths[i], "rb");
if (!stream)
continue;
fseek(stream, 0, SEEK_END);
size = ftell(stream);
fseek(stream, 0, SEEK_SET);
text = malloc(size + 1);
text[size] = '\0';
if (fread(text, 1, size, stream) == size)
glfwUpdateGamepadMappings(text);
free(text);
fclose(stream);
}
}
static const char* joystick_label(int jid)
{
static char label[1024];
snprintf(label, sizeof(label), "%i: %s", jid + 1, glfwGetJoystickName(jid));
return label;
}
static void hat_widget(struct nk_context* nk, unsigned char state)
{
float radius;
struct nk_rect area;
struct nk_vec2 center;
if (nk_widget(&area, nk) == NK_WIDGET_INVALID)
return;
center = nk_vec2(area.x + area.w / 2.f, area.y + area.h / 2.f);
radius = NK_MIN(area.w, area.h) / 2.f;
nk_stroke_circle(nk_window_get_canvas(nk),
nk_rect(center.x - radius,
center.y - radius,
radius * 2.f,
radius * 2.f),
1.f,
nk_rgb(175, 175, 175));
if (state)
{
const float angles[] =
{
0.f, 0.f,
NK_PI * 1.5f, NK_PI * 1.75f,
NK_PI, 0.f,
NK_PI * 1.25f, 0.f,
NK_PI * 0.5f, NK_PI * 0.25f,
0.f, 0.f,
NK_PI * 0.75f, 0.f,
};
const float cosa = nk_cos(angles[state]);
const float sina = nk_sin(angles[state]);
const struct nk_vec2 p0 = nk_vec2(0.f, -radius);
const struct nk_vec2 p1 = nk_vec2( radius / 2.f, -radius / 3.f);
const struct nk_vec2 p2 = nk_vec2(-radius / 2.f, -radius / 3.f);
nk_fill_triangle(nk_window_get_canvas(nk),
center.x + cosa * p0.x + sina * p0.y,
center.y + cosa * p0.y - sina * p0.x,
center.x + cosa * p1.x + sina * p1.y,
center.y + cosa * p1.y - sina * p1.x,
center.x + cosa * p2.x + sina * p2.y,
center.y + cosa * p2.y - sina * p2.x,
nk_rgb(175, 175, 175));
}
}
int main(void)
{
int jid, hat_buttons = GLFW_FALSE;
struct nk_context* nk;
struct nk_font_atlas* atlas;
memset(joysticks, 0, sizeof(joysticks));
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
glfwWindowHint(GLFW_WIN32_KEYBOARD_MENU, GLFW_TRUE);
window = glfwCreateWindow(800, 600, "Joystick Test", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(1);
nk = nk_glfw3_init(window, NK_GLFW3_INSTALL_CALLBACKS);
nk_glfw3_font_stash_begin(&atlas);
nk_glfw3_font_stash_end();
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
{
if (glfwJoystickPresent(jid))
joysticks[joystick_count++] = jid;
}
glfwSetJoystickCallback(joystick_callback);
glfwSetDropCallback(window, drop_callback);
while (!glfwWindowShouldClose(window))
{
int i, width, height;
glfwGetWindowSize(window, &width, &height);
glClear(GL_COLOR_BUFFER_BIT);
nk_glfw3_new_frame();
if (nk_begin(nk,
"Joysticks",
nk_rect(width - 200.f, 0.f, 200.f, (float) height),
NK_WINDOW_MINIMIZABLE |
NK_WINDOW_TITLE))
{
nk_layout_row_dynamic(nk, 30, 1);
nk_checkbox_label(nk, "Hat buttons", &hat_buttons);
if (joystick_count)
{
for (i = 0; i < joystick_count; i++)
{
if (nk_button_label(nk, joystick_label(joysticks[i])))
nk_window_set_focus(nk, joystick_label(joysticks[i]));
}
}
else
nk_label(nk, "No joysticks connected", NK_TEXT_LEFT);
}
nk_end(nk);
for (i = 0; i < joystick_count; i++)
{
if (nk_begin(nk,
joystick_label(joysticks[i]),
nk_rect(i * 20.f, i * 20.f, 550.f, 570.f),
NK_WINDOW_BORDER |
NK_WINDOW_MOVABLE |
NK_WINDOW_SCALABLE |
NK_WINDOW_MINIMIZABLE |
NK_WINDOW_TITLE))
{
int j, axis_count, button_count, hat_count;
const float* axes;
const unsigned char* buttons;
const unsigned char* hats;
GLFWgamepadstate state;
nk_layout_row_dynamic(nk, 30, 1);
nk_labelf(nk, NK_TEXT_LEFT, "Hardware GUID %s",
glfwGetJoystickGUID(joysticks[i]));
nk_label(nk, "Joystick state", NK_TEXT_LEFT);
axes = glfwGetJoystickAxes(joysticks[i], &axis_count);
buttons = glfwGetJoystickButtons(joysticks[i], &button_count);
hats = glfwGetJoystickHats(joysticks[i], &hat_count);
if (!hat_buttons)
button_count -= hat_count * 4;
for (j = 0; j < axis_count; j++)
nk_slide_float(nk, -1.f, axes[j], 1.f, 0.1f);
nk_layout_row_dynamic(nk, 30, 12);
for (j = 0; j < button_count; j++)
{
char name[16];
snprintf(name, sizeof(name), "%i", j + 1);
nk_select_label(nk, name, NK_TEXT_CENTERED, buttons[j]);
}
nk_layout_row_dynamic(nk, 30, 8);
for (j = 0; j < hat_count; j++)
hat_widget(nk, hats[j]);
nk_layout_row_dynamic(nk, 30, 1);
if (glfwGetGamepadState(joysticks[i], &state))
{
int hat = 0;
const char* names[GLFW_GAMEPAD_BUTTON_LAST + 1 - 4] =
{
"A", "B", "X", "Y",
"LB", "RB",
"Back", "Start", "Guide",
"LT", "RT",
};
nk_labelf(nk, NK_TEXT_LEFT,
"Gamepad state: %s",
glfwGetGamepadName(joysticks[i]));
nk_layout_row_dynamic(nk, 30, 2);
for (j = 0; j <= GLFW_GAMEPAD_AXIS_LAST; j++)
nk_slide_float(nk, -1.f, state.axes[j], 1.f, 0.1f);
nk_layout_row_dynamic(nk, 30, GLFW_GAMEPAD_BUTTON_LAST + 1 - 4);
for (j = 0; j <= GLFW_GAMEPAD_BUTTON_LAST - 4; j++)
nk_select_label(nk, names[j], NK_TEXT_CENTERED, state.buttons[j]);
if (state.buttons[GLFW_GAMEPAD_BUTTON_DPAD_UP])
hat |= GLFW_HAT_UP;
if (state.buttons[GLFW_GAMEPAD_BUTTON_DPAD_RIGHT])
hat |= GLFW_HAT_RIGHT;
if (state.buttons[GLFW_GAMEPAD_BUTTON_DPAD_DOWN])
hat |= GLFW_HAT_DOWN;
if (state.buttons[GLFW_GAMEPAD_BUTTON_DPAD_LEFT])
hat |= GLFW_HAT_LEFT;
nk_layout_row_dynamic(nk, 30, 8);
hat_widget(nk, hat);
}
else
nk_label(nk, "Joystick has no gamepad mapping", NK_TEXT_LEFT);
}
nk_end(nk);
}
nk_glfw3_render(NK_ANTI_ALIASING_ON);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,263 +0,0 @@
//========================================================================
// Monitor information tool
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test prints monitor and video mode information or verifies video
// modes
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "getopt.h"
enum Mode
{
LIST_MODE,
TEST_MODE
};
static void usage(void)
{
printf("Usage: monitors [-t]\n");
printf(" monitors -h\n");
}
static int euclid(int a, int b)
{
return b ? euclid(b, a % b) : a;
}
static const char* format_mode(const GLFWvidmode* mode)
{
static char buffer[512];
const int gcd = euclid(mode->width, mode->height);
snprintf(buffer,
sizeof(buffer),
"%i x %i x %i (%i:%i) (%i %i %i) %i Hz",
mode->width, mode->height,
mode->redBits + mode->greenBits + mode->blueBits,
mode->width / gcd, mode->height / gcd,
mode->redBits, mode->greenBits, mode->blueBits,
mode->refreshRate);
buffer[sizeof(buffer) - 1] = '\0';
return buffer;
}
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
printf("Framebuffer resized to %ix%i\n", width, height);
glViewport(0, 0, width, height);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
static void list_modes(GLFWmonitor* monitor)
{
int count, x, y, width_mm, height_mm, i;
int workarea_x, workarea_y, workarea_width, workarea_height;
float xscale, yscale;
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
const GLFWvidmode* modes = glfwGetVideoModes(monitor, &count);
glfwGetMonitorPos(monitor, &x, &y);
glfwGetMonitorPhysicalSize(monitor, &width_mm, &height_mm);
glfwGetMonitorContentScale(monitor, &xscale, &yscale);
glfwGetMonitorWorkarea(monitor, &workarea_x, &workarea_y, &workarea_width, &workarea_height);
printf("Name: %s (%s)\n",
glfwGetMonitorName(monitor),
glfwGetPrimaryMonitor() == monitor ? "primary" : "secondary");
printf("Current mode: %s\n", format_mode(mode));
printf("Virtual position: %i, %i\n", x, y);
printf("Content scale: %f x %f\n", xscale, yscale);
printf("Physical size: %i x %i mm (%0.2f dpi at %i x %i)\n",
width_mm, height_mm, mode->width * 25.4f / width_mm, mode->width, mode->height);
printf("Monitor work area: %i x %i starting at %i, %i\n",
workarea_width, workarea_height, workarea_x, workarea_y);
printf("Modes:\n");
for (i = 0; i < count; i++)
{
printf("%3u: %s", (unsigned int) i, format_mode(modes + i));
if (memcmp(mode, modes + i, sizeof(GLFWvidmode)) == 0)
printf(" (current mode)");
putchar('\n');
}
}
static void test_modes(GLFWmonitor* monitor)
{
int i, count;
GLFWwindow* window;
const GLFWvidmode* modes = glfwGetVideoModes(monitor, &count);
for (i = 0; i < count; i++)
{
const GLFWvidmode* mode = modes + i;
GLFWvidmode current;
glfwWindowHint(GLFW_RED_BITS, mode->redBits);
glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
printf("Testing mode %u on monitor %s: %s\n",
(unsigned int) i,
glfwGetMonitorName(monitor),
format_mode(mode));
window = glfwCreateWindow(mode->width, mode->height,
"Video Mode Test",
glfwGetPrimaryMonitor(),
NULL);
if (!window)
{
printf("Failed to enter mode %u: %s\n",
(unsigned int) i,
format_mode(mode));
continue;
}
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetKeyCallback(window, key_callback);
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(1);
glfwSetTime(0.0);
while (glfwGetTime() < 5.0)
{
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
if (glfwWindowShouldClose(window))
{
printf("User terminated program\n");
glfwTerminate();
exit(EXIT_SUCCESS);
}
}
glGetIntegerv(GL_RED_BITS, &current.redBits);
glGetIntegerv(GL_GREEN_BITS, &current.greenBits);
glGetIntegerv(GL_BLUE_BITS, &current.blueBits);
glfwGetWindowSize(window, &current.width, &current.height);
if (current.redBits != mode->redBits ||
current.greenBits != mode->greenBits ||
current.blueBits != mode->blueBits)
{
printf("*** Color bit mismatch: (%i %i %i) instead of (%i %i %i)\n",
current.redBits, current.greenBits, current.blueBits,
mode->redBits, mode->greenBits, mode->blueBits);
}
if (current.width != mode->width || current.height != mode->height)
{
printf("*** Size mismatch: %ix%i instead of %ix%i\n",
current.width, current.height,
mode->width, mode->height);
}
printf("Closing window\n");
glfwDestroyWindow(window);
window = NULL;
glfwPollEvents();
}
}
int main(int argc, char** argv)
{
int ch, i, count, mode = LIST_MODE;
GLFWmonitor** monitors;
while ((ch = getopt(argc, argv, "th")) != -1)
{
switch (ch)
{
case 'h':
usage();
exit(EXIT_SUCCESS);
case 't':
mode = TEST_MODE;
break;
default:
usage();
exit(EXIT_FAILURE);
}
}
glfwSetErrorCallback(error_callback);
glfwInitHint(GLFW_COCOA_MENUBAR, GLFW_FALSE);
if (!glfwInit())
exit(EXIT_FAILURE);
monitors = glfwGetMonitors(&count);
for (i = 0; i < count; i++)
{
if (mode == LIST_MODE)
list_modes(monitors[i]);
else if (mode == TEST_MODE)
test_modes(monitors[i]);
}
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,221 +0,0 @@
//========================================================================
// Multisample anti-aliasing test
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test renders two high contrast, slowly rotating quads, one aliased
// and one (hopefully) anti-aliased, thus allowing for visual verification
// of whether MSAA is indeed enabled
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#if defined(_MSC_VER)
// Make MS math.h define M_PI
#define _USE_MATH_DEFINES
#endif
#include "linmath.h"
#include <stdio.h>
#include <stdlib.h>
#include "getopt.h"
static const vec2 vertices[4] =
{
{ -0.6f, -0.6f },
{ 0.6f, -0.6f },
{ 0.6f, 0.6f },
{ -0.6f, 0.6f }
};
static const char* vertex_shader_text =
"#version 110\n"
"uniform mat4 MVP;\n"
"attribute vec2 vPos;\n"
"void main()\n"
"{\n"
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
"}\n";
static const char* fragment_shader_text =
"#version 110\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(1.0);\n"
"}\n";
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action != GLFW_PRESS)
return;
switch (key)
{
case GLFW_KEY_SPACE:
glfwSetTime(0.0);
break;
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
}
}
static void usage(void)
{
printf("Usage: msaa [-h] [-s SAMPLES]\n");
}
int main(int argc, char** argv)
{
int ch, samples = 4;
GLFWwindow* window;
GLuint vertex_buffer, vertex_shader, fragment_shader, program;
GLint mvp_location, vpos_location;
while ((ch = getopt(argc, argv, "hs:")) != -1)
{
switch (ch)
{
case 'h':
usage();
exit(EXIT_SUCCESS);
case 's':
samples = atoi(optarg);
break;
default:
usage();
exit(EXIT_FAILURE);
}
}
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
if (samples)
printf("Requesting MSAA with %i samples\n", samples);
else
printf("Requesting that MSAA not be available\n");
glfwWindowHint(GLFW_SAMPLES, samples);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(800, 400, "Aliasing Detector", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetKeyCallback(window, key_callback);
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(1);
glGetIntegerv(GL_SAMPLES, &samples);
if (samples)
printf("Context reports MSAA is available with %i samples\n", samples);
else
printf("Context reports MSAA is unavailable\n");
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
glCompileShader(vertex_shader);
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
glCompileShader(fragment_shader);
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
mvp_location = glGetUniformLocation(program, "MVP");
vpos_location = glGetAttribLocation(program, "vPos");
glEnableVertexAttribArray(vpos_location);
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
sizeof(vertices[0]), (void*) 0);
while (!glfwWindowShouldClose(window))
{
float ratio;
int width, height;
mat4x4 m, p, mvp;
const double angle = glfwGetTime() * M_PI / 180.0;
glfwGetFramebufferSize(window, &width, &height);
ratio = width / (float) height;
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 0.f, 1.f);
mat4x4_translate(m, -1.f, 0.f, 0.f);
mat4x4_rotate_Z(m, m, (float) angle);
mat4x4_mul(mvp, p, m);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
glDisable(GL_MULTISAMPLE);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
mat4x4_translate(m, 1.f, 0.f, 0.f);
mat4x4_rotate_Z(m, m, (float) angle);
mat4x4_mul(mvp, p, m);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
glEnable(GL_MULTISAMPLE);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,241 +0,0 @@
//========================================================================
// Window re-opener (open/close stress test)
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test came about as the result of bug #1262773
//
// It closes and re-opens the GLFW window every five seconds, alternating
// between windowed and full screen mode
//
// It also times and logs opening and closing actions and attempts to separate
// user initiated window closing from its own
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include "linmath.h"
static const char* vertex_shader_text =
"#version 110\n"
"uniform mat4 MVP;\n"
"attribute vec2 vPos;\n"
"void main()\n"
"{\n"
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
"}\n";
static const char* fragment_shader_text =
"#version 110\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(1.0);\n"
"}\n";
static const vec2 vertices[4] =
{
{ -0.5f, -0.5f },
{ 0.5f, -0.5f },
{ 0.5f, 0.5f },
{ -0.5f, 0.5f }
};
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void window_close_callback(GLFWwindow* window)
{
printf("Close callback triggered\n");
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action != GLFW_PRESS)
return;
switch (key)
{
case GLFW_KEY_Q:
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
}
}
static void close_window(GLFWwindow* window)
{
double base = glfwGetTime();
glfwDestroyWindow(window);
printf("Closing window took %0.3f seconds\n", glfwGetTime() - base);
}
int main(int argc, char** argv)
{
int count = 0;
double base;
GLFWwindow* window;
srand((unsigned int) time(NULL));
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
for (;;)
{
int width, height;
GLFWmonitor* monitor = NULL;
GLuint vertex_shader, fragment_shader, program, vertex_buffer;
GLint mvp_location, vpos_location;
if (count & 1)
{
int monitorCount;
GLFWmonitor** monitors = glfwGetMonitors(&monitorCount);
monitor = monitors[rand() % monitorCount];
}
if (monitor)
{
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
width = mode->width;
height = mode->height;
}
else
{
width = 640;
height = 480;
}
base = glfwGetTime();
window = glfwCreateWindow(width, height, "Window Re-opener", monitor, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
if (monitor)
{
printf("Opening full screen window on monitor %s took %0.3f seconds\n",
glfwGetMonitorName(monitor),
glfwGetTime() - base);
}
else
{
printf("Opening regular window took %0.3f seconds\n",
glfwGetTime() - base);
}
glfwSetWindowCloseCallback(window, window_close_callback);
glfwSetKeyCallback(window, key_callback);
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(1);
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
glCompileShader(vertex_shader);
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
glCompileShader(fragment_shader);
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
mvp_location = glGetUniformLocation(program, "MVP");
vpos_location = glGetAttribLocation(program, "vPos");
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(vpos_location);
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
sizeof(vertices[0]), (void*) 0);
glfwSetTime(0.0);
while (glfwGetTime() < 5.0)
{
float ratio;
int width, height;
mat4x4 m, p, mvp;
glfwGetFramebufferSize(window, &width, &height);
ratio = width / (float) height;
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 0.f, 1.f);
mat4x4_identity(m);
mat4x4_rotate_Z(m, m, (float) glfwGetTime());
mat4x4_mul(mvp, p, m);
glUseProgram(program);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glfwSwapBuffers(window);
glfwPollEvents();
if (glfwWindowShouldClose(window))
{
close_window(window);
printf("User closed window\n");
glfwTerminate();
exit(EXIT_SUCCESS);
}
}
printf("Closing window\n");
close_window(window);
count++;
}
glfwTerminate();
}

View File

@ -1,251 +0,0 @@
//========================================================================
// Vsync enabling test
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test renders a high contrast, horizontally moving bar, allowing for
// visual verification of whether the set swap interval is indeed obeyed
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "linmath.h"
static const struct
{
float x, y;
} vertices[4] =
{
{ -0.25f, -1.f },
{ 0.25f, -1.f },
{ 0.25f, 1.f },
{ -0.25f, 1.f }
};
static const char* vertex_shader_text =
"#version 110\n"
"uniform mat4 MVP;\n"
"attribute vec2 vPos;\n"
"void main()\n"
"{\n"
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
"}\n";
static const char* fragment_shader_text =
"#version 110\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(1.0);\n"
"}\n";
static int swap_tear;
static int swap_interval;
static double frame_rate;
static void update_window_title(GLFWwindow* window)
{
char title[256];
snprintf(title, sizeof(title), "Tearing detector (interval %i%s, %0.1f Hz)",
swap_interval,
(swap_tear && swap_interval < 0) ? " (swap tear)" : "",
frame_rate);
glfwSetWindowTitle(window, title);
}
static void set_swap_interval(GLFWwindow* window, int interval)
{
swap_interval = interval;
glfwSwapInterval(swap_interval);
update_window_title(window);
}
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action != GLFW_PRESS)
return;
switch (key)
{
case GLFW_KEY_UP:
{
if (swap_interval + 1 > swap_interval)
set_swap_interval(window, swap_interval + 1);
break;
}
case GLFW_KEY_DOWN:
{
if (swap_tear)
{
if (swap_interval - 1 < swap_interval)
set_swap_interval(window, swap_interval - 1);
}
else
{
if (swap_interval - 1 >= 0)
set_swap_interval(window, swap_interval - 1);
}
break;
}
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, 1);
break;
case GLFW_KEY_F11:
case GLFW_KEY_ENTER:
{
static int x, y, width, height;
if (mods != GLFW_MOD_ALT)
return;
if (glfwGetWindowMonitor(window))
glfwSetWindowMonitor(window, NULL, x, y, width, height, 0);
else
{
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwGetWindowPos(window, &x, &y);
glfwGetWindowSize(window, &width, &height);
glfwSetWindowMonitor(window, monitor,
0, 0, mode->width, mode->height,
mode->refreshRate);
}
break;
}
}
}
int main(int argc, char** argv)
{
unsigned long frame_count = 0;
double last_time, current_time;
GLFWwindow* window;
GLuint vertex_buffer, vertex_shader, fragment_shader, program;
GLint mvp_location, vpos_location;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(640, 480, "Tearing detector", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
set_swap_interval(window, 0);
last_time = glfwGetTime();
frame_rate = 0.0;
swap_tear = (glfwExtensionSupported("WGL_EXT_swap_control_tear") ||
glfwExtensionSupported("GLX_EXT_swap_control_tear"));
glfwSetKeyCallback(window, key_callback);
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
glCompileShader(vertex_shader);
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
glCompileShader(fragment_shader);
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
mvp_location = glGetUniformLocation(program, "MVP");
vpos_location = glGetAttribLocation(program, "vPos");
glEnableVertexAttribArray(vpos_location);
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
sizeof(vertices[0]), (void*) 0);
while (!glfwWindowShouldClose(window))
{
int width, height;
mat4x4 m, p, mvp;
float position = cosf((float) glfwGetTime() * 4.f) * 0.75f;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
mat4x4_ortho(p, -1.f, 1.f, -1.f, 1.f, 0.f, 1.f);
mat4x4_translate(m, position, 0.f, 0.f);
mat4x4_mul(mvp, p, m);
glUseProgram(program);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glfwSwapBuffers(window);
glfwPollEvents();
frame_count++;
current_time = glfwGetTime();
if (current_time - last_time > 1.0)
{
frame_rate = frame_count / (current_time - last_time);
frame_count = 0;
last_time = current_time;
update_window_title(window);
}
}
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,151 +0,0 @@
//========================================================================
// Multi-threading test
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test is intended to verify whether the OpenGL context part of
// the GLFW API is able to be used from multiple threads
//
//========================================================================
#include "tinycthread.h"
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct
{
GLFWwindow* window;
const char* title;
float r, g, b;
thrd_t id;
} Thread;
static volatile int running = GLFW_TRUE;
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
static int thread_main(void* data)
{
const Thread* thread = data;
glfwMakeContextCurrent(thread->window);
glfwSwapInterval(1);
while (running)
{
const float v = (float) fabs(sin(glfwGetTime() * 2.f));
glClearColor(thread->r * v, thread->g * v, thread->b * v, 0.f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(thread->window);
}
glfwMakeContextCurrent(NULL);
return 0;
}
int main(void)
{
int i, result;
Thread threads[] =
{
{ NULL, "Red", 1.f, 0.f, 0.f, 0 },
{ NULL, "Green", 0.f, 1.f, 0.f, 0 },
{ NULL, "Blue", 0.f, 0.f, 1.f, 0 }
};
const int count = sizeof(threads) / sizeof(Thread);
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
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);
if (!threads[i].window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetKeyCallback(threads[i].window, key_callback);
}
glfwMakeContextCurrent(threads[0].window);
gladLoadGL(glfwGetProcAddress);
glfwMakeContextCurrent(NULL);
for (i = 0; i < count; i++)
{
if (thrd_create(&threads[i].id, thread_main, threads + i) !=
thrd_success)
{
fprintf(stderr, "Failed to create secondary thread\n");
glfwTerminate();
exit(EXIT_FAILURE);
}
}
while (running)
{
glfwWaitEvents();
for (i = 0; i < count; i++)
{
if (glfwWindowShouldClose(threads[i].window))
running = GLFW_FALSE;
}
}
for (i = 0; i < count; i++)
glfwHideWindow(threads[i].window);
for (i = 0; i < count; i++)
thrd_join(threads[i].id, &result);
exit(EXIT_SUCCESS);
}

View File

@ -1,99 +0,0 @@
//========================================================================
// Event wait timeout test
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test is intended to verify that waiting for events with timeout works
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <time.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
static float nrand(void)
{
return (float) rand() / (float) RAND_MAX;
}
int main(void)
{
GLFWwindow* window;
srand((unsigned int) time(NULL));
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
window = glfwCreateWindow(640, 480, "Event Wait Timeout Test", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSetKeyCallback(window, key_callback);
while (!glfwWindowShouldClose(window))
{
int width, height;
float r = nrand(), g = nrand(), b = nrand();
float l = (float) sqrt(r * r + g * g + b * b);
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClearColor(r / l, g / l, b / l, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEventsTimeout(1.0);
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}

View File

@ -1,73 +0,0 @@
//========================================================================
// UTF-8 window title test
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test sets a UTF-8 window title
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
int main(void)
{
GLFWwindow* window;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
window = glfwCreateWindow(400, 400, "English 日本語 русский язык 官話", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(1);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
glfwTerminate();
exit(EXIT_SUCCESS);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,428 +0,0 @@
//========================================================================
// Window properties test
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <stdarg.h>
#define NK_IMPLEMENTATION
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_BUTTON_TRIGGER_ON_RELEASE
#include <nuklear.h>
#define NK_GLFW_GL2_IMPLEMENTATION
#include <nuklear_glfw_gl2.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(int argc, char** argv)
{
int windowed_x, windowed_y, windowed_width, windowed_height;
int last_xpos = INT_MIN, last_ypos = INT_MIN;
int last_width = INT_MIN, last_height = INT_MIN;
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[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())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
glfwWindowHint(GLFW_WIN32_KEYBOARD_MENU, GLFW_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
GLFWwindow* window = glfwCreateWindow(600, 600, "Window Features", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(0);
bool position_supported = true;
glfwGetError(NULL);
glfwGetWindowPos(window, &last_xpos, &last_ypos);
sprintf(xpos_buffer, "%i", last_xpos);
sprintf(ypos_buffer, "%i", last_ypos);
if (glfwGetError(NULL) == GLFW_FEATURE_UNAVAILABLE)
position_supported = false;
glfwGetWindowSize(window, &last_width, &last_height);
sprintf(width_buffer, "%i", last_width);
sprintf(height_buffer, "%i", last_height);
sprintf(numer_buffer, "%i", aspect_numer);
sprintf(denom_buffer, "%i", aspect_denom);
sprintf(min_width_buffer, "%i", min_width);
sprintf(min_height_buffer, "%i", min_height);
sprintf(max_width_buffer, "%i", max_width);
sprintf(max_height_buffer, "%i", max_height);
struct nk_context* nk = nk_glfw3_init(window, NK_GLFW3_INSTALL_CALLBACKS);
struct nk_font_atlas* atlas;
nk_glfw3_font_stash_begin(&atlas);
nk_glfw3_font_stash_end();
while (!(may_close && glfwWindowShouldClose(window)))
{
int width, height;
glfwGetWindowSize(window, &width, &height);
struct nk_rect area = nk_rect(0.f, 0.f, (float) width, (float) height);
nk_window_set_bounds(nk, "main", area);
nk_glfw3_new_frame();
if (nk_begin(nk, "main", area, 0))
{
nk_layout_row_dynamic(nk, 30, 5);
if (nk_button_label(nk, "Toggle Fullscreen"))
{
if (glfwGetWindowMonitor(window))
{
glfwSetWindowMonitor(window, NULL,
windowed_x, windowed_y,
windowed_width, windowed_height, 0);
}
else
{
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwGetWindowPos(window, &windowed_x, &windowed_y);
glfwGetWindowSize(window, &windowed_width, &windowed_height);
glfwSetWindowMonitor(window, monitor,
0, 0, mode->width, mode->height,
mode->refreshRate);
}
}
if (nk_button_label(nk, "Maximize"))
glfwMaximizeWindow(window);
if (nk_button_label(nk, "Iconify"))
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);
if (glfwGetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH))
{
nk_label(nk, "Press H to disable mouse passthrough", NK_TEXT_CENTERED);
if (glfwGetKey(window, GLFW_KEY_H))
glfwSetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH, false);
}
nk_label(nk, "Press Enter in a text field to set value", NK_TEXT_CENTERED);
nk_flags events;
const nk_flags flags = NK_EDIT_FIELD |
NK_EDIT_SIG_ENTER |
NK_EDIT_GOTO_END_ON_ACTIVATE;
if (position_supported)
{
int xpos, ypos;
glfwGetWindowPos(window, &xpos, &ypos);
nk_layout_row_dynamic(nk, 30, 3);
nk_label(nk, "Position", NK_TEXT_LEFT);
events = nk_edit_string_zero_terminated(nk, flags, xpos_buffer,
sizeof(xpos_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
xpos = atoi(xpos_buffer);
glfwSetWindowPos(window, xpos, ypos);
}
else if (xpos != last_xpos || (events & NK_EDIT_DEACTIVATED))
sprintf(xpos_buffer, "%i", xpos);
events = nk_edit_string_zero_terminated(nk, flags, ypos_buffer,
sizeof(ypos_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
ypos = atoi(ypos_buffer);
glfwSetWindowPos(window, xpos, ypos);
}
else if (ypos != last_ypos || (events & NK_EDIT_DEACTIVATED))
sprintf(ypos_buffer, "%i", ypos);
last_xpos = xpos;
last_ypos = ypos;
}
else
nk_label(nk, "Position not supported", NK_TEXT_LEFT);
nk_layout_row_dynamic(nk, 30, 3);
nk_label(nk, "Size", NK_TEXT_LEFT);
events = nk_edit_string_zero_terminated(nk, flags, width_buffer,
sizeof(width_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
width = atoi(width_buffer);
glfwSetWindowSize(window, width, height);
}
else if (width != last_width || (events & NK_EDIT_DEACTIVATED))
sprintf(width_buffer, "%i", width);
events = nk_edit_string_zero_terminated(nk, flags, height_buffer,
sizeof(height_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
height = atoi(height_buffer);
glfwSetWindowSize(window, width, height);
}
else if (height != last_height || (events & NK_EDIT_DEACTIVATED))
sprintf(height_buffer, "%i", height);
last_width = width;
last_height = height;
bool update_ratio_limit = false;
if (nk_checkbox_label(nk, "Aspect Ratio", &limit_aspect_ratio))
update_ratio_limit = true;
events = nk_edit_string_zero_terminated(nk, flags, numer_buffer,
sizeof(numer_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
aspect_numer = abs(atoi(numer_buffer));
update_ratio_limit = true;
}
else if (events & NK_EDIT_DEACTIVATED)
sprintf(numer_buffer, "%i", aspect_numer);
events = nk_edit_string_zero_terminated(nk, flags, denom_buffer,
sizeof(denom_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
aspect_denom = abs(atoi(denom_buffer));
update_ratio_limit = true;
}
else if (events & NK_EDIT_DEACTIVATED)
sprintf(denom_buffer, "%i", aspect_denom);
if (update_ratio_limit)
{
if (limit_aspect_ratio)
glfwSetWindowAspectRatio(window, aspect_numer, aspect_denom);
else
glfwSetWindowAspectRatio(window, GLFW_DONT_CARE, GLFW_DONT_CARE);
}
bool update_size_limit = false;
if (nk_checkbox_label(nk, "Minimum Size", &limit_min_size))
update_size_limit = true;
events = nk_edit_string_zero_terminated(nk, flags, min_width_buffer,
sizeof(min_width_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
min_width = abs(atoi(min_width_buffer));
update_size_limit = true;
}
else if (events & NK_EDIT_DEACTIVATED)
sprintf(min_width_buffer, "%i", min_width);
events = nk_edit_string_zero_terminated(nk, flags, min_height_buffer,
sizeof(min_height_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
min_height = abs(atoi(min_height_buffer));
update_size_limit = true;
}
else if (events & NK_EDIT_DEACTIVATED)
sprintf(min_height_buffer, "%i", min_height);
if (nk_checkbox_label(nk, "Maximum Size", &limit_max_size))
update_size_limit = true;
events = nk_edit_string_zero_terminated(nk, flags, max_width_buffer,
sizeof(max_width_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
max_width = abs(atoi(max_width_buffer));
update_size_limit = true;
}
else if (events & NK_EDIT_DEACTIVATED)
sprintf(max_width_buffer, "%i", max_width);
events = nk_edit_string_zero_terminated(nk, flags, max_height_buffer,
sizeof(max_height_buffer),
nk_filter_decimal);
if (events & NK_EDIT_COMMITED)
{
max_height = abs(atoi(max_height_buffer));
update_size_limit = true;
}
else if (events & NK_EDIT_DEACTIVATED)
sprintf(max_height_buffer, "%i", max_height);
if (update_size_limit)
{
glfwSetWindowSizeLimits(window,
limit_min_size ? min_width : GLFW_DONT_CARE,
limit_min_size ? min_height : GLFW_DONT_CARE,
limit_max_size ? max_width : GLFW_DONT_CARE,
limit_max_size ? max_height : GLFW_DONT_CARE);
}
int fb_width, fb_height;
glfwGetFramebufferSize(window, &fb_width, &fb_height);
nk_label(nk, "Framebuffer Size", NK_TEXT_LEFT);
nk_labelf(nk, NK_TEXT_LEFT, "%i", fb_width);
nk_labelf(nk, NK_TEXT_LEFT, "%i", fb_height);
float xscale, yscale;
glfwGetWindowContentScale(window, &xscale, &yscale);
nk_label(nk, "Content Scale", NK_TEXT_LEFT);
nk_labelf(nk, NK_TEXT_LEFT, "%f", xscale);
nk_labelf(nk, NK_TEXT_LEFT, "%f", yscale);
nk_layout_row_begin(nk, NK_DYNAMIC, 30, 5);
int frame_left, frame_top, frame_right, frame_bottom;
glfwGetWindowFrameSize(window, &frame_left, &frame_top, &frame_right, &frame_bottom);
nk_layout_row_push(nk, 1.f / 3.f);
nk_label(nk, "Frame Size:", NK_TEXT_LEFT);
nk_layout_row_push(nk, 1.f / 6.f);
nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_left);
nk_layout_row_push(nk, 1.f / 6.f);
nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_top);
nk_layout_row_push(nk, 1.f / 6.f);
nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_right);
nk_layout_row_push(nk, 1.f / 6.f);
nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_bottom);
nk_layout_row_end(nk);
nk_layout_row_begin(nk, NK_DYNAMIC, 30, 2);
float opacity = glfwGetWindowOpacity(window);
nk_layout_row_push(nk, 1.f / 3.f);
nk_labelf(nk, NK_TEXT_LEFT, "Opacity: %0.3f", opacity);
nk_layout_row_push(nk, 2.f / 3.f);
if (nk_slider_float(nk, 0.f, &opacity, 1.f, 0.001f))
glfwSetWindowOpacity(window, opacity);
nk_layout_row_end(nk);
nk_layout_row_begin(nk, NK_DYNAMIC, 30, 2);
int should_close = glfwWindowShouldClose(window);
nk_layout_row_push(nk, 1.f / 3.f);
if (nk_checkbox_label(nk, "Should Close", &should_close))
glfwSetWindowShouldClose(window, should_close);
nk_layout_row_push(nk, 2.f / 3.f);
nk_checkbox_label(nk, "May Close", &may_close);
nk_layout_row_end(nk);
nk_layout_row_dynamic(nk, 30, 1);
nk_label(nk, "Attributes", NK_TEXT_CENTERED);
nk_layout_row_dynamic(nk, 30, width > 200 ? width / 200 : 1);
int decorated = glfwGetWindowAttrib(window, GLFW_DECORATED);
if (nk_checkbox_label(nk, "Decorated", &decorated))
glfwSetWindowAttrib(window, GLFW_DECORATED, decorated);
int resizable = glfwGetWindowAttrib(window, GLFW_RESIZABLE);
if (nk_checkbox_label(nk, "Resizable", &resizable))
glfwSetWindowAttrib(window, GLFW_RESIZABLE, resizable);
int floating = glfwGetWindowAttrib(window, GLFW_FLOATING);
if (nk_checkbox_label(nk, "Floating", &floating))
glfwSetWindowAttrib(window, GLFW_FLOATING, floating);
int passthrough = glfwGetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH);
if (nk_checkbox_label(nk, "Mouse Passthrough", &passthrough))
glfwSetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH, passthrough);
int auto_iconify = glfwGetWindowAttrib(window, GLFW_AUTO_ICONIFY);
if (nk_checkbox_label(nk, "Auto Iconify", &auto_iconify))
glfwSetWindowAttrib(window, GLFW_AUTO_ICONIFY, auto_iconify);
nk_value_bool(nk, "Focused", glfwGetWindowAttrib(window, GLFW_FOCUSED));
nk_value_bool(nk, "Hovered", glfwGetWindowAttrib(window, GLFW_HOVERED));
nk_value_bool(nk, "Visible", glfwGetWindowAttrib(window, GLFW_VISIBLE));
nk_value_bool(nk, "Iconified", glfwGetWindowAttrib(window, GLFW_ICONIFIED));
nk_value_bool(nk, "Maximized", glfwGetWindowAttrib(window, GLFW_MAXIMIZED));
}
nk_end(nk);
glClear(GL_COLOR_BUFFER_BIT);
nk_glfw3_render(NK_ANTI_ALIASING_ON);
glfwSwapBuffers(window);
glfwWaitEvents();
}
nk_glfw3_shutdown();
glfwTerminate();
exit(EXIT_SUCCESS);
}