Compare commits

...

195 Commits

Author SHA1 Message Date
Camilla Berglund 30306e5470 Fix resolution for reopen test 2015-10-12 21:09:07 +02:00
Aaron Jacobs 755f913b02 Fix invalid types, null pointer use, memory leak
Closes #612.
2015-10-12 21:09:07 +02:00
Camilla Berglund fb6fbcf700 Fix video modes not restored when hiding OS X app 2015-10-12 21:08:59 +02:00
Camilla Berglund adf130965c Update changelog 2015-10-12 19:11:21 +02:00
Camilla Berglund be65829055 Clarify GLU deprecation 2015-10-12 19:05:21 +02:00
Camilla Berglund e0084617d5 Fix monitor disappearing on OS X with AGS
When automatic graphics switching is activated, the CGDirectDisplayID
for the display changes, casuing the primary GLFWmonitor to disappear.
2015-10-12 18:42:18 +02:00
Camilla Berglund 8b2da399ee Add description of 3.1.2 release 2015-10-12 13:59:45 +02:00
Camilla Berglund e163d21f23 Remove stale remark 2015-10-10 22:16:27 +02:00
Camilla Berglund 0d759c8c1a Fix XBufferOverflow handling for XIM input 2015-10-09 14:16:01 +02:00
Camilla Berglund 87ad8c0561 Fix XIM input on non-UTF-8 locales 2015-10-09 13:26:23 +02:00
Camilla Berglund 842aeb8c47 Make Win32 video mode enumeration faster 2015-10-04 13:51:35 +02:00
Camilla Berglund 3dc53e21e5 Cleanup 2015-09-20 15:52:44 +02:00
Camilla Berglund f5cbdbab4f Clarify monitor reference documentation
Related to #594.
2015-09-17 16:37:21 +02:00
Camilla Berglund cf9079c783 Fix documentation typo 2015-09-16 18:51:49 +02:00
Camilla Berglund 0b65053ffd Clarify documentation of glfwGetClipboardString
The reference documentation for glfwGetClipboardString did not link to
GLFW_FORMAT_UNAVAILABLE.

Fixes #605.
2015-09-16 18:25:56 +02:00
Camilla Berglund 7c6a8775eb Fix error type for unavailable pixel format error
All backends reported this as GLFW_PLATFORM_ERROR, while the
documentation mandates GLFW_FORMAT_UNAVAILABLE.
2015-09-16 16:24:21 +02:00
Camilla Berglund 40da56fbf7 Fix grammar 2015-09-09 12:28:03 +02:00
Camilla Berglund c8e068712b Fix glfwGetProcAddress documentation 2015-09-08 21:43:05 +02:00
Camilla Berglund f6f0771770 Replace NSScreen with platform functions 2015-09-07 16:32:10 +02:00
Camilla Berglund 4ad00fa388 Add window refresh events logging to iconify test 2015-09-07 16:32:10 +02:00
Camilla Berglund 4b4cb9ce66 Fix window refresh events emission on OS X 2015-09-07 16:32:10 +02:00
Camilla Berglund 67eadf1e97 Fix glfwIconifyWindow not restoring video mode
Fixes #590.
2015-09-07 16:32:10 +02:00
Camilla Berglund 6123937bde Add missing version string entries 2015-09-01 17:19:09 +02:00
Camilla Berglund da3a77b4e3 Add dynamic client library loading to EGL backend
Fixes #586.
2015-08-27 20:52:10 +02:00
Camilla Berglund 255f9f0234 Fix deadlock with negative swap interval on Aero
Fixes #587.
2015-08-27 20:25:28 +02:00
Camilla Berglund ba4504a9c7 Formatting 2015-08-25 02:26:10 +02:00
Camilla Berglund 7e13a4909e Make all EGL functions dynamically loaded 2015-08-25 02:24:42 +02:00
Camilla Berglund afe4aadade Make all GLX functions dynamically loaded 2015-08-18 17:56:34 +02:00
Camilla Berglund 8db7528ac7 Add support for Cygwin libGL soname 2015-08-18 16:58:32 +02:00
Camilla Berglund 2d39dff84a Replace XkbGetKeyboard with XkbGetMap
Switch to XkbGetMap as XkbGetKeyboard returns NULL on XWayland.

Fixes #389.
2015-08-18 14:27:28 +02:00
Camilla Berglund b69b4a9f2a Remove global symbols for Motif WM hints 2015-08-18 13:34:51 +02:00
Camilla Berglund 85a01bfd9b Document image data being non-premultiplied
Fixes #426.
2015-08-17 21:09:59 +02:00
Camilla Berglund 352a4f2757 Update changelog 2015-08-17 21:09:43 +02:00
Camilla Berglund 41287694cb Replace convertBaseToScreen deprecated in 10.11
Closes #534.
2015-08-17 19:46:24 +02:00
Camilla Berglund 04a439a0a0 Fix function name conflict between source files
Fixes #574.
2015-08-16 15:35:12 +02:00
Camilla Berglund e528a8c7a4 Clarify comment for X11 translateKey 2015-08-16 15:12:13 +02:00
Camilla Berglund 362751e4ef Fix cursor test event mode message 2015-08-16 14:29:04 +02:00
Camilla Berglund 0db3940cc4 Formatting 2015-08-16 14:28:51 +02:00
Camilla Berglund e2bb5e1726 Fix glfwWaitEvents generating events on Win32
Disabled cursor mode caused subsequent glfwWaitEvents calls to return
directly on Win32 due to cursor re-centring emitting WM_MOUSEMOVE.

Fixes #543.
2015-08-16 14:27:54 +02:00
Camilla Berglund 572ac09660 Fix example build errors on VS2013 and earlier
VC++ does not support inline in C mode.

Fixes #581.
2015-08-16 03:24:39 +02:00
Camilla Berglund 9f5a483256 Fix glfwWaitEvents returning prematurely on X11 2015-08-14 13:52:02 +02:00
Camilla Berglund cc752ad6a0 Fix EINTR not being handled for select on X11
Closes #580.
2015-08-14 13:49:52 +02:00
Camilla Berglund ce2ec035f4 Fix TinyCThread time retrieval 2015-08-14 12:42:38 +02:00
Camilla Berglund 20ed0a15a4 Clarify documentation re X11 asynchronicity
Related to #575.
2015-08-12 21:31:54 +02:00
Camilla Berglund a02aeaf972 Fix a maybe-uninitialized warning on GCC 4.9 2015-08-12 18:03:08 +02:00
Camilla Berglund ca8912375c Fix Motif hints being set for X11 full screen
Related to #575.
2015-08-12 18:02:45 +02:00
Camilla Berglund 6b8d490249 Make all client API functions dynamically loaded 2015-08-12 01:01:42 +02:00
Camilla Berglund 84b512c62c Make all WGL functions dynamically loaded 2015-08-12 01:01:37 +02:00
Camilla Berglund 1343ef5915 Replace stray malloc with calloc 2015-08-10 11:13:39 +02:00
Camilla Berglund 65f3bb01be Remove options from gears example 2015-08-09 18:16:58 +02:00
Camilla Berglund 10805cb6ec Add linmath.h to readme dependency list 2015-08-09 16:58:25 +02:00
Camilla Berglund dd01dd7bef Replace GLU with linmath.h in examples 2015-08-09 16:54:19 +02:00
Camilla Berglund 1057bd38cf Add linmath.h 2015-08-09 16:53:46 +02:00
Camilla Berglund fcd6ec99d3 Formatting 2015-08-09 13:58:50 +02:00
Camilla Berglund d2113dc9f5 Remove ad-hoc M_PIs and enable VC++ macro
Fixes #564.
2015-08-09 13:57:04 +02:00
Camilla Berglund 3d62ff0e07 Fix implicit truncation to float in cursor test
Fixes #565.
2015-08-09 13:57:04 +02:00
Camilla Berglund 90adbe0451 Fix no-GLES-on-NSGL error type and description 2015-08-09 13:37:53 +02:00
Camilla Berglund f6defeff5d Remove C++-isms in Mir port
Related to #568.
2015-08-09 13:29:21 +02:00
Camilla Berglund 0a1225d0df Decouple Win32 cursor setting and tracking 2015-08-09 13:26:41 +02:00
Camilla Berglund 527952102a Fixed filtering of events duplicated by XIM.
Duplicate events cannot be filtered by the return value of XFilterEvent,
as that discards dead key events on some IMs (ibus), nor by its inverse,
as that discards all key events on other IMs (?).  This solution is
based on the workaround in SDL2 and takes advantage of the identical
time of the duplicate events.

Fixes #548.
Closes #554.
Closes #571.
2015-08-07 16:53:43 +02:00
Camilla Berglund 8a4e939a10 Fix glext.h regression in glfwinfo on OS X
The glfwinfo program uses symbols not provided by the glext.h header in
every development environment.

Closes #572.
2015-08-07 16:31:05 +02:00
Camilla Berglund f8395886d3 Formatting 2015-07-30 20:36:03 +02:00
Brandon Schaefer 9527c93a1c Move to the new MirEvent 2.0 + 0.14/0.15 changes
Closes #568.
2015-07-30 20:35:55 +02:00
Camilla Berglund 37e13361f5 Fixed last manual inclusion of glext.h. 2015-07-28 14:51:36 +02:00
Yaron Cohen-Tal bb6db74167 Fixed finding of PowerVR SDK libraries.
Closes #560.
2015-07-28 14:14:31 +02:00
Camilla Berglund 1f95fac699 Extension string type cleanup. 2015-07-28 14:12:16 +02:00
Camilla Berglund 24e4e674a5 Enabled MSAA for splitview example. 2015-07-27 12:42:16 +02:00
Camilla Berglund 460e5d792d Fixed splitview example on Retina displays. 2015-07-21 21:58:24 +02:00
Camilla Berglund 02d821c0ab Updated changelog. 2015-07-21 17:47:08 +02:00
Camilla Berglund d12b34388d Added reference to CMake Info.plist template. 2015-07-21 17:42:01 +02:00
Camilla Berglund e686f5a249 Fixed AppKit not initialized for cursor creation. 2015-07-21 17:22:21 +02:00
Camilla Berglund 33c7c28dde Replaced the various cursor tests with a sane one. 2015-07-16 17:48:59 +02:00
Camilla Berglund 04c057238b Added support for EXT_framebuffer_sRGB.
Added sRGB extensions to standards conformance page.
2015-07-16 17:48:00 +02:00
Camilla Berglund bfe55118dd Fixed name of Win32 cursor tracking flag. 2015-07-14 15:45:22 +02:00
Camilla Berglund f825af06f0 Formatting. 2015-07-14 15:45:22 +02:00
Camilla Berglund 2205bdd469 Improved X11 display opening failure. 2015-07-06 14:38:00 +02:00
Camilla Berglund 0f3b69c79d Fixed missing utility function return types.
Fixes #546.
2015-07-05 01:13:52 +02:00
Camilla Berglund cf10e318d6 Formatting. 2015-07-01 14:58:43 +02:00
Camilla Berglund 1ab9dbab60 Removed test replaced by glfwinfo. 2015-07-01 14:50:46 +02:00
Camilla Berglund 4f0fc55385 Added version option to glfwinfo. 2015-07-01 14:48:20 +02:00
Camilla Berglund 23195693ed Added glfwinfo options for context and fb hints. 2015-07-01 14:45:48 +02:00
Camilla Berglund a7fa41612c Fixed printing of GLFW version on usage and error. 2015-07-01 14:15:12 +02:00
Camilla Berglund 5f91ea34de Made glfwinfo options set hints directly. 2015-07-01 14:14:51 +02:00
Camilla Berglund ea9c186e36 Updated changelog. 2015-06-26 16:20:20 +02:00
Camilla Berglund a97477337d Updated changelog and credits, formatting.
Fixes #17.
Closes #536.
2015-06-26 13:41:27 +02:00
Aaron Jacobs fec6f187d1 Do not recurse over IOHIDElement children. 2015-06-26 13:07:49 +02:00
Aaron Jacobs 1a96c294ee Add support for joystick hot swapping on OS X. 2015-06-26 13:07:39 +02:00
Camilla Berglund 19a28e2c9f Fixed X11 arrow cursor image.
Fixes #541.
2015-06-25 12:59:51 +02:00
Camilla Berglund 1984d40e33 Formatting. 2015-06-25 01:23:23 +02:00
Camilla Berglund cf4206d987 Fixed duplicate key presses caused by XIM.
Probably.
2015-06-25 00:43:12 +02:00
Camilla Berglund cc4c232956 Renamed cursor window library struct member.
Since _glfwPlatformWindowFocused it has a more limited role.
2015-06-17 12:06:45 +02:00
Camilla Berglund 226f85efcb Key translation tables are now in _glfw. 2015-06-16 22:26:30 +02:00
Camilla Berglund 2aa8e17c88 Cleanup. 2015-06-16 22:16:36 +02:00
Camilla Berglund 3365139a6c Cleanup. 2015-06-16 12:10:20 +02:00
Camilla Berglund 2cc3c16ab1 Documentation tweak. 2015-06-15 20:40:15 +02:00
Camilla Berglund 3a0b397054 Fixed regression for WGL full screen DWM hack.
The DwmFlush workaround for windowed windows on Nvidia caused jitter for
full screen windows.  The workaround is now only used for windowed mode
windows.

Fixes #519.
2015-06-15 20:19:49 +02:00
Camilla Berglund b15eaeda16 Implemented auto-iconification on X11.
Fixes #531.
2015-06-15 18:46:45 +02:00
Camilla Berglund e049190ff1 Moved focus callback triggering last. 2015-06-15 18:46:45 +02:00
Camilla Berglund dba59cf903 Improved X11 focus event filtering.
Some focus events need to be ignored to allow functionality like
Alt+Tab and volume indicators to not affect application-visible window
focus.  However, the previous filtering was too broad and missed virtual
desktop switching, Alt+Tab and programmatic iconification.

Fixes #405.
2015-06-15 18:44:54 +02:00
Camilla Berglund 56122cbe2f Keep X11 full screen window properties on iconify. 2015-06-15 15:32:35 +02:00
Camilla Berglund c77edaee34 Always pre-position X11 full screen windows. 2015-06-15 15:32:35 +02:00
Camilla Berglund 21ce21cc07 Improved X11 full screen focus control flow. 2015-06-15 15:32:16 +02:00
Camilla Berglund 6cf15615e8 Clarified EWMH full screen error messages. 2015-06-15 14:39:56 +02:00
Camilla Berglund a1399426c3 Removed superfluous X11 window struct member. 2015-06-15 14:38:13 +02:00
Camilla Berglund 81249724e3 Removed retrieval of unused values. 2015-06-15 14:36:32 +02:00
Camilla Berglund bdcffa90eb Remove superfluous X11 library struct member. 2015-06-15 14:28:13 +02:00
Camilla Berglund 1ee4c4ba62 Clarified control flow in X11 event processing. 2015-06-15 14:24:27 +02:00
Camilla Berglund 7935a366f4 Fixed particles example on Retina displays. 2015-06-12 03:13:36 +02:00
Camilla Berglund 08b3af4387 Fixed non-pre-edit character input via XIM.
Fixes #501.
Fixes #473.
2015-06-09 21:10:01 +02:00
Camilla Berglund 8e96402819 Formatting. 2015-06-09 21:04:58 +02:00
Camilla Berglund 1c104a385d Clarified note on role of CMake. 2015-06-09 21:04:49 +02:00
Camilla Berglund ec6f0811a0 Improved initial placement of full screen windows. 2015-06-08 16:14:51 +02:00
Camilla Berglund a257e7a3ee Removed caching of Win32 window styles. 2015-06-08 16:10:07 +02:00
Camilla Berglund acaddf9cd9 Added decimals to DPI reported by monitor test. 2015-06-07 21:34:54 +02:00
Camilla Berglund bb50368d55 Fixed enumeration of invalid video modes.
Fixes #350.
2015-06-07 21:34:46 +02:00
Camilla Berglund 8503d53018 Improved tearing test.
Added support for arbitrary swap intervals, including negative ones if
(GLX|WGL)_EXT_swap_control_tear is available.
2015-06-07 20:54:25 +02:00
Camilla Berglund 8d4ba0aa83 Improved multi-window test.
Fixed proper Windows colors.  Added support for Escape key.  Made
windows undecorated.  Added command-line option for decorated windows.
2015-06-07 20:47:13 +02:00
Camilla Berglund 5abf7841f8 Improved glfwinfo tool.
Added long options to glfwinfo.  Cleaned up code.
2015-06-07 20:40:25 +02:00
Camilla Berglund ff67e06844 Added prefixes to header guard macros. 2015-06-07 19:32:24 +02:00
Camilla Berglund 5f74c2afdf Cleanup. 2015-06-07 18:27:37 +02:00
Camilla Berglund 96b3f17d02 Re-used config structs for hints. 2015-06-07 18:14:07 +02:00
Camilla Berglund 58c2c10cdb Moved helper functions to correct section. 2015-06-07 13:24:09 +02:00
Camilla Berglund e6cc3c4752 Clarified WM_PROTOCOLS event handling. 2015-06-02 17:54:25 +02:00
Camilla Berglund 9f0e359d73 Formatting. 2015-06-02 17:27:35 +02:00
Camilla Berglund 82c5dfc30a Formatting. 2015-06-02 17:26:23 +02:00
Camilla Berglund ee2d036bbf Fixed destination of _NET_WM_PING reply. 2015-06-02 17:25:09 +02:00
Camilla Berglund cf363103d2 Formatting. 2015-06-02 17:10:22 +02:00
Camilla Berglund 41af5aaae2 Simplified sending events to WM. 2015-06-02 17:09:38 +02:00
Camilla Berglund f0212f3f15 Fixed typo in function declaration. 2015-06-02 13:51:24 +02:00
Camilla Berglund 81144bb969 Corrected changelog verb. 2015-06-02 03:32:30 +02:00
Camilla Berglund b00a7d0619 Simplified version string functions. 2015-06-02 03:32:29 +02:00
Camilla Berglund ef6dec17ba Added missing entries to Linux version strings. 2015-06-02 03:32:28 +02:00
Camilla Berglund b067bb6304 Removed swap interval re-application hack.
This approach is not compatible with multi-threading.
2015-06-02 03:32:27 +02:00
Camilla Berglund ed18c145cd Fixed section for changelog entry. 2015-06-02 03:32:27 +02:00
Camilla Berglund 8247e6069d Fixed mode setting for tearing test. 2015-06-02 03:26:02 +02:00
Camilla Berglund 38ca109766 Clarified context TLS function names. 2015-06-01 04:00:55 +02:00
Camilla Berglund 6d5753c548 Added support for AMD PowerXpress override.
Generalized _GLFW_USE_OPTIMUS_HPG to _GLFW_USE_HYBRID_HPG to reflect the
change.

Fixes #520.
2015-05-29 13:15:32 +02:00
Camilla Berglund 0fa909a889 Updated .gitignore. 2015-05-28 18:55:14 +02:00
Camilla Berglund 38ae319bea Header inclusion cleanup. 2015-05-28 01:52:22 +02:00
Camilla Berglund 287e30239c Renamed extension version struct members. 2015-05-28 01:52:22 +02:00
Camilla Berglund 530fc5a431 Added full screen support to tearing test. 2015-05-27 16:14:15 +02:00
Camilla Berglund d3e25db395 Added missing documentation for option. 2015-05-27 02:22:56 +02:00
Camilla Berglund f3cd42887d Fixed changelog section for WGL entries. 2015-05-27 02:22:01 +02:00
Camilla Berglund 3c52cb1790 Simplified glXGetProcAddress logic.
Removed compile-time selection of GLX entry point retrieval mechanism.
Made dlopen a required dependency.

This is a stopgap solution until we start requiring GLX 1.4.
2015-05-27 02:20:55 +02:00
Camilla Berglund 8309e0ecb0 Use DwmFlush when DWM is enabled.
Use DwmFlush instead of WGL_EXT_swap_control when desktop compositing is
enabled, to avoid the jitter of DWM and WGL vsync fighting.

Fixes #516.
2015-05-21 18:28:53 +02:00
Camilla Berglund 22e9451192 Fixed accuracy test on Retina displays. 2015-05-21 00:43:52 +02:00
Camilla Berglund a1641cdec9 Renamed MSAA test program. 2015-05-19 15:27:58 +02:00
Camilla Berglund 8f0fd7ecf5 Reverted to plain NSView.
Fixes #500.
Fixes #443.
Closes #504.
Closes #510.
2015-05-18 22:55:38 +02:00
Camilla Berglund c7f564e866 Stop making it worse. 2015-05-14 17:14:30 +02:00
Camilla Berglund c9ae3f4efe Fixed build regression.
Fixes regression caused by 5f7f6319eb.
2015-05-14 17:00:03 +02:00
Camilla Berglund 6d0698ba0e Updated changelog. 2015-05-14 16:29:54 +02:00
Camilla Berglund 155da0cd09 Unified librt and libm logic. 2015-05-14 16:15:50 +02:00
Camilla Berglund b4f3adb6ee Removed no-op librt illogic. 2015-05-14 16:11:18 +02:00
Camilla Berglund 6b232bd8f6 Updated minimum required CMake version to 2.8.12.
All major package systems seem to have caught up.
2015-05-14 15:59:53 +02:00
Camilla Berglund 323d4a484d Simplified libdl logic. 2015-05-13 16:33:29 +02:00
Camilla Berglund 6af25fb423 MinGW flag logic cleanup. 2015-05-13 16:33:29 +02:00
Nicholas Vitovitch 35b6c72634 Simplifies CMake version checks. 2015-05-13 16:33:29 +02:00
Camilla Berglund 5f7f6319eb Made global setting of CMake module path explicit. 2015-05-13 16:14:01 +02:00
Camilla Berglund 47592fbf42 Cleaned up example build file. 2015-05-13 16:01:42 +02:00
Camilla Berglund 80a38c1e45 Updated Info.plist template file. 2015-05-13 15:59:09 +02:00
Jay Weisskopf c599ea0737 Fix typo: "is" changed to "are"
Fixes #512.
2015-05-13 00:18:12 +02:00
Camilla Berglund 9040c64e5b Implemented GLFW_AUTO_ICONIFY on OS X.
Fixes #506.
2015-05-06 23:53:52 +02:00
Camilla Berglund 905073a506 Simplified WGL extension logic.
Not applying this to GLX or EGL yet because Mesa.
2015-05-04 19:31:33 +02:00
Emmanuel Gil Peyrot 656666e722 wayland: Fix typo introduced in e253beaa.
Closes #502.
2015-04-20 22:34:30 +02:00
Camilla Berglund 460c34df4b Documentation tweaks. 2015-04-19 13:50:13 +02:00
Camilla Berglund d1ea1ec21b Added credit. 2015-04-19 13:27:44 +02:00
Emmanuel Gil Peyrot e253beaa2b wayland: Implement glfwGetCursorPos
Closes #499.
2015-04-19 13:27:43 +02:00
Camilla Berglund 9021e52a6f Fixed clipboard test OS X modifier. 2015-04-16 18:34:32 +02:00
Camilla Berglund 5b6e67119f Added credit. 2015-04-14 21:15:50 +02:00
Eric Larson ad1739c63f Fixed invalid pointer when Xrandr is unavailable.
Fixes #497.
Closes #498.
2015-04-14 21:11:27 +02:00
Camilla Berglund b415b9aacf Fixed harmless argument reversal. 2015-04-14 19:05:58 +02:00
Camilla Berglund dc9d287e33 Comment cleanup. 2015-04-14 18:32:54 +02:00
Camilla Berglund 135be952fe Added reporting of unlikely WGL extension error. 2015-04-14 18:32:53 +02:00
Camilla Berglund c21a8573b4 Replaced comment with assertion. 2015-04-14 18:32:53 +02:00
Camilla Berglund 5733b0e4cb Removed repetitition in input guide.
Fixes #496.
2015-04-10 13:31:54 +02:00
Camilla Berglund 5c3f8efd23 Context config translation cleanup. 2015-04-10 13:18:26 +02:00
Camilla Berglund 076d9311fa Removed tab characters. 2015-04-10 13:17:27 +02:00
Camilla Berglund c5099ff407 Cleanup of #493. 2015-04-09 17:59:37 +02:00
Chi-kwan Chan 4277e9f5d6 Removed NSScreen member of OS X monitor.
Apple's documentation of [NSScreen screens] mentions that, "The
(screens) array should not be cached.  Screens can be added, removed,
or dynamically reconfigured at any time."  Because of this, we simply
obtain the screen from a displayID whenever we need it.

Fixes #492.
Closes #493.
2015-04-09 17:59:37 +02:00
Camilla Berglund 882b770ecb Cleanup of #487. 2015-04-09 17:59:37 +02:00
Elviss Strazdins a21f586c3b Removed check for whether context is current.
The GLFW TLS slot will be out of sync if an outside source makes another
context current.

Fixes #487.
2015-04-09 17:59:37 +02:00
Camilla Berglund 2fbd948a67 Fixed initialization failing on headless systems.
Fixes #482.
2015-04-09 17:59:37 +02:00
Camilla Berglund 49cf82a0ac Cleaned up monitor and video mode enumeration. 2015-04-09 17:40:27 +02:00
Camilla Berglund 6412dcb896 Added note on delayed OS X window title updating.
Fixes #495.
2015-04-07 22:19:57 +02:00
Camilla Berglund 16e80258b8 Shrunk error message buffer.
This fixes a VC++ static analysis warning.
2015-04-07 22:19:57 +02:00
Camilla Berglund b875bbcdf1 Added missing VC++ gitignore entries. 2015-04-07 22:19:56 +02:00
Camilla Berglund 6b21c4f6c9 Fixed out-of-tree build documentation.
Fixes #489.
2015-04-07 22:19:56 +02:00
Camilla Berglund e8bceaa284 Documentation work. 2015-04-07 22:19:55 +02:00
Camilla Berglund 59abeeb097 Added window attribute remarks.
Fixes #485.
Related to #476.
2015-04-07 22:19:55 +02:00
Camilla Berglund d95b79f9eb Documentation grammar fix. 2015-04-07 22:19:54 +02:00
Camilla Berglund 1861cf4975 Removed stale comment. 2015-04-07 02:29:49 +02:00
Camilla Berglund 427c79b24b Documented framebuffer attribute retrieval.
Related to #476.
2015-03-30 21:53:47 +02:00
Camilla Berglund f3270d4ce8 Fixed language referring to GLFW 2.
Fixes #476.
2015-03-26 12:42:30 +01:00
Emmanuel Gil Peyrot 4974585d04 wayland: Handle disconnect properly
Merge code for PollEvents and WaitEvents, and handle disconnect properly.
2015-03-26 15:12:49 +08:00
Camilla Berglund 5268914b3f Started 3.1.2. 2015-03-20 00:16:24 +01:00
83 changed files with 3934 additions and 3033 deletions
+6 -5
View File
@@ -3,12 +3,16 @@
_ReSharper*
*.opensdf
*.sdf
*.suo
*.dir
*.vcxproj*
*.sln
Win32
x64
Debug
Release
MinSizeRel
RelWithDebInfo
# CMake files
Makefile
@@ -21,6 +25,7 @@ cmake_uninstall.cmake
docs/Doxyfile
docs/html
docs/warnings.txt
docs/doxygen_sqlite3.db
src/glfw_config.h
src/glfw3.pc
src/glfw3Config.cmake
@@ -50,20 +55,16 @@ examples/simple
examples/wave
tests/*.app
tests/*.exe
tests/accuracy
tests/clipboard
tests/cursor
tests/cursoranim
tests/defaults
tests/empty
tests/events
tests/fsaa
tests/gamma
tests/glfwinfo
tests/iconify
tests/joysticks
tests/monitors
tests/peter
tests/msaa
tests/reopen
tests/sharing
tests/tearing
@@ -5,34 +5,34 @@
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${APPLE_GUI_EXECUTABLE}</string>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleGetInfoString</key>
<string>${APPLE_GUI_INFO_STRING}</string>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleIconFile</key>
<string>${APPLE_GUI_ICON}</string>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleIdentifier</key>
<string>${APPLE_GUI_IDENTIFIER}</string>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string>${APPLE_GUI_LONG_VERSION_STRING}</string>
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
<key>CFBundleName</key>
<string>${APPLE_GUI_BUNDLE_NAME}</string>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${APPLE_GUI_SHORT_VERSION_STRING}</string>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${APPLE_GUI_BUNDLE_VERSION}</string>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>LSRequiresCarbon</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>${APPLE_GUI_COPYRIGHT}</string>
<key>NSHighResolutionCapable</key>
<true/>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>
+1 -1
View File
@@ -6,7 +6,7 @@
find_path(EGL_INCLUDE_DIR NAMES EGL/egl.h PATHS /opt/vc/include)
set(EGL_NAMES ${EGL_NAMES} egl EGL)
set(EGL_NAMES ${EGL_NAMES} egl EGL libEGL)
find_library(EGL_LIBRARY NAMES ${EGL_NAMES} PATHS /opt/vc/lib)
include(FindPackageHandleStandardArgs)
+1 -1
View File
@@ -6,7 +6,7 @@
find_path(GLESv1_INCLUDE_DIR NAMES GLES/gl.h PATHS /opt/vc/include)
set(GLESv1_NAMES ${GLESv1_NAMES} GLESv1_CM)
set(GLESv1_NAMES ${GLESv1_NAMES} GLESv1_CM libGLES_CM)
find_library(GLESv1_LIBRARY NAMES ${GLESv1_NAMES} PATHS /opt/vc/lib)
include(FindPackageHandleStandardArgs)
+1 -1
View File
@@ -6,7 +6,7 @@
find_path(GLESv2_INCLUDE_DIR NAMES GLES2/gl2.h PATHS /opt/vc/include)
set(GLESv2_NAMES ${GLESv2_NAMES} GLESv2)
set(GLESv2_NAMES ${GLESv2_NAMES} GLESv2 libGLESv2)
find_library(GLESv2_LIBRARY NAMES ${GLESv2_NAMES} PATHS /opt/vc/lib)
include(FindPackageHandleStandardArgs)
+41 -76
View File
@@ -1,8 +1,8 @@
project(GLFW C)
cmake_minimum_required(VERSION 2.8.9)
cmake_minimum_required(VERSION 2.8.12)
if (CMAKE_VERSION VERSION_EQUAL "3.0" OR CMAKE_VERSION VERSION_GREATER "3.0")
if (NOT CMAKE_VERSION VERSION_LESS "3.0")
# Until all major package systems have moved to CMake 3,
# we stick with the older INSTALL_NAME_DIR mechanism
cmake_policy(SET CMP0042 OLD)
@@ -10,7 +10,7 @@ endif()
set(GLFW_VERSION_MAJOR "3")
set(GLFW_VERSION_MINOR "1")
set(GLFW_VERSION_PATCH "1")
set(GLFW_VERSION_PATCH "2")
set(GLFW_VERSION_EXTRA "")
set(GLFW_VERSION "${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}")
set(GLFW_VERSION_FULL "${GLFW_VERSION}.${GLFW_VERSION_PATCH}${GLFW_VERSION_EXTRA}")
@@ -26,8 +26,7 @@ option(GLFW_INSTALL "Generate installation target" ON)
option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF)
if (WIN32)
option(GLFW_USE_DWM_SWAP_INTERVAL "Set swap interval even when DWM compositing is enabled" OFF)
option(GLFW_USE_OPTIMUS_HPG "Force use of high-performance GPU on Optimus systems" OFF)
option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF)
endif()
if (APPLE)
@@ -58,6 +57,8 @@ elseif (GLFW_USE_MIR)
set(GLFW_USE_EGL ON)
endif()
set(CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules")
if (GLFW_USE_EGL)
set(GLFW_CLIENT_LIBRARY "opengl" CACHE STRING
"The client library to use; one of opengl, glesv1 or glesv2")
@@ -72,7 +73,6 @@ if (GLFW_USE_EGL)
message(FATAL_ERROR "Unsupported client library")
endif()
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMake/modules")
find_package(EGL REQUIRED)
if (NOT _GLFW_USE_OPENGL)
@@ -137,7 +137,6 @@ endif()
if (MINGW)
# Enable link-time exploit mitigation features enabled by default on MSVC
include(CheckCCompilerFlag)
# Compatibility with data execution prevention (DEP)
@@ -160,6 +159,12 @@ if (MINGW)
if (_GLFW_HAS_64ASLR)
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--high-entropy-va ${CMAKE_SHARED_LINKER_FLAGS}")
endif()
# HACK: When building on MinGW, WINVER and UNICODE need to be defined before
# the inclusion of stddef.h (by glfw3.h), which is itself included before
# win32_platform.h. We define them here until a saner solution can be found
# NOTE: MinGW-w64 and Visual C++ do /not/ need this hack.
add_definitions(-DUNICODE -DWINVER=0x0501)
endif()
#--------------------------------------------------------------------
@@ -204,6 +209,25 @@ else()
message(FATAL_ERROR "No supported platform was detected")
endif()
#--------------------------------------------------------------------
# Find and add Unix math and time libraries
#--------------------------------------------------------------------
if (UNIX AND NOT APPLE)
find_library(RT_LIBRARY rt)
mark_as_advanced(RT_LIBRARY)
if (RT_LIBRARY)
list(APPEND glfw_LIBRARIES "${RT_LIBRARY}")
list(APPEND glfw_PKG_LIBS "-lrt")
endif()
find_library(MATH_LIBRARY m)
mark_as_advanced(MATH_LIBRARY)
if (MATH_LIBRARY)
list(APPEND glfw_LIBRARIES "${MATH_LIBRARY}")
list(APPEND glfw_PKG_LIBS "-lm")
endif()
endif()
#--------------------------------------------------------------------
# Use Win32 for window creation
#--------------------------------------------------------------------
@@ -211,19 +235,8 @@ if (_GLFW_WIN32)
list(APPEND glfw_PKG_LIBS "-lgdi32")
if (GLFW_USE_DWM_SWAP_INTERVAL)
set(_GLFW_USE_DWM_SWAP_INTERVAL 1)
endif()
if (GLFW_USE_OPTIMUS_HPG)
set(_GLFW_USE_OPTIMUS_HPG 1)
endif()
# HACK: When building on MinGW, WINVER and UNICODE need to be defined before
# the inclusion of stddef.h (by glfw3.h), which is itself included before
# win32_platform.h. We define them here until a saner solution can be found
# NOTE: MinGW-w64 and Visual C++ do /not/ need this hack.
if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU")
add_definitions(-DUNICODE -DWINVER=0x0501)
if (GLFW_USE_HYBRID_HPG)
set(_GLFW_USE_HYBRID_HPG 1)
endif()
endif()
@@ -250,9 +263,6 @@ if (_GLFW_X11)
# Set up library and include paths
list(APPEND glfw_INCLUDE_DIRS "${X11_X11_INCLUDE_PATH}")
list(APPEND glfw_LIBRARIES "${X11_X11_LIB}" "${CMAKE_THREAD_LIBS_INIT}")
if (UNIX AND NOT APPLE)
list(APPEND glfw_LIBRARIES "${RT_LIBRARY}")
endif()
# Check for XRandR (modern resolution switching and gamma control)
if (NOT X11_Xrandr_FOUND)
@@ -309,20 +319,6 @@ if (_GLFW_X11)
list(APPEND glfw_INCLUDE_DIR "${X11_Xkb_INCLUDE_PATH}")
find_library(RT_LIBRARY rt)
mark_as_advanced(RT_LIBRARY)
if (RT_LIBRARY)
list(APPEND glfw_LIBRARIES "${RT_LIBRARY}")
list(APPEND glfw_PKG_LIBS "-lrt")
endif()
find_library(MATH_LIBRARY m)
mark_as_advanced(MATH_LIBRARY)
if (MATH_LIBRARY)
list(APPEND glfw_LIBRARIES "${MATH_LIBRARY}")
list(APPEND glfw_PKG_LIBS "-lm")
endif()
# Check for Xcursor
if (NOT X11_Xcursor_FOUND)
message(FATAL_ERROR "The Xcursor libraries and headers were not found")
@@ -348,13 +344,6 @@ if (_GLFW_WAYLAND)
list(APPEND glfw_PKG_DEPS "xkbcommon")
list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
find_library(MATH_LIBRARY m)
mark_as_advanced(MATH_LIBRARY)
if (MATH_LIBRARY)
list(APPEND glfw_LIBRARIES "${MATH_LIBRARY}")
list(APPEND glfw_PKG_LIBS "-lm")
endif()
endif()
#--------------------------------------------------------------------
@@ -371,13 +360,6 @@ if (_GLFW_MIR)
list(APPEND glfw_PKG_DEPS "xkbcommon")
list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
find_library(MATH_LIBRARY m)
mark_as_advanced(MATH_LIBRARY)
if (MATH_LIBRARY)
list(APPEND glfw_LIBRARIES "${MATH_LIBRARY}")
list(APPEND glfw_PKG_LIBS "-lm")
endif()
endif()
#--------------------------------------------------------------------
@@ -390,32 +372,10 @@ if (_GLFW_GLX)
list(APPEND glfw_PKG_DEPS "gl")
include(CheckFunctionExists)
set(CMAKE_REQUIRED_LIBRARIES "${OPENGL_gl_LIBRARY}")
check_function_exists(glXGetProcAddress _GLFW_HAS_GLXGETPROCADDRESS)
check_function_exists(glXGetProcAddressARB _GLFW_HAS_GLXGETPROCADDRESSARB)
check_function_exists(glXGetProcAddressEXT _GLFW_HAS_GLXGETPROCADDRESSEXT)
if (NOT _GLFW_HAS_GLXGETPROCADDRESS AND
NOT _GLFW_HAS_GLXGETPROCADDRESSARB AND
NOT _GLFW_HAS_GLXGETPROCADDRESSEXT)
message(WARNING "No glXGetProcAddressXXX variant found")
# Check for dlopen support as a fallback
set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_DL_LIBS}")
check_function_exists(dlopen _GLFW_HAS_DLOPEN)
if (NOT _GLFW_HAS_DLOPEN)
message(FATAL_ERROR "No entry point retrieval mechanism found")
endif()
if (CMAKE_DL_LIBS)
list(APPEND glfw_LIBRARIES "${CMAKE_DL_LIBS}")
list(APPEND glfw_PKG_LIBS "-l${CMAKE_DL_LIBS}")
endif()
if (CMAKE_DL_LIBS)
list(APPEND glfw_LIBRARIES "${CMAKE_DL_LIBS}")
list(APPEND glfw_PKG_LIBS "-l${CMAKE_DL_LIBS}")
endif()
endif()
#--------------------------------------------------------------------
@@ -442,6 +402,11 @@ if (_GLFW_EGL)
list(APPEND glfw_PKG_DEPS "glesv2")
endif()
if (CMAKE_DL_LIBS)
list(APPEND glfw_LIBRARIES "${CMAKE_DL_LIBS}")
list(APPEND glfw_PKG_LIBS "-l${CMAKE_DL_LIBS}")
endif()
endif()
#--------------------------------------------------------------------
+69 -25
View File
@@ -6,8 +6,9 @@ GLFW is a free, Open Source, multi-platform library for OpenGL and OpenGL ES
application development. It provides a simple, platform-independent API for
creating windows and contexts, reading input, handling events, etc.
Version 3.1.1 adds fixes for a number of bugs that together affect all supported
platforms, most notably workarounds for bugs in some popular window managers.
Version 3.1.2 adds fixes for a large number of bugs that together affect all
supported platforms, as well as dynamic loading work that simplifies compilation
and linking.
If you are new to GLFW, you may find the
[introductory tutorial](http://www.glfw.org/docs/latest/quick.html) for GLFW
@@ -59,30 +60,69 @@ GLFW bundles a number of dependencies in the `deps/` directory.
examples
- An OpenGL 3.2 core loader generated by
[glad](https://github.com/Dav1dde/glad) for examples using modern OpenGL
- [linmath.h](https://github.com/datenwolf/linmath.h) for linear algebra in
examples
## Changelog
- Made library compilation fail if any header option macros are defined
- Removed support for LCC and Borland C++
- Bugfix: `glfwSetTime` silently accepted invalid values
- [Cocoa] Bugfix: `NSHighResolutionCapable` was not enabled for test and
example programs
- [Cocoa] Bugfix: Sleeping monitors were not included in the monitor list
- [Cocoa] Bugfix: `glfwSetWindowSize` did not change the video mode for full
screen windows
- [X11] Added support for Cygwin-X
- [X11] Made XInput2 optional at compile-time
- [X11] Made Xxf86vm optional at compile-time
- [X11] Bugfix: Moved `_NET_REQUEST_FRAME_EXTENTS` request to
`glfwGetWindowFrameSize` and added protocol-breaking timeout
as a workaround for broken support in Unity, Fluxbox and Xfwm
- [X11] Bugfix: Mouse button `GLFW_MOUSE_BUTTON_4` was never used
- [X11] Bugfix: `glfwTerminate` could close an unrelated file descriptor
- [X11] Bugfix: Some WMs (KWM, Fluxbox) did not respect cursor redefinition
- [WGL] Bugfix: The context flags debug bit was not set for OpenGL ES
- [GLX] Bugfix: The context flags debug bit was not set for OpenGL ES
- [EGL] Bugfix: The context flags debug bit was not set for OpenGL ES
- Made all client API functions dynamically loaded
- Changed minimum required CMake version to 2.8.12
- Replaced GLU with [linmath.h](https://github.com/datenwolf/linmath.h) in
example programs
- Merged all cursor test programs into the `cursor` program
- Removed all mention of GLU in examples, build files and package dependencies
- Bugfix: Initialization failed on headless systems
- Bugfix: The cached current context could get out of sync
- Bugfix: `glfwIconifyWindow` did not restore the original video mode for full
screen windows created with `GLFW_AUTO_ICONIFY`
- [Win32] Renamed hybrid GPU override compile-time option to
`_GLFW_USE_HYBRID_HPG` and added support for AMD PowerXpress systems
- [Win32] Bugfix: `glfwGetVideoModes` included unusable modes on some systems
- [Win32] Bugfix: `glfwWaitEvents` would return directly for focused windows in
disabled cursor mode
- [Cocoa] Bugfix: The cached `NSScreen` for a monitor could get out of sync
- [Cocoa] Bugfix: The `GLFW_AUTO_ICONIFY` window hint was ignored
- [Cocoa] Bugfix: Resizing a window to its minimum size would segfault
- [Cocoa] Bugfix: Creating or showing a window would make its context current
- [Cocoa] Bugfix: Joysticks connected after `glfwInit` were not detected
- [Cocoa] Bugfix: Cursor creation failed unless a window had been created.
- [Cocoa] Bugfix: Window refresh events were not generated by iconification or
restoration
- [Cocoa] Bugfix: The primary monitor would get reported as disconnected when
entering full screen on a dual-GPU machine with automatic
graphics switching
- [Cocoa] Bugfix: The original video modes were not restored when the
application was hidden
- [X11] Bugfix: `glfwInit` would segfault on systems without RandR
- [X11] Bugfix: The response to `_NET_WM_PING` was sent to the wrong window
- [X11] Bugfix: Character input via XIM did not work in many cases
- [X11] Bugfix: No fallback existed for missing `_NET_ACTIVE_WINDOW` support
- [X11] Bugfix: Some significant window focus events were ignored
- [X11] Bugfix: The `GLFW_AUTO_ICONIFY` window hint was ignored
- [X11] Bugfix: The original video mode was not restored on iconification of
full screen windows
- [X11] Bugfix: `GLFW_ARROW_CURSOR` selected the wrong cursor image
- [X11] Bugfix: The `GLFW_DECORATED` hint was not ignored for full screen
- [X11] Bugfix: `glfwWaitEvents` did not handle `EINTR` for `select`
- [X11] Bugfix: `glfwWaitEvents` could return when no events were available
- [X11] Bugfix: `XkbGetKeyboard` fails on XWayland
- [X11] Bugfix: Character input did not work correctly for non-UTF-8 locales
- [X11] Bugfix: Long input sequences generated by IMEs were discarded
- [WGL] Made all WGL functions dynamically loaded
- [WGL] Removed `GLFW_USE_DWM_SWAP_INTERVAL` compile-time option
- [WGL] Bugfix: Swap interval was ignored when DWM was enabled
- [WGL] Bugfix: Failure to find a pixel format was reported incorrectly
- [GLX] Added dependency on `libdl` on systems where it provides `dlopen`
- [GLX] Made all GLX functions dynamically loaded
- [GLX] Removed `_GLFW_HAS_GLXGETPROCADDRESS*` and `_GLFW_HAS_DLOPEN`
compile-time options
- [GLX] Bugfix: Failure to find a `GLXFBConfig` was reported incorrectly
- [EGL] Made all EGL functions dynamically loaded
- [EGL] Bugfix: `glfwGetProcAddress` did not return the addresses of core
functions
- [EGL] Bugfix: Failure to find an `EGLConfig` was reported incorrectly
- [NSGL] Bugfix: Failure to find a pixel format was reported incorrectly
## Contact
@@ -100,9 +140,7 @@ request, please file it in the
[issue tracker](https://github.com/glfw/glfw/issues) on GitHub.
Finally, if you're interested in helping out with the development of GLFW or
porting it to your favorite platform, we have an occasionally active
[developer's mailing list](https://lists.stacken.kth.se/mailman/listinfo/glfw-dev),
or you could join us on `#glfw`.
porting it to your favorite platform, join us on GitHub or IRC.
## Acknowledgements
@@ -121,6 +159,7 @@ skills.
- Doug Binks
- blanco
- Martin Capitanio
- Chi-kwan Chan
- Lambert Clara
- Andrew Corrigan
- Noel Cower
@@ -142,14 +181,17 @@ skills.
- heromyth
- Lucas Hinderberger
- Paul Holden
- Aaron Jacobs
- Toni Jovanoski
- Arseny Kapoulkine
- Osman Keskin
- Cameron King
- Peter Knut
- Eric Larson
- Robin Leffmann
- Glenn Lewis
- Shane Liesegang
- Eyal Lotem
- Дмитри Малышев
- Martins Mozeiko
- Tristam MacDonald
@@ -173,6 +215,7 @@ skills.
- Peoro
- Braden Pellett
- Arturo J. Pérez
- Emmanuel Gil Peyrot
- Cyril Pichard
- Pieroman
- Jorge Rodriguez
@@ -191,6 +234,7 @@ skills.
- Julian Squires
- Johannes Stein
- Justin Stoecker
- Elviss Strazdins
- Nathan Sweet
- TTK-Bandit
- Sergey Tikhomirov
+571
View File
@@ -0,0 +1,571 @@
#ifndef LINMATH_H
#define LINMATH_H
#include <math.h>
#ifdef _MSC_VER
#define inline __inline
#endif
#define LINMATH_H_DEFINE_VEC(n) \
typedef float vec##n[n]; \
static inline void vec##n##_add(vec##n r, vec##n const a, vec##n const b) \
{ \
int i; \
for(i=0; i<n; ++i) \
r[i] = a[i] + b[i]; \
} \
static inline void vec##n##_sub(vec##n r, vec##n const a, vec##n const b) \
{ \
int i; \
for(i=0; i<n; ++i) \
r[i] = a[i] - b[i]; \
} \
static inline void vec##n##_scale(vec##n r, vec##n const v, float const s) \
{ \
int i; \
for(i=0; i<n; ++i) \
r[i] = v[i] * s; \
} \
static inline float vec##n##_mul_inner(vec##n const a, vec##n const b) \
{ \
float p = 0.; \
int i; \
for(i=0; i<n; ++i) \
p += b[i]*a[i]; \
return p; \
} \
static inline float vec##n##_len(vec##n const v) \
{ \
return sqrtf(vec##n##_mul_inner(v,v)); \
} \
static inline void vec##n##_norm(vec##n r, vec##n const v) \
{ \
float k = 1.f / vec##n##_len(v); \
vec##n##_scale(r, v, k); \
}
LINMATH_H_DEFINE_VEC(2)
LINMATH_H_DEFINE_VEC(3)
LINMATH_H_DEFINE_VEC(4)
static inline void vec3_mul_cross(vec3 r, vec3 const a, vec3 const b)
{
r[0] = a[1]*b[2] - a[2]*b[1];
r[1] = a[2]*b[0] - a[0]*b[2];
r[2] = a[0]*b[1] - a[1]*b[0];
}
static inline void vec3_reflect(vec3 r, vec3 const v, vec3 const n)
{
float p = 2.f*vec3_mul_inner(v, n);
int i;
for(i=0;i<3;++i)
r[i] = v[i] - p*n[i];
}
static inline void vec4_mul_cross(vec4 r, vec4 a, vec4 b)
{
r[0] = a[1]*b[2] - a[2]*b[1];
r[1] = a[2]*b[0] - a[0]*b[2];
r[2] = a[0]*b[1] - a[1]*b[0];
r[3] = 1.f;
}
static inline void vec4_reflect(vec4 r, vec4 v, vec4 n)
{
float p = 2.f*vec4_mul_inner(v, n);
int i;
for(i=0;i<4;++i)
r[i] = v[i] - p*n[i];
}
typedef vec4 mat4x4[4];
static inline void mat4x4_identity(mat4x4 M)
{
int i, j;
for(i=0; i<4; ++i)
for(j=0; j<4; ++j)
M[i][j] = i==j ? 1.f : 0.f;
}
static inline void mat4x4_dup(mat4x4 M, mat4x4 N)
{
int i, j;
for(i=0; i<4; ++i)
for(j=0; j<4; ++j)
M[i][j] = N[i][j];
}
static inline void mat4x4_row(vec4 r, mat4x4 M, int i)
{
int k;
for(k=0; k<4; ++k)
r[k] = M[k][i];
}
static inline void mat4x4_col(vec4 r, mat4x4 M, int i)
{
int k;
for(k=0; k<4; ++k)
r[k] = M[i][k];
}
static inline void mat4x4_transpose(mat4x4 M, mat4x4 N)
{
int i, j;
for(j=0; j<4; ++j)
for(i=0; i<4; ++i)
M[i][j] = N[j][i];
}
static inline void mat4x4_add(mat4x4 M, mat4x4 a, mat4x4 b)
{
int i;
for(i=0; i<4; ++i)
vec4_add(M[i], a[i], b[i]);
}
static inline void mat4x4_sub(mat4x4 M, mat4x4 a, mat4x4 b)
{
int i;
for(i=0; i<4; ++i)
vec4_sub(M[i], a[i], b[i]);
}
static inline void mat4x4_scale(mat4x4 M, mat4x4 a, float k)
{
int i;
for(i=0; i<4; ++i)
vec4_scale(M[i], a[i], k);
}
static inline void mat4x4_scale_aniso(mat4x4 M, mat4x4 a, float x, float y, float z)
{
int i;
vec4_scale(M[0], a[0], x);
vec4_scale(M[1], a[1], y);
vec4_scale(M[2], a[2], z);
for(i = 0; i < 4; ++i) {
M[3][i] = a[3][i];
}
}
static inline void mat4x4_mul(mat4x4 M, mat4x4 a, mat4x4 b)
{
mat4x4 temp;
int k, r, c;
for(c=0; c<4; ++c) for(r=0; r<4; ++r) {
temp[c][r] = 0.f;
for(k=0; k<4; ++k)
temp[c][r] += a[k][r] * b[c][k];
}
mat4x4_dup(M, temp);
}
static inline void mat4x4_mul_vec4(vec4 r, mat4x4 M, vec4 v)
{
int i, j;
for(j=0; j<4; ++j) {
r[j] = 0.f;
for(i=0; i<4; ++i)
r[j] += M[i][j] * v[i];
}
}
static inline void mat4x4_translate(mat4x4 T, float x, float y, float z)
{
mat4x4_identity(T);
T[3][0] = x;
T[3][1] = y;
T[3][2] = z;
}
static inline void mat4x4_translate_in_place(mat4x4 M, float x, float y, float z)
{
vec4 t = {x, y, z, 0};
vec4 r;
int i;
for (i = 0; i < 4; ++i) {
mat4x4_row(r, M, i);
M[3][i] += vec4_mul_inner(r, t);
}
}
static inline void mat4x4_from_vec3_mul_outer(mat4x4 M, vec3 a, vec3 b)
{
int i, j;
for(i=0; i<4; ++i) for(j=0; j<4; ++j)
M[i][j] = i<3 && j<3 ? a[i] * b[j] : 0.f;
}
static inline void mat4x4_rotate(mat4x4 R, mat4x4 M, float x, float y, float z, float angle)
{
float s = sinf(angle);
float c = cosf(angle);
vec3 u = {x, y, z};
if(vec3_len(u) > 1e-4) {
vec3_norm(u, u);
mat4x4 T;
mat4x4_from_vec3_mul_outer(T, u, u);
mat4x4 S = {
{ 0, u[2], -u[1], 0},
{-u[2], 0, u[0], 0},
{ u[1], -u[0], 0, 0},
{ 0, 0, 0, 0}
};
mat4x4_scale(S, S, s);
mat4x4 C;
mat4x4_identity(C);
mat4x4_sub(C, C, T);
mat4x4_scale(C, C, c);
mat4x4_add(T, T, C);
mat4x4_add(T, T, S);
T[3][3] = 1.;
mat4x4_mul(R, M, T);
} else {
mat4x4_dup(R, M);
}
}
static inline void mat4x4_rotate_X(mat4x4 Q, mat4x4 M, float angle)
{
float s = sinf(angle);
float c = cosf(angle);
mat4x4 R = {
{1.f, 0.f, 0.f, 0.f},
{0.f, c, s, 0.f},
{0.f, -s, c, 0.f},
{0.f, 0.f, 0.f, 1.f}
};
mat4x4_mul(Q, M, R);
}
static inline void mat4x4_rotate_Y(mat4x4 Q, mat4x4 M, float angle)
{
float s = sinf(angle);
float c = cosf(angle);
mat4x4 R = {
{ c, 0.f, s, 0.f},
{ 0.f, 1.f, 0.f, 0.f},
{ -s, 0.f, c, 0.f},
{ 0.f, 0.f, 0.f, 1.f}
};
mat4x4_mul(Q, M, R);
}
static inline void mat4x4_rotate_Z(mat4x4 Q, mat4x4 M, float angle)
{
float s = sinf(angle);
float c = cosf(angle);
mat4x4 R = {
{ c, s, 0.f, 0.f},
{ -s, c, 0.f, 0.f},
{ 0.f, 0.f, 1.f, 0.f},
{ 0.f, 0.f, 0.f, 1.f}
};
mat4x4_mul(Q, M, R);
}
static inline void mat4x4_invert(mat4x4 T, mat4x4 M)
{
float s[6];
float c[6];
s[0] = M[0][0]*M[1][1] - M[1][0]*M[0][1];
s[1] = M[0][0]*M[1][2] - M[1][0]*M[0][2];
s[2] = M[0][0]*M[1][3] - M[1][0]*M[0][3];
s[3] = M[0][1]*M[1][2] - M[1][1]*M[0][2];
s[4] = M[0][1]*M[1][3] - M[1][1]*M[0][3];
s[5] = M[0][2]*M[1][3] - M[1][2]*M[0][3];
c[0] = M[2][0]*M[3][1] - M[3][0]*M[2][1];
c[1] = M[2][0]*M[3][2] - M[3][0]*M[2][2];
c[2] = M[2][0]*M[3][3] - M[3][0]*M[2][3];
c[3] = M[2][1]*M[3][2] - M[3][1]*M[2][2];
c[4] = M[2][1]*M[3][3] - M[3][1]*M[2][3];
c[5] = M[2][2]*M[3][3] - M[3][2]*M[2][3];
/* Assumes it is invertible */
float idet = 1.0f/( s[0]*c[5]-s[1]*c[4]+s[2]*c[3]+s[3]*c[2]-s[4]*c[1]+s[5]*c[0] );
T[0][0] = ( M[1][1] * c[5] - M[1][2] * c[4] + M[1][3] * c[3]) * idet;
T[0][1] = (-M[0][1] * c[5] + M[0][2] * c[4] - M[0][3] * c[3]) * idet;
T[0][2] = ( M[3][1] * s[5] - M[3][2] * s[4] + M[3][3] * s[3]) * idet;
T[0][3] = (-M[2][1] * s[5] + M[2][2] * s[4] - M[2][3] * s[3]) * idet;
T[1][0] = (-M[1][0] * c[5] + M[1][2] * c[2] - M[1][3] * c[1]) * idet;
T[1][1] = ( M[0][0] * c[5] - M[0][2] * c[2] + M[0][3] * c[1]) * idet;
T[1][2] = (-M[3][0] * s[5] + M[3][2] * s[2] - M[3][3] * s[1]) * idet;
T[1][3] = ( M[2][0] * s[5] - M[2][2] * s[2] + M[2][3] * s[1]) * idet;
T[2][0] = ( M[1][0] * c[4] - M[1][1] * c[2] + M[1][3] * c[0]) * idet;
T[2][1] = (-M[0][0] * c[4] + M[0][1] * c[2] - M[0][3] * c[0]) * idet;
T[2][2] = ( M[3][0] * s[4] - M[3][1] * s[2] + M[3][3] * s[0]) * idet;
T[2][3] = (-M[2][0] * s[4] + M[2][1] * s[2] - M[2][3] * s[0]) * idet;
T[3][0] = (-M[1][0] * c[3] + M[1][1] * c[1] - M[1][2] * c[0]) * idet;
T[3][1] = ( M[0][0] * c[3] - M[0][1] * c[1] + M[0][2] * c[0]) * idet;
T[3][2] = (-M[3][0] * s[3] + M[3][1] * s[1] - M[3][2] * s[0]) * idet;
T[3][3] = ( M[2][0] * s[3] - M[2][1] * s[1] + M[2][2] * s[0]) * idet;
}
static inline void mat4x4_orthonormalize(mat4x4 R, mat4x4 M)
{
mat4x4_dup(R, M);
float s = 1.;
vec3 h;
vec3_norm(R[2], R[2]);
s = vec3_mul_inner(R[1], R[2]);
vec3_scale(h, R[2], s);
vec3_sub(R[1], R[1], h);
vec3_norm(R[2], R[2]);
s = vec3_mul_inner(R[1], R[2]);
vec3_scale(h, R[2], s);
vec3_sub(R[1], R[1], h);
vec3_norm(R[1], R[1]);
s = vec3_mul_inner(R[0], R[1]);
vec3_scale(h, R[1], s);
vec3_sub(R[0], R[0], h);
vec3_norm(R[0], R[0]);
}
static inline void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t, float n, float f)
{
M[0][0] = 2.f*n/(r-l);
M[0][1] = M[0][2] = M[0][3] = 0.f;
M[1][1] = 2.f*n/(t-b);
M[1][0] = M[1][2] = M[1][3] = 0.f;
M[2][0] = (r+l)/(r-l);
M[2][1] = (t+b)/(t-b);
M[2][2] = -(f+n)/(f-n);
M[2][3] = -1.f;
M[3][2] = -2.f*(f*n)/(f-n);
M[3][0] = M[3][1] = M[3][3] = 0.f;
}
static inline void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t, float n, float f)
{
M[0][0] = 2.f/(r-l);
M[0][1] = M[0][2] = M[0][3] = 0.f;
M[1][1] = 2.f/(t-b);
M[1][0] = M[1][2] = M[1][3] = 0.f;
M[2][2] = -2.f/(f-n);
M[2][0] = M[2][1] = M[2][3] = 0.f;
M[3][0] = -(r+l)/(r-l);
M[3][1] = -(t+b)/(t-b);
M[3][2] = -(f+n)/(f-n);
M[3][3] = 1.f;
}
static inline void mat4x4_perspective(mat4x4 m, float y_fov, float aspect, float n, float f)
{
/* NOTE: Degrees are an unhandy unit to work with.
* linmath.h uses radians for everything! */
float const a = 1.f / (float) tan(y_fov / 2.f);
m[0][0] = a / aspect;
m[0][1] = 0.f;
m[0][2] = 0.f;
m[0][3] = 0.f;
m[1][0] = 0.f;
m[1][1] = a;
m[1][2] = 0.f;
m[1][3] = 0.f;
m[2][0] = 0.f;
m[2][1] = 0.f;
m[2][2] = -((f + n) / (f - n));
m[2][3] = -1.f;
m[3][0] = 0.f;
m[3][1] = 0.f;
m[3][2] = -((2.f * f * n) / (f - n));
m[3][3] = 0.f;
}
static inline void mat4x4_look_at(mat4x4 m, vec3 eye, vec3 center, vec3 up)
{
/* Adapted from Android's OpenGL Matrix.java. */
/* See the OpenGL GLUT documentation for gluLookAt for a description */
/* of the algorithm. We implement it in a straightforward way: */
/* TODO: The negation of of can be spared by swapping the order of
* operands in the following cross products in the right way. */
vec3 f;
vec3_sub(f, center, eye);
vec3_norm(f, f);
vec3 s;
vec3_mul_cross(s, f, up);
vec3_norm(s, s);
vec3 t;
vec3_mul_cross(t, s, f);
m[0][0] = s[0];
m[0][1] = t[0];
m[0][2] = -f[0];
m[0][3] = 0.f;
m[1][0] = s[1];
m[1][1] = t[1];
m[1][2] = -f[1];
m[1][3] = 0.f;
m[2][0] = s[2];
m[2][1] = t[2];
m[2][2] = -f[2];
m[2][3] = 0.f;
m[3][0] = 0.f;
m[3][1] = 0.f;
m[3][2] = 0.f;
m[3][3] = 1.f;
mat4x4_translate_in_place(m, -eye[0], -eye[1], -eye[2]);
}
typedef float quat[4];
static inline void quat_identity(quat q)
{
q[0] = q[1] = q[2] = 0.f;
q[3] = 1.f;
}
static inline void quat_add(quat r, quat a, quat b)
{
int i;
for(i=0; i<4; ++i)
r[i] = a[i] + b[i];
}
static inline void quat_sub(quat r, quat a, quat b)
{
int i;
for(i=0; i<4; ++i)
r[i] = a[i] - b[i];
}
static inline void quat_mul(quat r, quat p, quat q)
{
vec3 w;
vec3_mul_cross(r, p, q);
vec3_scale(w, p, q[3]);
vec3_add(r, r, w);
vec3_scale(w, q, p[3]);
vec3_add(r, r, w);
r[3] = p[3]*q[3] - vec3_mul_inner(p, q);
}
static inline void quat_scale(quat r, quat v, float s)
{
int i;
for(i=0; i<4; ++i)
r[i] = v[i] * s;
}
static inline float quat_inner_product(quat a, quat b)
{
float p = 0.f;
int i;
for(i=0; i<4; ++i)
p += b[i]*a[i];
return p;
}
static inline void quat_conj(quat r, quat q)
{
int i;
for(i=0; i<3; ++i)
r[i] = -q[i];
r[3] = q[3];
}
static inline void quat_rotate(quat r, float angle, vec3 axis) {
vec3 v;
vec3_scale(v, axis, sinf(angle / 2));
int i;
for(i=0; i<3; ++i)
r[i] = v[i];
r[3] = cosf(angle / 2);
}
#define quat_norm vec4_norm
static inline void quat_mul_vec3(vec3 r, quat q, vec3 v)
{
/*
* Method by Fabian 'ryg' Giessen (of Farbrausch)
t = 2 * cross(q.xyz, v)
v' = v + q.w * t + cross(q.xyz, t)
*/
vec3 t = {q[0], q[1], q[2]};
vec3 u = {q[0], q[1], q[2]};
vec3_mul_cross(t, t, v);
vec3_scale(t, t, 2);
vec3_mul_cross(u, u, t);
vec3_scale(t, t, q[3]);
vec3_add(r, v, t);
vec3_add(r, r, u);
}
static inline void mat4x4_from_quat(mat4x4 M, quat q)
{
float a = q[3];
float b = q[0];
float c = q[1];
float d = q[2];
float a2 = a*a;
float b2 = b*b;
float c2 = c*c;
float d2 = d*d;
M[0][0] = a2 + b2 - c2 - d2;
M[0][1] = 2.f*(b*c + a*d);
M[0][2] = 2.f*(b*d - a*c);
M[0][3] = 0.f;
M[1][0] = 2*(b*c - a*d);
M[1][1] = a2 - b2 + c2 - d2;
M[1][2] = 2.f*(c*d + a*b);
M[1][3] = 0.f;
M[2][0] = 2.f*(b*d + a*c);
M[2][1] = 2.f*(c*d - a*b);
M[2][2] = a2 - b2 - c2 + d2;
M[2][3] = 0.f;
M[3][0] = M[3][1] = M[3][2] = 0.f;
M[3][3] = 1.f;
}
static inline void mat4x4o_mul_quat(mat4x4 R, mat4x4 M, quat q)
{
/* XXX: The way this is written only works for othogonal matrices. */
/* TODO: Take care of non-orthogonal case. */
quat_mul_vec3(R[0], q, M[0]);
quat_mul_vec3(R[1], q, M[1]);
quat_mul_vec3(R[2], q, M[2]);
R[3][0] = R[3][1] = R[3][2] = 0.f;
R[3][3] = 1.f;
}
static inline void quat_from_mat4x4(quat q, mat4x4 M)
{
float r=0.f;
int i;
int perm[] = { 0, 1, 2, 0, 1 };
int *p = perm;
for(i = 0; i<3; i++) {
float m = M[i][i];
if( m < r )
continue;
m = r;
p = &perm[i];
}
r = sqrtf(1.f + M[p[0]][p[0]] - M[p[1]][p[1]] - M[p[2]][p[2]] );
if(r < 1e-6) {
q[0] = 1.f;
q[1] = q[2] = q[3] = 0.f;
return;
}
q[0] = r/2.f;
q[1] = (M[p[0]][p[1]] - M[p[1]][p[0]])/(2.f*r);
q[2] = (M[p[2]][p[0]] - M[p[0]][p[2]])/(2.f*r);
q[3] = (M[p[2]][p[1]] - M[p[1]][p[2]])/(2.f*r);
}
#endif
+4 -3
View File
@@ -22,8 +22,9 @@ freely, subject to the following restrictions:
*/
/* 2013-01-06 Camilla Berglund <elmindreda@elmindreda.org>
*
*
* Added casts from time_t to DWORD to avoid warnings on VC++.
* Fixed time retrieval on POSIX systems.
*/
#include "tinycthread.h"
@@ -294,7 +295,7 @@ int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
{
#if defined(_TTHREAD_WIN32_)
struct timespec now;
if (clock_gettime(TIME_UTC, &now) == 0)
if (clock_gettime(CLOCK_REALTIME, &now) == 0)
{
DWORD delta = (DWORD) ((ts->tv_sec - now.tv_sec) * 1000 +
(ts->tv_nsec - now.tv_nsec + 500000) / 1000000);
@@ -471,7 +472,7 @@ int thrd_sleep(const struct timespec *time_point, struct timespec *remaining)
#endif
/* Get the current time */
if (clock_gettime(TIME_UTC, &now) != 0)
if (clock_gettime(CLOCK_REALTIME, &now) != 0)
return -2; // FIXME: Some specific error code?
#if defined(_TTHREAD_WIN32_)
+5 -4
View File
@@ -96,8 +96,8 @@ to that header.
`GLFW_INCLUDE_GLU` makes the header include the GLU header in addition to the
header selected above. This should only be used with the standard OpenGL header
and only for legacy code. GLU has been deprecated and should not be used in new
code.
and only for compatibility with legacy code. GLU has been deprecated and should
not be used in new code.
@note GLFW does not provide any of the API headers mentioned above. They must
be provided by your development environment or your OpenGL or OpenGL ES SDK.
@@ -254,7 +254,7 @@ You can also use the `glfw3.pc` file without installing it first, by using the
env PKG_CONFIG_PATH=path/to/glfw/src cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --libs glfw3`
@endcode
The dependencies do not include GLU, as GLFW does not need it. On OS X, GLU is
The dependencies do not include GLU, as GLFW does not use it. On OS X, GLU is
built into the OpenGL framework, so if you need GLU you don't need to do
anything extra. If you need GLU and are using Linux or BSD, you should add the
`glu` pkg-config module.
@@ -263,7 +263,8 @@ anything extra. If you need GLU and are using Linux or BSD, you should add the
cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --libs glfw3 glu`
@endcode
If you are using the static version of the GLFW library, make sure you don't link statically against GLU.
If you are using the static version of the GLFW library, make sure you don't
link statically against GLU.
@code{.sh}
cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --static --libs glfw3` `pkg-config --libs glu`
+10
View File
@@ -117,6 +117,11 @@ whether a context is flushed when it is released (made non-current). Where this
extension is unavailable, the `GLFW_CONTEXT_RELEASE_BEHAVIOR` hint will have no
effect and the context will always be flushed when released.
GLFW uses the `GLX_ARB_framebuffer_sRGB` and `GLX_EXT_framebuffer_sRGB`
extensions to provide support for sRGB framebuffers. Where both of these
extensions are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect.
@section compat_wgl WGL extensions
The WGL API is used to create OpenGL contexts on Microsoft Windows and other
@@ -154,6 +159,11 @@ whether a context is flushed when it is released (made non-current). Where this
extension is unavailable, the `GLFW_CONTEXT_RELEASE_BEHAVIOR` hint will have no
effect and the context will always be flushed when released.
GLFW uses the `WGL_ARB_framebuffer_sRGB` and `WGL_EXT_framebuffer_sRGB`
extensions to provide support for sRGB framebuffers. Where both of these
extension are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect.
@section compat_osx OpenGL 3.2 and later on OS X
Support for OpenGL 3.2 and above was introduced with OS X 10.7 and even then
+22 -33
View File
@@ -17,8 +17,9 @@ Homebrew, you can simply install its CMake package. If not, you can download
installers for Windows and OS X from the [CMake website](http://www.cmake.org/).
@note CMake only generates project files or makefiles. It does not compile the
actual GLFW library. To compile GLFW, first generate these files and then use
them in your chosen development environment to compile the actual GLFW library.
actual GLFW library. To compile GLFW, first generate these files for your
chosen development environment and then use them to compile the actual GLFW
library.
@subsection compile_deps Dependencies
@@ -89,11 +90,10 @@ Once you have Xcode installed, move on to @ref compile_generate.
To compile GLFW for X11, you need to have the X11 and OpenGL header packages
installed, as well as the basic development tools like GCC and make. For
example, on Ubuntu and other distributions based on Debian GNU/Linux, you need
to install the `xorg-dev` and `libglu1-mesa-dev` packages. The former pulls in
all X.org header packages and the latter pulls in the Mesa OpenGL and GLU
packages. GLFW itself doesn't need or use GLU, but some of the examples do.
Note that using header files and libraries from Mesa during compilation
_will not_ tie your binaries to the Mesa implementation of OpenGL.
to install the `xorg-dev` and `libgl1-mesa-dev` packages. The former pulls in
all X.org header packages and the latter pulls in the Mesa OpenGL development
packages. Note that using header files and libraries from Mesa during
compilation _will not_ tie your binaries to the Mesa implementation of OpenGL.
Once you have installed the necessary packages, move on to @ref
compile_generate.
@@ -127,15 +127,14 @@ cd <glfw-root-dir>
cmake .
@endcode
To make an out-of-tree build, make another directory, enter it and run CMake
with the (relative or absolute) path to the root of the source tree as an
argument.
To make an out-of-tree build, make a directory outside of the source tree, enter
it and run CMake with the (relative or absolute) path to the root of the source
tree as an argument.
@code{.sh}
cd <glfw-root-dir>
mkdir build
cd build
cmake ..
mkdir glfw-build
cd glfw-build
cmake <glfw-root-dir>
@endcode
Once you have generated the project files or makefiles for your chosen
@@ -222,16 +221,11 @@ DLL version of the Visual C++ library is used. It is recommended to set this to
`ON`, as this keeps the executable smaller and benefits from security and bug
fix updates of the Visual C++ runtime.
`GLFW_USE_DWM_SWAP_INTERVAL` determines whether the swap interval is set even
when DWM compositing is enabled. If this is `ON`, the swap interval is set even
if DWM is enabled. It is recommended to set this to `OFF`, as doing otherwise
can lead to severe jitter.
`GLFW_USE_OPTIMUS_HPG` determines whether to export the `NvOptimusEnablement`
symbol, which forces the use of the high-performance GPU on Nvidia Optimus
systems. This symbol needs to be exported by the EXE to be detected by the
driver, so the override will not work if GLFW is built as a DLL. See _Enabling
High Performance Graphics Rendering on Optimus Systems_ for more details.
`GLFW_USE_HYBRID_HPG` determines whether to export the `NvOptimusEnablement` and
`AmdPowerXpressRequestHighPerformance` symbols, which force the use of the
high-performance GPU on Nvidia Optimus and AMD PowerXpress systems. These symbols
need to be exported by the EXE to be detected by the driver, so the override
will not work if GLFW is built as a DLL.
@subsubsection compile_options_egl EGL specific CMake options
@@ -294,18 +288,13 @@ libraries.
If you are building GLFW as a shared library / dynamic library / DLL then you
must also define `_GLFW_BUILD_DLL`. Otherwise, you may not define it.
If you are using the X11 window creation API then you _must_ also select an entry
point retrieval mechanism.
- `_GLFW_HAS_GLXGETPROCADDRESS` to use `glXGetProcAddress` (recommended)
- `_GLFW_HAS_GLXGETPROCADDRESSARB` to use `glXGetProcAddressARB` (legacy)
- `_GLFW_HAS_GLXGETPROCADDRESSEXT` to use `glXGetProcAddressEXT` (legacy)
- `_GLFW_HAS_DLOPEN` to do manual retrieval with `dlopen` (fallback)
In addition, support for the following X11 extensions can be enabled:
If you are using the X11 window creation API, support for the following X11
extensions can be enabled:
- `_GLFW_HAS_XINPUT` to use XInput2 for high-resolution cursor motion
(recommended)
- `_GLFW_HAS_XF86VM` to use Xxf86vm as a fallback when RandR gamma is broken
(recommended)
If you are using the Cocoa window creation API, the following options are
available:
+3 -6
View File
@@ -307,12 +307,9 @@ void load_extensions(void)
{
if (glfwExtensionSupported("GL_ARB_debug_output"))
{
pfnGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGARBPROC) glfwGetProcAddress("glGetDebugMessageLogARB");
if (pfnGetDebugMessageLog)
{
// Both the extension name and the function pointer are present
has_ARB_debug_output = 1;
}
pfnGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGARBPROC)
glfwGetProcAddress("glGetDebugMessageLogARB");
has_ARB_debug_output = 1;
}
}
+14 -11
View File
@@ -104,15 +104,12 @@ void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod
@endcode
The action is one of `GLFW_PRESS`, `GLFW_REPEAT` or `GLFW_RELEASE`. The key
will be `GLFW_KEY_UNKNOWN` if GLFW lacks a key token for it. These keys still
have unique, if platform-specific scancodes.
will be `GLFW_KEY_UNKNOWN` if GLFW lacks a key token for it, for example
_E-mail_ and _Play_ keys.
The scancode is unique for every key but is platform-specific, so a scancode
will map to different keys on different platforms.
The key will be `GLFW_KEY_UNKNOWN` for special keys like _E-mail_ or _Play_ that
don't have a key token. Those keys will still have unique, if platform-specific
scancodes.
The scancode is unique for every key, regardless of whether it has a key token.
Scancodes are platform-specific but consistent over time, so keys will have
different scancodes depending on the platform but they are safe to save to disk.
Key states for [named keys](@ref keys) are also saved in per-window state arrays
that can be polled with @ref glfwGetKey.
@@ -299,8 +296,9 @@ GLFWcursor* cursor = glfwCreateCursor(&image, 0, 0);
If cursor creation fails, `NULL` will be returned, so it is necessary to check
the return value.
The image data is 32-bit RGBA, i.e. eight bits per channel. The pixels are
arranged canonically as sequential rows, starting from the top-left corner.
The image data is 32-bit, little-endian, non-premultiplied RGBA, i.e. eight bits
per channel. The pixels are arranged canonically as sequential rows, starting
from the top-left corner.
@subsubsection cursor_standard Standard cursor creation
@@ -546,9 +544,14 @@ converted to one, you can retrieve it with @ref glfwGetClipboardString. See the
reference documentation for the lifetime of the returned string.
@code
const char* clipboard = glfwGetClipboardString(window);
const char* text = glfwGetClipboardString(window);
if (text)
insert_text(text);
@endcode
If the clipboard is empty or if its contents could not be converted, `NULL` is
returned.
The contents of the system clipboard can be set to a UTF-8 encoded string with
@ref glfwSetClipboardString.
+3 -6
View File
@@ -210,12 +210,9 @@ including functions that may called before initialization.
The reference documentation for every GLFW function states whether it is limited
to the main thread.
The following categories of functions are and will remain limited to the main
thread due to the limitations of one or several platforms:
- Initialization and termination
- Event processing
- Creation and destruction of window, context and cursor objects
Initialization and termination, event processing and the creation and
destruction of windows, contexts and cursors are all limited to the main thread
due to limitations of one or several platforms.
Because event processing must be performed on the main thread, all callbacks
except for the error callback will only be called on that thread. The error
+1 -1
View File
@@ -429,7 +429,7 @@ invalidating any window handles you may still have.
GLFW 3 does not by default include the GLU header and GLU itself has been
deprecated by [Khronos](https://en.wikipedia.org/wiki/Khronos_Group). __New
projects should avoid using GLU__, but if you need to compile legacy code that
projects should not use GLU__, but if you need it for legacy code that
has been moved to GLFW 3, you can request that the GLFW header includes it by
defining `GLFW_INCLUDE_GLU` before the inclusion of the GLFW header.
+3 -2
View File
@@ -47,8 +47,9 @@ In other words:
GLFW one and it will detect this
Starting with version 3.0, the GLU header `glu.h` is no longer included by
default. If you wish to include it, define `GLFW_INCLUDE_GLU` before the
inclusion of the GLFW header.
default. GLU is deprecated and should not be used in new code. If you need to
include it for legacy code, define `GLFW_INCLUDE_GLU` before the inclusion of
the GLFW header.
@code
#define GLFW_INCLUDE_GLU
+48 -19
View File
@@ -134,9 +134,7 @@ you wish to have the specified attributes.
Some window hints are hard constraints. These must match the available
capabilities _exactly_ for window and context creation to succeed. Hints
that are not hard constraints are matched as closely as possible, but the
resulting window and context may differ from what these hints requested. To
find out the actual attributes of the created window and context, use the
@ref glfwGetWindowAttrib function.
resulting context and framebuffer may differ from what these hints requested.
The following hints are always hard constraints:
- `GLFW_STEREO`
@@ -151,30 +149,30 @@ context, but are ignored when requesting an OpenGL ES context:
@subsubsection window_hints_wnd Window related hints
`GLFW_RESIZABLE` specifies whether the (windowed mode) window will be resizable
`GLFW_RESIZABLE` specifies whether the windowed mode window will be resizable
_by the user_. The window will still be resizable using the @ref
glfwSetWindowSize function. This hint is ignored for full screen windows.
`GLFW_VISIBLE` specifies whether the (windowed mode) window will be initially
`GLFW_VISIBLE` specifies whether the windowed mode window will be initially
visible. This hint is ignored for full screen windows.
`GLFW_DECORATED` specifies whether the (windowed mode) window will have window
decorations such as a border, a close widget, etc. This hint is ignored for
full screen windows. Note that even though a window may lack a close widget, it
is usually still possible for the user to generate close events.
`GLFW_DECORATED` specifies whether the windowed mode window will have window
decorations such as a border, a close widget, etc. An undecorated window may
still allow the user to generate close events on some platforms. This hint is
ignored for full screen windows.
`GLFW_FOCUSED` specifies whether the (windowed mode) window will be given input
`GLFW_FOCUSED` specifies whether the windowed mode window will be given input
focus when created. This hint is ignored for full screen and initially hidden
windows.
`GLFW_AUTO_ICONIFY` specifies whether the (full screen) window will
`GLFW_AUTO_ICONIFY` specifies whether the full screen window will
automatically iconify and restore the previous video mode on input focus loss.
This hint is ignored for windowed mode windows.
`GLFW_FLOATING` specifies whether the window will be floating above other
regular windows, also called topmost or always-on-top. This is intended
primarily for debugging purposes and cannot be used to implement proper full
screen windows. This hint is ignored for full screen windows.
`GLFW_FLOATING` specifies whether the windowed mode window will be floating
above other regular windows, also called topmost or always-on-top. This is
intended primarily for debugging purposes and cannot be used to implement proper
full screen windows. This hint is ignored for full screen windows.
@subsubsection window_hints_fb Framebuffer related hints
@@ -208,6 +206,8 @@ Zero disables multisampling. `GLFW_DONT_CARE` means the application has no
preference.
`GLFW_SRGB_CAPABLE` specifies whether the framebuffer should be sRGB capable.
If supported, the created context will provide `GL_ARB_framebuffer_sRGB` or
`GL_EXT_framebuffer_sRGB`.
`GLFW_DOUBLEBUFFER` specifies whether the framebuffer should be double buffered.
You nearly always want to use double buffering. This is a hard constraint.
@@ -538,7 +538,7 @@ As long as your source file is encoded as UTF-8, you can use any Unicode
characters directly in the source.
@code
glfwSetWindowTitle(window, "おもひでぽろぽろ");
glfwSetWindowTitle(window, "プラネテス");
@endcode
@@ -764,6 +764,37 @@ This is `GLFW_LOSE_CONTEXT_ON_RESET` or `GLFW_NO_RESET_NOTIFICATION` if the
window's context supports robustness, or `GLFW_NO_ROBUSTNESS` otherwise.
@subsubsection window_attribs_fb Framebuffer related attributes
The attributes of the default framebuffer (i.e. the framebuffer attached to the
window) are not provided by this function but can be queried with both OpenGL
and OpenGL ES.
If you are using version 3.0 or later of OpenGL or OpenGL ES, the
`glGetFramebufferAttachmentParameteriv` function can be used to retrieve the
number of bits for the red, green, blue, alpha, depth and stencil buffer
channels. Otherwise, the `glGetIntegerv` function can be used.
The number of MSAA samples are always retrieved with `glGetIntegerv`. For
contexts supporting framebuffer objects, the number of samples of the currently
bound framebuffer is returned.
Attribute | glGetIntegerv | glGetFramebufferAttachmentParameteriv
------------ | ----------------- | -------------------------------------
Red bits | `GL_RED_BITS` | `GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE`
Green bits | `GL_GREEN_BITS` | `GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE`
Blue bits | `GL_BLUE_BITS` | `GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE`
Alpha bits | `GL_ALPHA_BITS` | `GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE`
Depth bits | `GL_DEPTH_BITS` | `GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE`
Stencil bits | `GL_STENCIL_BITS` | `GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE`
MSAA samples | `GL_SAMPLES` | _Not provided by this function_
When calling `glGetFramebufferAttachmentParameteriv`, the red, green, blue and
alpha sizes can be queried from the `GL_BACK_LEFT`, while the depth and stencil
sizes can be queried from the `GL_DEPTH` and `GL_STENCIL` attachments,
respectively.
@section buffer_swap Buffer swapping
GLFW windows are by default double buffered. That means that you have two
@@ -796,8 +827,6 @@ interval of one lets you avoid tearing.
Note that this may not work on all machines, as some drivers have
user-controlled settings that override any swap interval the application
requests. It is also by default disabled on Windows Vista and later when using
DWM (Aero), as using it there sometimes leads to severe jitter. You can
forcibly enable it for machines using DWM using @ref compile_options_win32.
requests.
*/
+21 -44
View File
@@ -1,5 +1,5 @@
link_libraries(glfw "${OPENGL_glu_LIBRARY}")
link_libraries(glfw)
if (BUILD_SHARED_LIBS)
add_definitions(-DGLFW_DLL)
@@ -22,61 +22,38 @@ set(GETOPT "${GLFW_SOURCE_DIR}/deps/getopt.h"
set(TINYCTHREAD "${GLFW_SOURCE_DIR}/deps/tinycthread.h"
"${GLFW_SOURCE_DIR}/deps/tinycthread.c")
if (APPLE)
# Set fancy names for bundles
add_executable(Boing MACOSX_BUNDLE boing.c)
add_executable(Gears MACOSX_BUNDLE gears.c)
add_executable(Heightmap MACOSX_BUNDLE heightmap.c ${GLAD})
add_executable(Particles MACOSX_BUNDLE particles.c ${TINYCTHREAD})
add_executable(Simple MACOSX_BUNDLE simple.c)
add_executable(SplitView MACOSX_BUNDLE splitview.c)
add_executable(Wave MACOSX_BUNDLE wave.c)
add_executable(boing WIN32 MACOSX_BUNDLE boing.c)
add_executable(gears WIN32 MACOSX_BUNDLE gears.c)
add_executable(heightmap WIN32 MACOSX_BUNDLE heightmap.c ${GLAD})
add_executable(particles WIN32 MACOSX_BUNDLE particles.c ${TINYCTHREAD} ${GETOPT})
add_executable(simple WIN32 MACOSX_BUNDLE simple.c)
add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c)
add_executable(wave WIN32 MACOSX_BUNDLE wave.c)
set_target_properties(Boing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Boing")
set_target_properties(Gears PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gears")
set_target_properties(Heightmap PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Heightmap")
set_target_properties(Particles PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Particles")
set_target_properties(Simple PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Simple")
set_target_properties(SplitView PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Split View")
set_target_properties(Wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave")
target_link_libraries(particles "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
set_target_properties(Boing Gears Heightmap Particles Simple SplitView Wave PROPERTIES
FOLDER "GLFW3/Examples"
MACOSX_BUNDLE_INFO_PLIST "${GLFW_SOURCE_DIR}/CMake/AppleInfo.plist")
set(WINDOWS_BINARIES boing gears heightmap particles simple splitview wave)
else()
# Set boring names for executables
add_executable(boing WIN32 boing.c)
add_executable(gears WIN32 gears.c)
add_executable(heightmap WIN32 heightmap.c ${GLAD})
add_executable(particles WIN32 particles.c ${TINYCTHREAD} ${GETOPT})
add_executable(simple WIN32 simple.c)
add_executable(splitview WIN32 splitview.c)
add_executable(wave WIN32 wave.c)
set_target_properties(boing gears heightmap particles simple splitview wave PROPERTIES
FOLDER "GLFW3/Examples")
endif()
if (APPLE)
target_link_libraries(Particles "${CMAKE_THREAD_LIBS_INIT}")
elseif (UNIX)
target_link_libraries(particles "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
endif()
set_target_properties(${WINDOWS_BINARIES} PROPERTIES FOLDER "GLFW3/Examples")
if (MSVC)
set(WINDOWS_BINARIES boing gears heightmap particles simple splitview wave)
# Tell MSVC to use main instead of WinMain for Windows subsystem executables
set_target_properties(${WINDOWS_BINARIES} PROPERTIES
LINK_FLAGS "/ENTRY:mainCRTStartup")
endif()
if (APPLE)
set(BUNDLE_BINARIES Boing Gears Heightmap Particles Simple SplitView Wave)
set_target_properties(boing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Boing")
set_target_properties(gears PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gears")
set_target_properties(heightmap PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Heightmap")
set_target_properties(particles PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Particles")
set_target_properties(simple PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Simple")
set_target_properties(splitview PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Split View")
set_target_properties(wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave")
set_target_properties(${BUNDLE_BINARIES} PROPERTIES
set_target_properties(${WINDOWS_BINARIES} PROPERTIES
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}
MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION_FULL})
MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION_FULL}
MACOSX_BUNDLE_INFO_PLIST "${GLFW_SOURCE_DIR}/CMake/MacOSXBundleInfo.plist.in")
endif()
+21 -39
View File
@@ -27,13 +27,19 @@
* 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 GLFW_INCLUDE_GLU
#include <GLFW/glfw3.h>
#include <linmath.h>
/*****************************************************************************
* Various declarations and macros
@@ -102,11 +108,6 @@ double dt;
#define RAND_MAX 4095
#endif
/* PI */
#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795
#endif
/*****************************************************************************
* Truncate a degree.
@@ -167,28 +168,6 @@ void CrossProduct( vertex_t a, vertex_t b, vertex_t c, vertex_t *n )
n->z = u1 * v2 - v1 * u2;
}
/*****************************************************************************
* Calculate the angle to be passed to gluPerspective() so that a scene
* is visible. This function originates from the OpenGL Red Book.
*
* Parms : size
* The size of the segment when the angle is intersected at "dist"
* (ie at the outermost edge of the angle of vision).
*
* dist
* Distance from viewpoint to scene.
*****************************************************************************/
GLfloat PerspectiveAngle( GLfloat size,
GLfloat dist )
{
GLfloat radTheta, degTheta;
radTheta = 2.f * (GLfloat) atan2( size / 2.f, dist );
degTheta = (180.f * radTheta) / (GLfloat) M_PI;
return degTheta;
}
#define BOING_DEBUG 0
@@ -233,22 +212,25 @@ void display(void)
*****************************************************************************/
void reshape( GLFWwindow* window, int w, int h )
{
mat4x4 projection, view;
glViewport( 0, 0, (GLsizei)w, (GLsizei)h );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( PerspectiveAngle( RADIUS * 2, 200 ),
(GLfloat)w / (GLfloat)h,
1.0,
VIEW_SCENE_DIST );
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 );
glLoadIdentity();
gluLookAt( 0.0, 0.0, VIEW_SCENE_DIST,/* eye */
0.0, 0.0, 0.0, /* center of vision */
0.0, -1.0, 0.0 ); /* up vector */
{
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 )
+6 -24
View File
@@ -21,6 +21,10 @@
* - Enabled vsync
*/
#if defined(_MSC_VER)
// Make MS math.h define M_PI
#define _USE_MATH_DEFINES
#endif
#include <math.h>
#include <stdlib.h>
@@ -28,14 +32,6 @@
#include <string.h>
#include <GLFW/glfw3.h>
#ifndef M_PI
#define M_PI 3.141592654
#endif
/* If non-zero, the program exits after that many seconds
*/
static int autoexit = 0;
/**
Draw a gear wheel. You'll probably want to call this function when
@@ -264,13 +260,12 @@ void reshape( GLFWwindow* window, int width, int height )
/* program & OpenGL initialization */
static void init(int argc, char *argv[])
static void init(void)
{
static GLfloat pos[4] = {5.f, 5.f, 10.f, 0.f};
static GLfloat 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};
GLint i;
glLightfv(GL_LIGHT0, GL_POSITION, pos);
glEnable(GL_CULL_FACE);
@@ -298,19 +293,6 @@ static void init(int argc, char *argv[])
glEndList();
glEnable(GL_NORMALIZE);
for ( i=1; i<argc; i++ ) {
if (strcmp(argv[i], "-info")==0) {
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
}
else if ( strcmp(argv[i], "-exit")==0) {
autoexit = 30;
printf("Auto Exit after %i seconds.\n", autoexit );
}
}
}
@@ -347,7 +329,7 @@ int main(int argc, char *argv[])
reshape(window, width, height);
// Parse command-line options
init(argc, argv);
init();
// Main loop
while( !glfwWindowShouldClose(window) )
+15 -10
View File
@@ -24,6 +24,11 @@
//
//========================================================================
#if defined(_MSC_VER)
// Make MS math.h define M_PI
#define _USE_MATH_DEFINES
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -32,8 +37,8 @@
#include <tinycthread.h>
#include <getopt.h>
#include <linmath.h>
#define GLFW_INCLUDE_GLU
#include <GLFW/glfw3.h>
// Define tokens for GL_EXT_separate_specular_color if not already defined
@@ -43,11 +48,6 @@
#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA
#endif // GL_EXT_separate_specular_color
// Some <math.h>'s do not define M_PI
#ifndef M_PI
#define M_PI 3.141592654
#endif
//========================================================================
// Type definitions
@@ -785,17 +785,22 @@ static void draw_scene(GLFWwindow* window, double t)
double xpos, ypos, zpos, angle_x, angle_y, angle_z;
static double t_old = 0.0;
float dt;
mat4x4 projection;
// Calculate frame-to-frame delta time
dt = (float) (t - t_old);
t_old = t;
mat4x4_perspective(projection,
65.f * (float) M_PI / 180.f,
aspect_ratio,
1.0, 60.0);
glClearColor(0.1f, 0.1f, 0.1f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(65.0, aspect_ratio, 1.0, 60.0);
glLoadMatrixf((const GLfloat*) projection);
// Setup camera
glMatrixMode(GL_MODELVIEW);
@@ -986,11 +991,11 @@ int main(int argc, char** argv)
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwSetWindowSizeCallback(window, resize_callback);
glfwSetFramebufferSizeCallback(window, resize_callback);
glfwSetKeyCallback(window, key_callback);
// Set initial aspect ratio
glfwGetWindowSize(window, &width, &height);
glfwGetFramebufferSize(window, &width, &height);
resize_callback(window, width, height);
// Upload particle texture
+72 -29
View File
@@ -10,16 +10,19 @@
// because I am not a friend of orthogonal projections)
//========================================================================
#define GLFW_INCLUDE_GLU
#define GLFW_INCLUDE_GLEXT
#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>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#include <linmath.h>
//========================================================================
@@ -149,6 +152,7 @@ static void drawGrid(float scale, int steps)
{
int i;
float x, y;
mat4x4 view;
glPushMatrix();
@@ -157,10 +161,13 @@ static void drawGrid(float scale, int steps)
glClear(GL_COLOR_BUFFER_BIT);
// Setup modelview matrix (flat XY view)
glLoadIdentity();
gluLookAt(0.0, 0.0, 1.0,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0);
{
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);
@@ -209,13 +216,14 @@ static void drawAllViews(void)
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};
double aspect;
float aspect;
mat4x4 view, projection;
// Calculate aspect of window
if (height > 0)
aspect = (double) width / (double) height;
aspect = (float) width / (float) height;
else
aspect = 1.0;
aspect = 1.f;
// Clear screen
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@@ -247,10 +255,13 @@ static void drawAllViews(void)
glViewport(0, height / 2, width / 2, height / 2);
glScissor(0, height / 2, width / 2, height / 2);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0f, 10.0f, 1e-3f, // Eye-position (above)
0.0f, 0.0f, 0.0f, // View-point
0.0f, 1.0f, 0.0f); // Up-vector
{
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();
@@ -258,10 +269,13 @@ static void drawAllViews(void)
glViewport(0, 0, width / 2, height / 2);
glScissor(0, 0, width / 2, height / 2);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0f, 0.0f, 10.0f, // Eye-position (in front of)
0.0f, 0.0f, 0.0f, // View-point
0.0f, 1.0f, 0.0f); // Up-vector
{
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();
@@ -269,10 +283,13 @@ static void drawAllViews(void)
glViewport(width / 2, 0, width / 2, height / 2);
glScissor(width / 2, 0, width / 2, height / 2);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(10.0f, 0.0f, 0.0f, // Eye-position (to the right)
0.0f, 0.0f, 0.0f, // View-point
0.0f, 1.0f, 0.0f); // Up-vector
{
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();
@@ -292,17 +309,23 @@ static void drawAllViews(void)
// Setup perspective projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(65.0f, aspect, 1.0f, 50.0f);
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);
glLoadIdentity();
gluLookAt(3.0f, 1.5f, 3.0f, // Eye-position
0.0f, 0.0f, 0.0f, // View-point
0.0f, 1.0f, 0.0f); // Up-vector
{
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);
@@ -383,6 +406,17 @@ static void windowRefreshFun(GLFWwindow* window)
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)
{
@@ -458,6 +492,8 @@ int main(void)
exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_SAMPLES, 4);
// Open OpenGL window
window = glfwCreateWindow(500, 500, "Split view demo", NULL, NULL);
if (!window)
@@ -479,6 +515,13 @@ int main(void)
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
if (glfwExtensionSupported("GL_ARB_multisample") ||
glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR) >= 2 ||
glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR) >= 3)
{
glEnable(GL_MULTISAMPLE_ARB);
}
glfwGetFramebufferSize(window, &width, &height);
framebufferSizeFun(window, width, height);
+12 -6
View File
@@ -8,16 +8,18 @@
* 2010-10-24: Formatting and cleanup - Camilla Berglund
*****************************************************************************/
#if defined(_MSC_VER)
// Make MS math.h define M_PI
#define _USE_MATH_DEFINES
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define GLFW_INCLUDE_GLU
#include <GLFW/glfw3.h>
#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795
#endif
#include <linmath.h>
// Maximum delta T to allow for differential calculations
#define MAX_DELTA_T 0.01
@@ -362,6 +364,7 @@ void scroll_callback(GLFWwindow* window, double x, double y)
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
float ratio = 1.f;
mat4x4 projection;
if (height > 0)
ratio = (float) width / (float) height;
@@ -371,8 +374,11 @@ void framebuffer_size_callback(GLFWwindow* window, int width, int height)
// Change to the projection matrix and set our viewing volume
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, ratio, 1.0, 1024.0);
mat4x4_perspective(projection,
60.f * (float) M_PI / 180.f,
ratio,
1.f, 1024.f);
glLoadMatrixf((const GLfloat*) projection);
}
+46 -28
View File
@@ -211,7 +211,7 @@ extern "C" {
* API changes.
* @ingroup init
*/
#define GLFW_VERSION_REVISION 1
#define GLFW_VERSION_REVISION 2
/*! @} */
/*! @name Key and button actions
@@ -531,7 +531,7 @@ extern "C" {
*
* @par
* Some pre-installed Windows graphics drivers do not support OpenGL. AMD only
* supports OpenGL ES via EGL, while Nvidia and Intel only supports it via
* supports OpenGL ES via EGL, while Nvidia and Intel only support it via
* a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa
* EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary
* driver.
@@ -1067,12 +1067,6 @@ typedef struct GLFWimage
* bundle, if present. This can be disabled with a
* [compile-time option](@ref compile_options_osx).
*
* @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to
* `"C"` then the environment's locale will be applied to that category. This
* is done because character input will not function when `LC_CTYPE` is set to
* `"C"`. If another locale was set before this function was called, it will
* be left untouched.
*
* @par Thread Safety
* This function may only be called from the main thread.
*
@@ -1212,12 +1206,13 @@ GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun);
/*! @brief Returns the currently connected monitors.
*
* This function returns an array of handles for all currently connected
* monitors.
* monitors. The primary monitor is always first in the returned array. If no
* monitors were found, this function returns `NULL`.
*
* @param[out] count Where to store the number of monitors in the returned
* array. This is set to zero if an error occurred.
* @return An array of monitor handles, or `NULL` if an
* [error](@ref error_handling) occurred.
* @return An array of monitor handles, or `NULL` if no monitors were found or
* if an [error](@ref error_handling) occurred.
*
* @par Pointer Lifetime
* The returned array is allocated and freed by GLFW. You should not free it
@@ -1240,14 +1235,17 @@ GLFWAPI GLFWmonitor** glfwGetMonitors(int* count);
/*! @brief Returns the primary monitor.
*
* This function returns the primary monitor. This is usually the monitor
* where elements like the Windows task bar or the OS X menu bar is located.
* where elements like the task bar or global menu bar are located.
*
* @return The primary monitor, or `NULL` if an [error](@ref error_handling)
* occurred.
* @return The primary monitor, or `NULL` if no monitors were found or if an
* [error](@ref error_handling) occurred.
*
* @par Thread Safety
* This function may only be called from the main thread.
*
* @remarks The primary monitor is always first in the array returned by @ref
* glfwGetMonitors.
*
* @sa @ref monitor_monitors
* @sa glfwGetMonitors
*
@@ -1551,8 +1549,8 @@ GLFWAPI void glfwWindowHint(int target, int hint);
* requested, as not all parameters and hints are
* [hard constraints](@ref window_hints_hard). This includes the size of the
* window, especially for full screen windows. To query the actual attributes
* of the created window, framebuffer and context, use queries like @ref
* glfwGetWindowAttrib and @ref glfwGetWindowSize.
* of the created window, framebuffer and context, see @ref
* glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize.
*
* To create a full screen window, you need to specify the monitor the window
* will cover. If no monitor is specified, windowed mode will be used. Unless
@@ -1622,13 +1620,20 @@ GLFWAPI void glfwWindowHint(int target, int hint);
* `NSHighResolutionCapable` key is enabled in the application bundle's
* `Info.plist`. For more information, see
* [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html)
* in the Mac Developer Library.
* in the Mac Developer Library. The GLFW test and example programs use
* a custom `Info.plist` template for this, which can be found as
* `CMake/MacOSXBundleInfo.plist.in` in the source tree.
*
* @remarks __X11:__ There is no mechanism for setting the window icon yet.
*
* @remarks __X11:__ Some window managers will not respect the placement of
* initially hidden windows.
*
* @remarks __X11:__ Due to the asynchronous nature of X11, it may take
* a moment for a window to reach its requested state. This means you may not
* be able to query the final size, position or other attributes directly after
* window creation.
*
* @par Reentrancy
* This function may not be called from a callback.
*
@@ -1718,6 +1723,9 @@ GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value);
* @param[in] window The window whose title to change.
* @param[in] title The UTF-8 encoded window title.
*
* @remarks __OS X:__ The window title will not be updated until the next time
* you process events.
*
* @par Thread Safety
* This function may only be called from the main thread.
*
@@ -2035,6 +2043,14 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
* @return The value of the attribute, or zero if an
* [error](@ref error_handling) occurred.
*
* @remarks Framebuffer related hints are not window attributes. See @ref
* window_attribs_fb for more information.
*
* @remarks Zero is a valid value for many window and context related
* attributes so you cannot use a return value of zero as an indication of
* errors. However, this function should not fail as long as it is passed
* valid arguments and the library has been [initialized](@ref intro_init).
*
* @par Thread Safety
* This function may only be called from the main thread.
*
@@ -2561,9 +2577,9 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
* @param[in] ypos The desired y-coordinate, relative to the top edge of the
* client area.
*
* @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it
* may take a moment for the window focus event to arrive. This means you will
* not be able to set the cursor position directly after window creation.
* @remarks __X11:__ Due to the asynchronous nature of X11, it may take
* a moment for the window focus event to arrive. This means you may not be
* able to set the cursor position directly after window creation.
*
* @par Thread Safety
* This function may only be called from the main thread.
@@ -2583,9 +2599,9 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos);
* glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor.
* Any remaining cursors are destroyed by @ref glfwTerminate.
*
* The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They
* are arranged canonically as packed sequential rows, starting from the
* top-left corner.
* The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight
* bits per channel. They are arranged canonically as packed sequential rows,
* starting from the top-left corner.
*
* The cursor hotspot is specified in pixels, relative to the upper-left corner
* of the cursor image. Like all other coordinate systems in GLFW, the X-axis
@@ -3061,7 +3077,9 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
/*! @brief Returns the contents of the clipboard as a string.
*
* This function returns the contents of the system clipboard, if it contains
* or is convertible to a UTF-8 encoded string.
* or is convertible to a UTF-8 encoded string. If the clipboard is empty or
* if its contents cannot be converted, `NULL` is returned and a @ref
* GLFW_FORMAT_UNAVAILABLE error is generated.
*
* @param[in] window The window that will request the clipboard contents.
* @return The contents of the clipboard as a UTF-8 encoded string, or `NULL`
@@ -3286,15 +3304,15 @@ GLFWAPI int glfwExtensionSupported(const char* extension);
* without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
*
* @param[in] procname The ASCII encoded name of the function.
* @return The address of the function, or `NULL` if the function is
* unavailable or an [error](@ref error_handling) occurred.
* @return The address of the function, or `NULL` if an [error](@ref
* error_handling) occurred.
*
* @remarks The addresses of a given function is not guaranteed to be the same
* @remarks The address of a given function is not guaranteed to be the same
* between contexts.
*
* @remarks This function may return a non-`NULL` address despite the
* associated version or extension not being available. Always check the
* context version or extension string presence first.
* context version or extension string first.
*
* @par Pointer Lifetime
* The returned function pointer is valid until the context is destroyed or the
+1 -3
View File
@@ -249,7 +249,7 @@ void _glfwPlatformTerminate(void)
const char* _glfwPlatformGetVersionString(void)
{
const char* version = _GLFW_VERSION_NUMBER " Cocoa"
return _GLFW_VERSION_NUMBER " Cocoa"
#if defined(_GLFW_NSGL)
" NSGL"
#endif
@@ -266,7 +266,5 @@ const char* _glfwPlatformGetVersionString(void)
" dynamic"
#endif
;
return version;
}
+23 -45
View File
@@ -252,50 +252,29 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
*count = 0;
CGGetOnlineDisplayList(0, NULL, &displayCount);
displays = calloc(displayCount, sizeof(CGDirectDisplayID));
monitors = calloc(displayCount, sizeof(_GLFWmonitor*));
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
NSArray* screens = [NSScreen screens];
for (i = 0; i < displayCount; i++)
{
int j;
_GLFWmonitor* monitor;
CGDirectDisplayID screenDisplayID = CGDisplayMirrorsDisplay(displays[i]);
if (screenDisplayID == kCGNullDirectDisplay)
screenDisplayID = displays[i];
if (CGDisplayIsAsleep(displays[i]))
continue;
const CGSize size = CGDisplayScreenSize(displays[i]);
char* name = getDisplayName(displays[i]);
monitors[found] = _glfwAllocMonitor(name, size.width, size.height);
monitors[found]->ns.displayID = displays[i];
monitor = _glfwAllocMonitor(name, size.width, size.height);
monitor->ns.displayID = displays[i];
monitor->ns.unitNumber = CGDisplayUnitNumber(displays[i]);
free(name);
for (j = 0; j < [screens count]; j++)
{
NSScreen* screen = [screens objectAtIndex:j];
NSDictionary* dictionary = [screen deviceDescription];
NSNumber* number = [dictionary objectForKey:@"NSScreenNumber"];
if ([number unsignedIntegerValue] == screenDisplayID)
{
monitors[found]->ns.screen = screen;
break;
}
}
if (monitors[found]->ns.screen)
found++;
else
{
_glfwFreeMonitor(monitors[found]);
monitors[found] = NULL;
}
found++;
monitors[found - 1] = monitor;
}
free(displays);
@@ -306,7 +285,9 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
GLboolean _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
{
return first->ns.displayID == second->ns.displayID;
// HACK: Compare unit numbers instead of display IDs to work around display
// replacement on machines with automatic graphics switching
return first->ns.unitNumber == second->ns.unitNumber;
}
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
@@ -319,22 +300,22 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
*ypos = (int) bounds.origin.y;
}
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
{
CFArrayRef modes;
CFIndex count, i, j;
CFIndex found, i, j;
GLFWvidmode* result;
CVDisplayLinkRef link;
*count = 0;
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
count = CFArrayGetCount(modes);
found = CFArrayGetCount(modes);
result = calloc(found, sizeof(GLFWvidmode));
result = calloc(count, sizeof(GLFWvidmode));
*found = 0;
for (i = 0; i < count; i++)
for (i = 0; i < found; i++)
{
CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
if (!modeIsGood(dm))
@@ -342,24 +323,21 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
for (j = 0; j < *found; j++)
for (j = 0; j < *count; j++)
{
if (_glfwCompareVideoModes(result + j, &mode) == 0)
break;
}
if (i < *found)
{
// This is a duplicate, so skip it
// Skip duplicate modes
if (i < *count)
continue;
}
result[*found] = mode;
(*found)++;
(*count)++;
result[*count - 1] = mode;
}
CFRelease(modes);
CVDisplayLinkRelease(link);
return result;
}
+7 -9
View File
@@ -24,9 +24,8 @@
//
//========================================================================
#ifndef _cocoa_platform_h_
#define _cocoa_platform_h_
#ifndef _glfw3_cocoa_platform_h_
#define _glfw3_cocoa_platform_h_
#include <stdint.h>
@@ -38,15 +37,14 @@ typedef void* id;
#endif
#include "posix_tls.h"
#include "iokit_joystick.h"
#if defined(_GLFW_NSGL)
#include "nsgl_context.h"
#else
#error "No supported context creation API selected"
#error "The Cocoa backend depends on NSGL platform support"
#endif
#include "iokit_joystick.h"
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS ns
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeNS ns_time
@@ -59,7 +57,7 @@ typedef void* id;
typedef struct _GLFWwindowNS
{
id object;
id delegate;
id delegate;
id view;
unsigned int modifierFlags;
@@ -92,7 +90,7 @@ typedef struct _GLFWmonitorNS
{
CGDirectDisplayID displayID;
CGDisplayModeRef previousMode;
id screen;
uint32_t unitNumber;
} _GLFWmonitorNS;
@@ -121,4 +119,4 @@ void _glfwInitTimer(void);
GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwRestoreVideoMode(_GLFWmonitor* monitor);
#endif // _cocoa_platform_h_
#endif // _glfw3_cocoa_platform_h_
+96 -61
View File
@@ -83,13 +83,16 @@ static void updateModeCursor(_GLFWwindow* window)
//
static GLboolean enterFullscreenMode(_GLFWwindow* window)
{
GLFWvidmode mode;
GLboolean status;
int xpos, ypos;
status = _glfwSetVideoMode(window->monitor, &window->videoMode);
// NOTE: The window is resized despite mode setting failure to make
// glfwSetWindowSize more robust
[window->ns.object setFrame:[window->monitor->ns.screen frame]
_glfwPlatformGetVideoMode(window->monitor, &mode);
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
[window->ns.object setFrame:NSMakeRect(xpos, ypos, mode.width, mode.height)
display:YES];
return status;
@@ -123,6 +126,34 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
return contentRect;
}
// Translates OS X key modifiers into GLFW ones
//
static int translateFlags(NSUInteger flags)
{
int mods = 0;
if (flags & NSShiftKeyMask)
mods |= GLFW_MOD_SHIFT;
if (flags & NSControlKeyMask)
mods |= GLFW_MOD_CONTROL;
if (flags & NSAlternateKeyMask)
mods |= GLFW_MOD_ALT;
if (flags & NSCommandKeyMask)
mods |= GLFW_MOD_SUPER;
return mods;
}
// Translates a OS X keycode to a GLFW keycode
//
static int translateKey(unsigned int key)
{
if (key >= sizeof(_glfw.ns.publicKeys) / sizeof(_glfw.ns.publicKeys[0]))
return GLFW_KEY_UNKNOWN;
return _glfw.ns.publicKeys[key];
}
//------------------------------------------------------------------------
// Delegate for window related notifications
@@ -156,7 +187,9 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
- (void)windowDidResize:(NSNotification *)notification
{
if (_glfw.focusedWindow == window &&
[window->nsgl.context update];
if (_glfw.cursorWindow == window &&
window->cursorMode == GLFW_CURSOR_DISABLED)
{
centerCursor(window);
@@ -167,12 +200,13 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
_glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
_glfwInputWindowSize(window, contentRect.size.width, contentRect.size.height);
_glfwInputWindowDamage(window);
}
- (void)windowDidMove:(NSNotification *)notification
{
if (_glfw.focusedWindow == window &&
[window->nsgl.context update];
if (_glfw.cursorWindow == window &&
window->cursorMode == GLFW_CURSOR_DISABLED)
{
centerCursor(window);
@@ -185,20 +219,23 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
- (void)windowDidMiniaturize:(NSNotification *)notification
{
if (window->monitor)
leaveFullscreenMode(window);
_glfwInputWindowIconify(window, GL_TRUE);
}
- (void)windowDidDeminiaturize:(NSNotification *)notification
{
if (window->monitor)
enterFullscreenMode(window);
_glfwInputWindowIconify(window, GL_FALSE);
}
- (void)windowDidBecomeKey:(NSNotification *)notification
{
if (window->monitor)
enterFullscreenMode(window);
if (_glfw.focusedWindow == window &&
if (_glfw.cursorWindow == window &&
window->cursorMode == GLFW_CURSOR_DISABLED)
{
centerCursor(window);
@@ -210,8 +247,8 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
- (void)windowDidResignKey:(NSNotification *)notification
{
if (window->monitor)
leaveFullscreenMode(window);
if (window->monitor && window->autoIconify)
_glfwPlatformIconifyWindow(window);
_glfwInputWindowFocus(window, GL_FALSE);
}
@@ -250,42 +287,22 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
_glfwPlatformPostEmptyEvent();
}
- (void)applicationDidHide:(NSNotification *)notification
{
int i;
for (i = 0; i < _glfw.monitorCount; i++)
_glfwRestoreVideoMode(_glfw.monitors[i]);
}
@end
// Translates OS X key modifiers into GLFW ones
//
static int translateFlags(NSUInteger flags)
{
int mods = 0;
if (flags & NSShiftKeyMask)
mods |= GLFW_MOD_SHIFT;
if (flags & NSControlKeyMask)
mods |= GLFW_MOD_CONTROL;
if (flags & NSAlternateKeyMask)
mods |= GLFW_MOD_ALT;
if (flags & NSCommandKeyMask)
mods |= GLFW_MOD_SUPER;
return mods;
}
// Translates a OS X keycode to a GLFW keycode
//
static int translateKey(unsigned int key)
{
if (key >= sizeof(_glfw.ns.publicKeys) / sizeof(_glfw.ns.publicKeys[0]))
return GLFW_KEY_UNKNOWN;
return _glfw.ns.publicKeys[key];
}
//------------------------------------------------------------------------
// Content view class for the GLFW window
//------------------------------------------------------------------------
@interface GLFWContentView : NSOpenGLView
@interface GLFWContentView : NSView
{
_GLFWwindow* window;
NSTrackingArea* trackingArea;
@@ -313,8 +330,7 @@ static int translateKey(unsigned int key)
- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow
{
self = [super initWithFrame:NSMakeRect(0, 0, 1, 1)
pixelFormat:nil];
self = [super init];
if (self != nil)
{
window = initWindow;
@@ -453,6 +469,10 @@ static int translateKey(unsigned int key)
const NSRect fbRect = convertRectToBacking(window, contentRect);
_glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
}
- (void)drawRect:(NSRect)rect
{
_glfwInputWindowDamage(window);
}
@@ -719,6 +739,7 @@ static void createMenuBar(void)
[[appMenu addItemWithTitle:@"Services"
action:NULL
keyEquivalent:@""] setSubmenu:servicesMenu];
[servicesMenu release];
[appMenu addItem:[NSMenuItem separatorItem]];
[appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName]
action:@selector(hide:)
@@ -737,6 +758,7 @@ static void createMenuBar(void)
NSMenuItem* windowMenuItem =
[bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
[bar release];
NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
[NSApp setWindowsMenu:windowMenu];
[windowMenuItem setSubmenu:windowMenu];
@@ -838,7 +860,15 @@ static GLboolean createWindow(_GLFWwindow* window,
NSRect contentRect;
if (wndconfig->monitor)
contentRect = [wndconfig->monitor->ns.screen frame];
{
GLFWvidmode mode;
int xpos, ypos;
_glfwPlatformGetVideoMode(window->monitor, &mode);
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
contentRect = NSMakeRect(xpos, ypos, mode.width, mode.height);
}
else
contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height);
@@ -865,7 +895,6 @@ static GLboolean createWindow(_GLFWwindow* window,
if (wndconfig->monitor)
{
[window->ns.object setLevel:NSMainMenuWindowLevel + 1];
[window->ns.object setHidesOnDeactivate:YES];
}
else
{
@@ -875,9 +904,19 @@ static GLboolean createWindow(_GLFWwindow* window,
[window->ns.object setLevel:NSFloatingWindowLevel];
}
window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
#if defined(_GLFW_USE_RETINA)
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
#endif /*_GLFW_USE_RETINA*/
[window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]];
[window->ns.object setDelegate:window->ns.delegate];
[window->ns.object setAcceptsMouseMovedEvents:YES];
[window->ns.object setContentView:window->ns.view];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
@@ -906,22 +945,6 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (!_glfwCreateContext(window, ctxconfig, fbconfig))
return GL_FALSE;
window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
#if defined(_GLFW_USE_RETINA)
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
#endif /*_GLFW_USE_RETINA*/
[window->ns.object setContentView:window->ns.view];
// NOTE: If you set the pixel format before the context it creates another
// context, only to have it destroyed by the next line
// We cannot use the view to create the context because that interface
// does not support context resource sharing
[window->ns.view setOpenGLContext:window->nsgl.context];
[window->ns.view setPixelFormat:window->nsgl.pixelFormat];
[window->nsgl.context setView:window->ns.view];
if (wndconfig->monitor)
@@ -1148,8 +1171,14 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
}
else
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
const NSRect localRect = NSMakeRect(x, contentRect.size.height - y - 1, 0, 0);
const NSRect globalRect = [window->ns.object convertRectToScreen:localRect];
const NSPoint globalPoint = globalRect.origin;
#else
const NSPoint localPoint = NSMakePoint(x, contentRect.size.height - y - 1);
const NSPoint globalPoint = [window->ns.object convertBaseToScreen:localPoint];
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
CGWarpMouseCursorPosition(CGPointMake(globalPoint.x,
transformY(globalPoint.y)));
@@ -1173,6 +1202,9 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
NSImage* native;
NSBitmapImageRep* rep;
if (!initializeAppKit())
return GL_FALSE;
rep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:NULL
pixelsWide:image->width
@@ -1208,6 +1240,9 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
{
if (!initializeAppKit())
return GL_FALSE;
cursor->ns.object = getStandardCursor(shape);
if (!cursor->ns.object)
{
+21 -22
View File
@@ -38,6 +38,7 @@
static GLboolean parseVersionString(int* api, int* major, int* minor, int* rev)
{
int i;
_GLFWwindow* window;
const char* version;
const char* prefixes[] =
{
@@ -49,7 +50,9 @@ static GLboolean parseVersionString(int* api, int* major, int* minor, int* rev)
*api = GLFW_OPENGL_API;
version = (const char*) glGetString(GL_VERSION);
window = _glfwPlatformGetCurrentContext();
version = (const char*) window->GetString(GL_VERSION);
if (!version)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
@@ -352,6 +355,10 @@ GLboolean _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
window->GetIntegerv = (PFNGLGETINTEGERVPROC) glfwGetProcAddress("glGetIntegerv");
window->GetString = (PFNGLGETSTRINGPROC) glfwGetProcAddress("glGetString");
window->Clear = (PFNGLCLEARPROC) glfwGetProcAddress("glClear");
if (!parseVersionString(&window->context.api,
&window->context.major,
&window->context.minor,
@@ -382,7 +389,7 @@ GLboolean _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
if (window->context.major >= 3)
{
GLint flags;
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
window->GetIntegerv(GL_CONTEXT_FLAGS, &flags);
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
window->context.forward = GL_TRUE;
@@ -404,7 +411,7 @@ GLboolean _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
(window->context.major == 3 && window->context.minor >= 2))
{
GLint mask;
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
window->GetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
@@ -427,7 +434,7 @@ GLboolean _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
// only present from 3.0 while the extension applies from 1.1
GLint strategy;
glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
window->GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
@@ -444,7 +451,7 @@ GLboolean _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
// one, so we can reuse them here
GLint strategy;
glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
window->GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
@@ -456,7 +463,7 @@ GLboolean _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
if (glfwExtensionSupported("GL_KHR_context_flush_control"))
{
GLint behavior;
glGetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior);
window->GetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior);
if (behavior == GL_NONE)
window->context.release = GLFW_RELEASE_BEHAVIOR_NONE;
@@ -490,19 +497,16 @@ GLboolean _glfwIsValidContext(const _GLFWctxconfig* ctxconfig)
return GL_TRUE;
}
int _glfwStringInExtensionString(const char* string, const GLubyte* extensions)
int _glfwStringInExtensionString(const char* string, const char* extensions)
{
const GLubyte* start;
GLubyte* where;
GLubyte* terminator;
const char* start = extensions;
// It takes a bit of care to be fool-proof about parsing the
// OpenGL extensions string. Don't be fooled by sub-strings,
// etc.
start = extensions;
for (;;)
{
where = (GLubyte*) strstr((const char*) start, string);
const char* where;
const char* terminator;
where = strstr(start, string);
if (!where)
return GL_FALSE;
@@ -527,12 +531,7 @@ int _glfwStringInExtensionString(const char* string, const GLubyte* extensions)
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT();
if (_glfwPlatformGetCurrentContext() == window)
return;
_glfwPlatformMakeContextCurrent(window);
}
@@ -589,7 +588,7 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
// Check if extension is in the modern OpenGL extensions string list
glGetIntegerv(GL_NUM_EXTENSIONS, &count);
window->GetIntegerv(GL_NUM_EXTENSIONS, &count);
for (i = 0; i < count; i++)
{
@@ -610,7 +609,7 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
{
// Check if extension is in the old style OpenGL extensions string
const GLubyte* extensions = glGetString(GL_EXTENSIONS);
const char* extensions = (const char*) window->GetString(GL_EXTENSIONS);
if (!extensions)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
+228 -74
View File
@@ -78,7 +78,7 @@ static const char* getErrorString(EGLint error)
static int getConfigAttrib(EGLConfig config, int attrib)
{
int value;
eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
_glfw_eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
return value;
}
@@ -93,7 +93,7 @@ static GLboolean chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* closest;
int i, nativeCount, usableCount;
eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
_glfw_eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
if (!nativeCount)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
@@ -101,7 +101,8 @@ static GLboolean chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
}
nativeConfigs = calloc(nativeCount, sizeof(EGLConfig));
eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount);
_glfw_eglGetConfigs(_glfw.egl.display, nativeConfigs,
nativeCount, &nativeCount);
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
usableCount = 0;
@@ -112,24 +113,18 @@ static GLboolean chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
_GLFWfbconfig* u = usableConfigs + usableCount;
#if defined(_GLFW_X11)
// Only consider EGLConfigs with associated visuals
if (!getConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
{
// Only consider EGLConfigs with associated visuals
continue;
}
#endif // _GLFW_X11
// Only consider RGB(A) EGLConfigs
if (!(getConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) & EGL_RGB_BUFFER))
{
// Only consider RGB(A) EGLConfigs
continue;
}
// Only consider window EGLConfigs
if (!(getConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
{
// Only consider window EGLConfigs
continue;
}
if (ctxconfig->api == GLFW_OPENGL_ES_API)
{
@@ -184,30 +179,91 @@ static GLboolean chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
//
int _glfwInitContextAPI(void)
{
if (!_glfwInitTLS())
int i;
const char* sonames[] =
{
#if defined(_GLFW_WIN32)
"libEGL.dll",
"EGL.dll",
#elif defined(_GLFW_COCOA)
"libEGL.dylib",
#else
"libEGL.so.1",
#endif
NULL
};
if (!_glfwCreateContextTLS())
return GL_FALSE;
_glfw.egl.display = eglGetDisplay((EGLNativeDisplayType)_GLFW_EGL_NATIVE_DISPLAY);
for (i = 0; sonames[i]; i++)
{
_glfw.egl.handle = _glfw_dlopen(sonames[i]);
if (_glfw.egl.handle)
break;
}
if (!_glfw.egl.handle)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to load EGL");
return GL_FALSE;
}
_glfw.egl.GetConfigAttrib =
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
_glfw.egl.GetConfigs =
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
_glfw.egl.GetDisplay =
_glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
_glfw.egl.GetError =
_glfw_dlsym(_glfw.egl.handle, "eglGetError");
_glfw.egl.Initialize =
_glfw_dlsym(_glfw.egl.handle, "eglInitialize");
_glfw.egl.Terminate =
_glfw_dlsym(_glfw.egl.handle, "eglTerminate");
_glfw.egl.BindAPI =
_glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
_glfw.egl.CreateContext =
_glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
_glfw.egl.DestroySurface =
_glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
_glfw.egl.DestroyContext =
_glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
_glfw.egl.CreateWindowSurface =
_glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
_glfw.egl.MakeCurrent =
_glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
_glfw.egl.SwapBuffers =
_glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
_glfw.egl.SwapInterval =
_glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
_glfw.egl.QueryString =
_glfw_dlsym(_glfw.egl.handle, "eglQueryString");
_glfw.egl.GetProcAddress =
_glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");
_glfw.egl.display =
_glfw_eglGetDisplay((EGLNativeDisplayType)_GLFW_EGL_NATIVE_DISPLAY);
if (_glfw.egl.display == EGL_NO_DISPLAY)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to get EGL display: %s",
getErrorString(eglGetError()));
getErrorString(_glfw_eglGetError()));
return GL_FALSE;
}
if (!eglInitialize(_glfw.egl.display,
&_glfw.egl.versionMajor,
&_glfw.egl.versionMinor))
if (!_glfw_eglInitialize(_glfw.egl.display,
&_glfw.egl.major,
&_glfw.egl.minor))
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to initialize EGL: %s",
getErrorString(eglGetError()));
getErrorString(_glfw_eglGetError()));
return GL_FALSE;
}
if (_glfwPlatformExtensionSupported("EGL_KHR_create_context"))
_glfw.egl.KHR_create_context = GL_TRUE;
_glfw.egl.KHR_create_context =
_glfwPlatformExtensionSupported("EGL_KHR_create_context");
return GL_TRUE;
}
@@ -216,9 +272,16 @@ int _glfwInitContextAPI(void)
//
void _glfwTerminateContextAPI(void)
{
eglTerminate(_glfw.egl.display);
if (_glfw_eglTerminate)
_glfw_eglTerminate(_glfw.egl.display);
_glfwTerminateTLS();
if (_glfw.egl.handle)
{
_glfw_dlclose(_glfw.egl.handle);
_glfw.egl.handle = NULL;
}
_glfwDestroyContextTLS();
}
#define setEGLattrib(attribName, attribValue) \
@@ -243,7 +306,7 @@ int _glfwCreateContext(_GLFWwindow* window,
if (!chooseFBConfigs(ctxconfig, fbconfig, &config))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"EGL: Failed to find a suitable EGLConfig");
return GL_FALSE;
}
@@ -256,8 +319,8 @@ int _glfwCreateContext(_GLFWwindow* window,
EGLint redBits, greenBits, blueBits, alphaBits, visualID = 0;
XVisualInfo info;
eglGetConfigAttrib(_glfw.egl.display, config,
EGL_NATIVE_VISUAL_ID, &visualID);
_glfw_eglGetConfigAttrib(_glfw.egl.display, config,
EGL_NATIVE_VISUAL_ID, &visualID);
info.screen = _glfw.x11.screen;
mask = VisualScreenMask;
@@ -270,17 +333,17 @@ int _glfwCreateContext(_GLFWwindow* window,
}
else
{
// some EGL drivers don't implement the EGL_NATIVE_VISUAL_ID
// attribute, so attempt to find the closest match.
// Some EGL drivers do not implement the EGL_NATIVE_VISUAL_ID
// attribute, so attempt to find the closest match
eglGetConfigAttrib(_glfw.egl.display, config,
EGL_RED_SIZE, &redBits);
eglGetConfigAttrib(_glfw.egl.display, config,
EGL_GREEN_SIZE, &greenBits);
eglGetConfigAttrib(_glfw.egl.display, config,
EGL_BLUE_SIZE, &blueBits);
eglGetConfigAttrib(_glfw.egl.display, config,
EGL_ALPHA_SIZE, &alphaBits);
_glfw_eglGetConfigAttrib(_glfw.egl.display, config,
EGL_RED_SIZE, &redBits);
_glfw_eglGetConfigAttrib(_glfw.egl.display, config,
EGL_GREEN_SIZE, &greenBits);
_glfw_eglGetConfigAttrib(_glfw.egl.display, config,
EGL_BLUE_SIZE, &blueBits);
_glfw_eglGetConfigAttrib(_glfw.egl.display, config,
EGL_ALPHA_SIZE, &alphaBits);
info.depth = redBits + greenBits + blueBits + alphaBits;
mask |= VisualDepthMask;
@@ -299,38 +362,38 @@ int _glfwCreateContext(_GLFWwindow* window,
if (ctxconfig->api == GLFW_OPENGL_ES_API)
{
if (!eglBindAPI(EGL_OPENGL_ES_API))
if (!_glfw_eglBindAPI(EGL_OPENGL_ES_API))
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to bind OpenGL ES: %s",
getErrorString(eglGetError()));
getErrorString(_glfw_eglGetError()));
return GL_FALSE;
}
}
else
{
if (!eglBindAPI(EGL_OPENGL_API))
if (!_glfw_eglBindAPI(EGL_OPENGL_API))
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to bind OpenGL: %s",
getErrorString(eglGetError()));
getErrorString(_glfw_eglGetError()));
return GL_FALSE;
}
}
if (_glfw.egl.KHR_create_context)
{
int index = 0, mask = 0, flags = 0, strategy = 0;
int index = 0, mask = 0, flags = 0;
if (ctxconfig->api == GLFW_OPENGL_API)
{
if (ctxconfig->forward)
flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
if (ctxconfig->forward)
flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
}
if (ctxconfig->debug)
@@ -339,9 +402,15 @@ int _glfwCreateContext(_GLFWwindow* window,
if (ctxconfig->robustness)
{
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
strategy = EGL_NO_RESET_NOTIFICATION_KHR;
{
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
EGL_NO_RESET_NOTIFICATION_KHR);
}
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
strategy = EGL_LOSE_CONTEXT_ON_RESET_KHR;
{
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
EGL_LOSE_CONTEXT_ON_RESET_KHR);
}
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
}
@@ -358,9 +427,6 @@ int _glfwCreateContext(_GLFWwindow* window,
if (flags)
setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags);
if (strategy)
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, strategy);
setEGLattrib(EGL_NONE, EGL_NONE);
}
else
@@ -376,19 +442,83 @@ int _glfwCreateContext(_GLFWwindow* window,
// Context release behaviors (GL_KHR_context_flush_control) are not yet
// supported on EGL but are not a hard constraint, so ignore and continue
window->egl.context = eglCreateContext(_glfw.egl.display,
config, share, attribs);
window->egl.context = _glfw_eglCreateContext(_glfw.egl.display,
config, share, attribs);
if (window->egl.context == EGL_NO_CONTEXT)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"EGL: Failed to create context: %s",
getErrorString(eglGetError()));
getErrorString(_glfw_eglGetError()));
return GL_FALSE;
}
window->egl.config = config;
// Load the appropriate client library
{
int i;
const char** sonames;
const char* es1sonames[] =
{
#if defined(_GLFW_WIN32)
"GLESv1_CM.dll",
"libGLES_CM.dll",
#elif defined(_GLFW_COCOA)
"libGLESv1_CM.dylib",
#else
"libGLESv1_CM.so.1",
"libGLES_CM.so.1",
#endif
NULL
};
const char* es2sonames[] =
{
#if defined(_GLFW_WIN32)
"GLESv2.dll",
"libGLESv2.dll",
#elif defined(_GLFW_COCOA)
"libGLESv2.dylib",
#else
"libGLESv2.so.2",
#endif
NULL
};
const char* glsonames[] =
{
#if defined(_GLFW_WIN32)
#elif defined(_GLFW_COCOA)
#else
"libGL.so.1",
#endif
NULL
};
if (ctxconfig->api == GLFW_OPENGL_ES_API)
{
if (ctxconfig->major == 1)
sonames = es1sonames;
else
sonames = es2sonames;
}
else
sonames = glsonames;
for (i = 0; sonames[i]; i++)
{
window->egl.client = _glfw_dlopen(sonames[i]);
if (window->egl.client)
break;
}
if (!window->egl.client)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to load client library");
return GL_FALSE;
}
}
return GL_TRUE;
}
@@ -398,6 +528,19 @@ int _glfwCreateContext(_GLFWwindow* window,
//
void _glfwDestroyContext(_GLFWwindow* window)
{
#if defined(_GLFW_X11)
// NOTE: Do not unload libGL.so.1 while the X11 display is still open,
// as it will make XCloseDisplay segfault
if (window->context.api != GLFW_OPENGL_API)
#endif // _GLFW_X11
{
if (window->egl.client)
{
_glfw_dlclose(window->egl.client);
window->egl.client = NULL;
}
}
#if defined(_GLFW_X11)
if (window->egl.visual)
{
@@ -408,13 +551,13 @@ void _glfwDestroyContext(_GLFWwindow* window)
if (window->egl.surface)
{
eglDestroySurface(_glfw.egl.display, window->egl.surface);
_glfw_eglDestroySurface(_glfw.egl.display, window->egl.surface);
window->egl.surface = EGL_NO_SURFACE;
}
if (window->egl.context)
{
eglDestroyContext(_glfw.egl.display, window->egl.context);
_glfw_eglDestroyContext(_glfw.egl.display, window->egl.context);
window->egl.context = EGL_NO_CONTEXT;
}
}
@@ -443,50 +586,52 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
{
if (window->egl.surface == EGL_NO_SURFACE)
{
window->egl.surface = eglCreateWindowSurface(_glfw.egl.display,
window->egl.config,
(EGLNativeWindowType)_GLFW_EGL_NATIVE_WINDOW,
NULL);
window->egl.surface =
_glfw_eglCreateWindowSurface(_glfw.egl.display,
window->egl.config,
(EGLNativeWindowType)_GLFW_EGL_NATIVE_WINDOW,
NULL);
if (window->egl.surface == EGL_NO_SURFACE)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to create window surface: %s",
getErrorString(eglGetError()));
getErrorString(_glfw_eglGetError()));
}
}
eglMakeCurrent(_glfw.egl.display,
window->egl.surface,
window->egl.surface,
window->egl.context);
_glfw_eglMakeCurrent(_glfw.egl.display,
window->egl.surface,
window->egl.surface,
window->egl.context);
}
else
{
eglMakeCurrent(_glfw.egl.display,
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
_glfw_eglMakeCurrent(_glfw.egl.display,
EGL_NO_SURFACE,
EGL_NO_SURFACE,
EGL_NO_CONTEXT);
}
_glfwSetCurrentContext(window);
_glfwSetContextTLS(window);
}
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
{
eglSwapBuffers(_glfw.egl.display, window->egl.surface);
_glfw_eglSwapBuffers(_glfw.egl.display, window->egl.surface);
}
void _glfwPlatformSwapInterval(int interval)
{
eglSwapInterval(_glfw.egl.display, interval);
_glfw_eglSwapInterval(_glfw.egl.display, interval);
}
int _glfwPlatformExtensionSupported(const char* extension)
{
const char* extensions;
extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
if (extensions != NULL)
const char* extensions = _glfw_eglQueryString(_glfw.egl.display,
EGL_EXTENSIONS);
if (extensions)
{
if (_glfwStringInExtensionString(extension, (unsigned char*) extensions))
if (_glfwStringInExtensionString(extension, extensions))
return GL_TRUE;
}
@@ -495,7 +640,16 @@ int _glfwPlatformExtensionSupported(const char* extension)
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
{
return eglGetProcAddress(procname);
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (window->egl.client)
{
GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->egl.client, procname);
if (proc)
return proc;
}
return _glfw_eglGetProcAddress(procname);
}
+73 -12
View File
@@ -25,8 +25,19 @@
//
//========================================================================
#ifndef _egl_context_h_
#define _egl_context_h_
#ifndef _glfw3_egl_context_h_
#define _glfw3_egl_context_h_
#if defined(_GLFW_WIN32)
#define _glfw_dlopen(name) LoadLibraryA(name)
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
#else
#include <dlfcn.h>
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle)
#define _glfw_dlsym(handle, name) dlsym(handle, name)
#endif
#include <EGL/egl.h>
@@ -35,10 +46,39 @@
// extensions and not all operating systems come with an up-to-date version
#include "../deps/EGL/eglext.h"
// Do we have support for dlopen/dlsym?
#if defined(_GLFW_HAS_DLOPEN)
#include <dlfcn.h>
#endif
// EGL function pointer typedefs
typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGATTRIBPROC)(EGLDisplay,EGLConfig,EGLint,EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGSPROC)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType);
typedef EGLint (EGLAPIENTRY * PFNEGLGETERRORPROC)(void);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLINITIALIZEPROC)(EGLDisplay,EGLint*,EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLTERMINATEPROC)(EGLDisplay);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLBINDAPIPROC)(EGLenum);
typedef EGLContext (EGLAPIENTRY * PFNEGLCREATECONTEXTPROC)(EGLDisplay,EGLConfig,EGLContext,const EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYSURFACEPROC)(EGLDisplay,EGLSurface);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYCONTEXTPROC)(EGLDisplay,EGLContext);
typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLMAKECURRENTPROC)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPBUFFERSPROC)(EGLDisplay,EGLSurface);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPINTERVALPROC)(EGLDisplay,EGLint);
typedef const char* (EGLAPIENTRY * PFNEGLQUERYSTRINGPROC)(EGLDisplay,EGLint);
typedef GLFWglproc (EGLAPIENTRY * PFNEGLGETPROCADDRESSPROC)(const char*);
#define _glfw_eglGetConfigAttrib _glfw.egl.GetConfigAttrib
#define _glfw_eglGetConfigs _glfw.egl.GetConfigs
#define _glfw_eglGetDisplay _glfw.egl.GetDisplay
#define _glfw_eglGetError _glfw.egl.GetError
#define _glfw_eglInitialize _glfw.egl.Initialize
#define _glfw_eglTerminate _glfw.egl.Terminate
#define _glfw_eglBindAPI _glfw.egl.BindAPI
#define _glfw_eglCreateContext _glfw.egl.CreateContext
#define _glfw_eglDestroySurface _glfw.egl.DestroySurface
#define _glfw_eglDestroyContext _glfw.egl.DestroyContext
#define _glfw_eglCreateWindowSurface _glfw.egl.CreateWindowSurface
#define _glfw_eglMakeCurrent _glfw.egl.MakeCurrent
#define _glfw_eglSwapBuffers _glfw.egl.SwapBuffers
#define _glfw_eglSwapInterval _glfw.egl.SwapInterval
#define _glfw_eglQueryString _glfw.egl.QueryString
#define _glfw_eglGetProcAddress _glfw.egl.GetProcAddress
#define _GLFW_PLATFORM_FBCONFIG EGLConfig egl
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextEGL egl
@@ -49,14 +89,16 @@
//
typedef struct _GLFWcontextEGL
{
EGLConfig config;
EGLContext context;
EGLSurface surface;
EGLConfig config;
EGLContext context;
EGLSurface surface;
#if defined(_GLFW_X11)
XVisualInfo* visual;
XVisualInfo* visual;
#endif
void* client;
} _GLFWcontextEGL;
@@ -65,10 +107,29 @@ typedef struct _GLFWcontextEGL
typedef struct _GLFWlibraryEGL
{
EGLDisplay display;
EGLint versionMajor, versionMinor;
EGLint major, minor;
GLboolean KHR_create_context;
void* handle;
PFNEGLGETCONFIGATTRIBPROC GetConfigAttrib;
PFNEGLGETCONFIGSPROC GetConfigs;
PFNEGLGETDISPLAYPROC GetDisplay;
PFNEGLGETERRORPROC GetError;
PFNEGLINITIALIZEPROC Initialize;
PFNEGLTERMINATEPROC Terminate;
PFNEGLBINDAPIPROC BindAPI;
PFNEGLCREATECONTEXTPROC CreateContext;
PFNEGLDESTROYSURFACEPROC DestroySurface;
PFNEGLDESTROYCONTEXTPROC DestroyContext;
PFNEGLCREATEWINDOWSURFACEPROC CreateWindowSurface;
PFNEGLMAKECURRENTPROC MakeCurrent;
PFNEGLSWAPBUFFERSPROC SwapBuffers;
PFNEGLSWAPINTERVALPROC SwapInterval;
PFNEGLQUERYSTRINGPROC QueryString;
PFNEGLGETPROCADDRESSPROC GetProcAddress;
} _GLFWlibraryEGL;
@@ -82,4 +143,4 @@ int _glfwAnalyzeContext(const _GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig);
#endif // _egl_context_h_
#endif // _glfw3_egl_context_h_
+2 -12
View File
@@ -57,23 +57,13 @@
// Define this to 1 if building as a shared library / dynamic library / DLL
#cmakedefine _GLFW_BUILD_DLL
// Define this to 1 if glfwSwapInterval should ignore DWM compositing status
#cmakedefine _GLFW_USE_DWM_SWAP_INTERVAL
// Define this to 1 to force use of high-performance GPU on Optimus systems
#cmakedefine _GLFW_USE_OPTIMUS_HPG
// Define this to 1 to force use of high-performance GPU on hybrid systems
#cmakedefine _GLFW_USE_HYBRID_HPG
// Define this to 1 if the XInput X11 extension is available
#cmakedefine _GLFW_HAS_XINPUT
// Define this to 1 if the Xxf86vm X11 extension is available
#cmakedefine _GLFW_HAS_XF86VM
// Define this to 1 if glXGetProcAddress is available
#cmakedefine _GLFW_HAS_GLXGETPROCADDRESS
// Define this to 1 if glXGetProcAddressARB is available
#cmakedefine _GLFW_HAS_GLXGETPROCADDRESSARB
// Define this to 1 if glXGetProcAddressEXT is available
#cmakedefine _GLFW_HAS_GLXGETPROCADDRESSEXT
// Define this to 1 if dlopen is available
#cmakedefine _GLFW_HAS_DLOPEN
// Define this to 1 if glfwInit should change the current directory
#cmakedefine _GLFW_USE_CHDIR
+116 -93
View File
@@ -30,11 +30,7 @@
#include <string.h>
#include <stdlib.h>
#include <assert.h>
// This is the only glXGetProcAddress variant not declared by glxext.h
void (*glXGetProcAddressEXT(const GLubyte* procName))();
#include <dlfcn.h>
#ifndef GLXBadProfileARB
#define GLXBadProfileARB 13
@@ -46,7 +42,7 @@ void (*glXGetProcAddressEXT(const GLubyte* procName))();
static int getFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
{
int value;
glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value);
_glfw_glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value);
return value;
}
@@ -61,16 +57,14 @@ static GLboolean chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* resul
const char* vendor;
GLboolean trustWindowBit = GL_TRUE;
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
// HACK: This is a (hopefully temporary) workaround for Chromium
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
vendor = _glfw_glXGetClientString(_glfw.x11.display, GLX_VENDOR);
if (strcmp(vendor, "Chromium") == 0)
{
// HACK: This is a (hopefully temporary) workaround for Chromium
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
trustWindowBit = GL_FALSE;
}
nativeConfigs = glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen,
&nativeCount);
nativeConfigs = _glfw_glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen,
&nativeCount);
if (!nativeCount)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
@@ -85,25 +79,19 @@ static GLboolean chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* resul
const GLXFBConfig n = nativeConfigs[i];
_GLFWfbconfig* u = usableConfigs + usableCount;
// Only consider GLXFBConfigs with associated visuals
if (!getFBConfigAttrib(n, GLX_VISUAL_ID))
{
// Only consider GLXFBConfigs with associated visuals
continue;
}
// Only consider RGBA GLXFBConfigs
if (!(getFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))
{
// Only consider RGBA GLXFBConfigs
continue;
}
// Only consider window GLXFBConfigs
if (!(getFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT))
{
if (trustWindowBit)
{
// Only consider window GLXFBConfigs
continue;
}
}
u->redBits = getFBConfigAttrib(n, GLX_RED_SIZE);
@@ -129,7 +117,7 @@ static GLboolean chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* resul
if (_glfw.glx.ARB_multisample)
u->samples = getFBConfigAttrib(n, GLX_SAMPLES);
if (_glfw.glx.ARB_framebuffer_sRGB)
if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB)
u->sRGB = getFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
u->glx = n;
@@ -152,11 +140,11 @@ static GLXContext createLegacyContext(_GLFWwindow* window,
GLXFBConfig fbconfig,
GLXContext share)
{
return glXCreateNewContext(_glfw.x11.display,
fbconfig,
GLX_RGBA_TYPE,
share,
True);
return _glfw_glXCreateNewContext(_glfw.x11.display,
fbconfig,
GLX_RGBA_TYPE,
share,
True);
}
@@ -168,36 +156,67 @@ static GLXContext createLegacyContext(_GLFWwindow* window,
//
int _glfwInitContextAPI(void)
{
if (!_glfwInitTLS())
return GL_FALSE;
#ifdef _GLFW_DLOPEN_LIBGL
_glfw.glx.libGL = dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL);
if (!_glfw.glx.libGL)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to find libGL");
return GL_FALSE;
}
#if defined(__CYGWIN__)
const char* soname = "libGL-1.so";
#else
const char* soname = "libGL.so.1";
#endif
if (!glXQueryExtension(_glfw.x11.display,
&_glfw.glx.errorBase,
&_glfw.glx.eventBase))
if (!_glfwCreateContextTLS())
return GL_FALSE;
_glfw.glx.handle = dlopen(soname, RTLD_LAZY | RTLD_GLOBAL);
if (!_glfw.glx.handle)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: %s", dlerror());
return GL_FALSE;
}
_glfw.glx.GetFBConfigs =
dlsym(_glfw.glx.handle, "glXGetFBConfigs");
_glfw.glx.GetFBConfigAttrib =
dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib");
_glfw.glx.GetClientString =
dlsym(_glfw.glx.handle, "glXGetClientString");
_glfw.glx.QueryExtension =
dlsym(_glfw.glx.handle, "glXQueryExtension");
_glfw.glx.QueryVersion =
dlsym(_glfw.glx.handle, "glXQueryVersion");
_glfw.glx.DestroyContext =
dlsym(_glfw.glx.handle, "glXDestroyContext");
_glfw.glx.MakeCurrent =
dlsym(_glfw.glx.handle, "glXMakeCurrent");
_glfw.glx.SwapBuffers =
dlsym(_glfw.glx.handle, "glXSwapBuffers");
_glfw.glx.QueryExtensionsString =
dlsym(_glfw.glx.handle, "glXQueryExtensionsString");
_glfw.glx.CreateNewContext =
dlsym(_glfw.glx.handle, "glXCreateNewContext");
_glfw.glx.GetVisualFromFBConfig =
dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
_glfw.glx.GetProcAddress =
dlsym(_glfw.glx.handle, "glXGetProcAddress");
_glfw.glx.GetProcAddressARB =
dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
if (!_glfw_glXQueryExtension(_glfw.x11.display,
&_glfw.glx.errorBase,
&_glfw.glx.eventBase))
{
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: GLX extension not found");
return GL_FALSE;
}
if (!glXQueryVersion(_glfw.x11.display,
&_glfw.glx.versionMajor,
&_glfw.glx.versionMinor))
if (!_glfw_glXQueryVersion(_glfw.x11.display,
&_glfw.glx.major,
&_glfw.glx.minor))
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"GLX: Failed to query GLX version");
return GL_FALSE;
}
if (_glfw.glx.versionMajor == 1 && _glfw.glx.versionMinor < 3)
if (_glfw.glx.major == 1 && _glfw.glx.minor < 3)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"GLX: GLX version 1.3 is required");
@@ -237,6 +256,9 @@ int _glfwInitContextAPI(void)
if (_glfwPlatformExtensionSupported("GLX_ARB_framebuffer_sRGB"))
_glfw.glx.ARB_framebuffer_sRGB = GL_TRUE;
if (_glfwPlatformExtensionSupported("GLX_EXT_framebuffer_sRGB"))
_glfw.glx.EXT_framebuffer_sRGB = GL_TRUE;
if (_glfwPlatformExtensionSupported("GLX_ARB_create_context"))
{
_glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
@@ -265,16 +287,16 @@ int _glfwInitContextAPI(void)
//
void _glfwTerminateContextAPI(void)
{
// Unload libGL.so if necessary
#ifdef _GLFW_DLOPEN_LIBGL
if (_glfw.glx.libGL != NULL)
{
dlclose(_glfw.glx.libGL);
_glfw.glx.libGL = NULL;
}
#endif
// NOTE: This function may not call any X11 functions, as it is called after
// XCloseDisplay (see _glfwPlatformTerminate for details)
_glfwTerminateTLS();
if (_glfw.glx.handle)
{
dlclose(_glfw.glx.handle);
_glfw.glx.handle = NULL;
}
_glfwDestroyContextTLS();
}
#define setGLXattrib(attribName, attribValue) \
@@ -291,7 +313,7 @@ int _glfwCreateContext(_GLFWwindow* window,
const _GLFWfbconfig* fbconfig)
{
int attribs[40];
GLXFBConfig native;
GLXFBConfig native = NULL;
GLXContext share = NULL;
if (ctxconfig->share)
@@ -299,13 +321,13 @@ int _glfwCreateContext(_GLFWwindow* window,
if (!chooseFBConfig(fbconfig, &native))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"GLX: Failed to find a suitable GLXFBConfig");
return GL_FALSE;
}
// Retrieve the corresponding visual
window->glx.visual = glXGetVisualFromFBConfig(_glfw.x11.display, native);
window->glx.visual = _glfw_glXGetVisualFromFBConfig(_glfw.x11.display,
native);
if (!window->glx.visual)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
@@ -350,20 +372,17 @@ int _glfwCreateContext(_GLFWwindow* window,
if (_glfw.glx.ARB_create_context)
{
int index = 0, mask = 0, flags = 0, strategy = 0;
int index = 0, mask = 0, flags = 0;
if (ctxconfig->api == GLFW_OPENGL_API)
{
if (ctxconfig->forward)
flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
if (ctxconfig->profile)
{
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
}
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
}
else
mask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
@@ -376,9 +395,15 @@ int _glfwCreateContext(_GLFWwindow* window,
if (_glfw.glx.ARB_create_context_robustness)
{
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
strategy = GLX_NO_RESET_NOTIFICATION_ARB;
{
setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
GLX_NO_RESET_NOTIFICATION_ARB);
}
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
strategy = GLX_LOSE_CONTEXT_ON_RESET_ARB;
{
setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
GLX_LOSE_CONTEXT_ON_RESET_ARB);
}
flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
}
@@ -401,12 +426,11 @@ int _glfwCreateContext(_GLFWwindow* window,
}
}
// NOTE: Only request an explicitly versioned context when necessary, as
// explicitly requesting version 1.0 does not always return the
// highest version supported by the driver
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
// NOTE: Only request an explicitly versioned context when
// necessary, as explicitly requesting version 1.0 does not
// always return the highest available version
setGLXattrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
setGLXattrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
}
@@ -417,9 +441,6 @@ int _glfwCreateContext(_GLFWwindow* window,
if (flags)
setGLXattrib(GLX_CONTEXT_FLAGS_ARB, flags);
if (strategy)
setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, strategy);
setGLXattrib(None, None);
window->glx.context =
@@ -429,12 +450,12 @@ int _glfwCreateContext(_GLFWwindow* window,
True,
attribs);
// HACK: This is a fallback for broken versions of the Mesa
// implementation of GLX_ARB_create_context_profile that fail
// default 1.0 context creation with a GLXBadProfileARB error in
// violation of the extension spec
if (!window->glx.context)
{
// HACK: This is a fallback for the broken Mesa implementation of
// GLX_ARB_create_context_profile, which fails default 1.0
// context creation with a GLXBadProfileARB error in violation
// of the extension spec
if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&
ctxconfig->api == GLFW_OPENGL_API &&
ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&
@@ -472,7 +493,7 @@ void _glfwDestroyContext(_GLFWwindow* window)
if (window->glx.context)
{
glXDestroyContext(_glfw.x11.display, window->glx.context);
_glfw_glXDestroyContext(_glfw.x11.display, window->glx.context);
window->glx.context = NULL;
}
}
@@ -486,19 +507,19 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
{
if (window)
{
glXMakeCurrent(_glfw.x11.display,
window->x11.handle,
window->glx.context);
_glfw_glXMakeCurrent(_glfw.x11.display,
window->x11.handle,
window->glx.context);
}
else
glXMakeCurrent(_glfw.x11.display, None, NULL);
_glfw_glXMakeCurrent(_glfw.x11.display, None, NULL);
_glfwSetCurrentContext(window);
_glfwSetContextTLS(window);
}
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
{
glXSwapBuffers(_glfw.x11.display, window->x11.handle);
_glfw_glXSwapBuffers(_glfw.x11.display, window->x11.handle);
}
void _glfwPlatformSwapInterval(int interval)
@@ -522,12 +543,9 @@ void _glfwPlatformSwapInterval(int interval)
int _glfwPlatformExtensionSupported(const char* extension)
{
const GLubyte* extensions;
// Get list of GLX extensions
extensions = (const GLubyte*) glXQueryExtensionsString(_glfw.x11.display,
_glfw.x11.screen);
if (extensions != NULL)
const char* extensions =
_glfw_glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen);
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GL_TRUE;
@@ -538,7 +556,12 @@ int _glfwPlatformExtensionSupported(const char* extension)
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
{
return _glfw_glXGetProcAddress((const GLubyte*) procname);
if (_glfw.glx.GetProcAddress)
return _glfw.glx.GetProcAddress((const GLubyte*) procname);
else if (_glfw.glx.GetProcAddressARB)
return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
else
return dlsym(_glfw.glx.handle, procname);
}
+49 -34
View File
@@ -25,8 +25,8 @@
//
//========================================================================
#ifndef _glx_context_h_
#define _glx_context_h_
#ifndef _glfw3_glx_context_h_
#define _glfw3_glx_context_h_
#define GLX_GLXEXT_LEGACY
#include <GL/glx.h>
@@ -34,28 +34,29 @@
// This path may need to be changed if you build GLFW using your own setup
// We ship and use our own copy of glxext.h since GLFW uses fairly new
// extensions and not all operating systems come with an up-to-date version
#define GLX_GLXEXT_PROTOTYPES
#include "../deps/GL/glxext.h"
// Do we have support for dlopen/dlsym?
#if defined(_GLFW_HAS_DLOPEN)
#include <dlfcn.h>
#endif
// We support four different ways for getting addresses for GL/GLX
// extension functions: glXGetProcAddress, glXGetProcAddressARB,
// glXGetProcAddressEXT, and dlsym
#if defined(_GLFW_HAS_GLXGETPROCADDRESSARB)
#define _glfw_glXGetProcAddress(x) glXGetProcAddressARB(x)
#elif defined(_GLFW_HAS_GLXGETPROCADDRESS)
#define _glfw_glXGetProcAddress(x) glXGetProcAddress(x)
#elif defined(_GLFW_HAS_GLXGETPROCADDRESSEXT)
#define _glfw_glXGetProcAddress(x) glXGetProcAddressEXT(x)
#elif defined(_GLFW_HAS_DLOPEN)
#define _glfw_glXGetProcAddress(x) dlsym(_glfw.glx.libGL, x)
#define _GLFW_DLOPEN_LIBGL
#else
#error "No OpenGL entry point retrieval mechanism was enabled"
#endif
// libGL.so function pointer typedefs
typedef int (*PFNGLXGETFBCONFIGATTRIBPROC)(Display*,GLXFBConfig,int,int*);
typedef const char* (*PFNGLXGETCLIENTSTRINGPROC)(Display*,int);
typedef Bool (*PFNGLXQUERYEXTENSIONPROC)(Display*,int*,int*);
typedef Bool (*PFNGLXQUERYVERSIONPROC)(Display*,int*,int*);
typedef void (*PFNGLXDESTROYCONTEXTPROC)(Display*,GLXContext);
typedef Bool (*PFNGLXMAKECURRENTPROC)(Display*,GLXDrawable,GLXContext);
typedef void (*PFNGLXSWAPBUFFERSPROC)(Display*,GLXDrawable);
typedef const char* (*PFNGLXQUERYEXTENSIONSSTRINGPROC)(Display*,int);
#define _glfw_glXGetFBConfigs _glfw.glx.GetFBConfigs
#define _glfw_glXGetFBConfigAttrib _glfw.glx.GetFBConfigAttrib
#define _glfw_glXGetClientString _glfw.glx.GetClientString
#define _glfw_glXQueryExtension _glfw.glx.QueryExtension
#define _glfw_glXQueryVersion _glfw.glx.QueryVersion
#define _glfw_glXDestroyContext _glfw.glx.DestroyContext
#define _glfw_glXMakeCurrent _glfw.glx.MakeCurrent
#define _glfw_glXSwapBuffers _glfw.glx.SwapBuffers
#define _glfw_glXQueryExtensionsString _glfw.glx.QueryExtensionsString
#define _glfw_glXCreateNewContext _glfw.glx.CreateNewContext
#define _glfw_glXGetVisualFromFBConfig _glfw.glx.GetVisualFromFBConfig
#define _GLFW_PLATFORM_FBCONFIG GLXFBConfig glx
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX glx
@@ -82,31 +83,45 @@ typedef struct _GLFWcontextGLX
//
typedef struct _GLFWlibraryGLX
{
int versionMajor, versionMinor;
int major, minor;
int eventBase;
int errorBase;
// GLX extensions
PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI;
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
// dlopen handle for libGL.so.1
void* handle;
// GLX 1.3 functions
PFNGLXGETFBCONFIGSPROC GetFBConfigs;
PFNGLXGETFBCONFIGATTRIBPROC GetFBConfigAttrib;
PFNGLXGETCLIENTSTRINGPROC GetClientString;
PFNGLXQUERYEXTENSIONPROC QueryExtension;
PFNGLXQUERYVERSIONPROC QueryVersion;
PFNGLXDESTROYCONTEXTPROC DestroyContext;
PFNGLXMAKECURRENTPROC MakeCurrent;
PFNGLXSWAPBUFFERSPROC SwapBuffers;
PFNGLXQUERYEXTENSIONSSTRINGPROC QueryExtensionsString;
PFNGLXCREATENEWCONTEXTPROC CreateNewContext;
PFNGLXGETVISUALFROMFBCONFIGPROC GetVisualFromFBConfig;
// GLX 1.4 and extension functions
PFNGLXGETPROCADDRESSPROC GetProcAddress;
PFNGLXGETPROCADDRESSPROC GetProcAddressARB;
PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI;
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
GLboolean SGI_swap_control;
GLboolean EXT_swap_control;
GLboolean MESA_swap_control;
GLboolean ARB_multisample;
GLboolean ARB_framebuffer_sRGB;
GLboolean EXT_framebuffer_sRGB;
GLboolean ARB_create_context;
GLboolean ARB_create_context_profile;
GLboolean ARB_create_context_robustness;
GLboolean EXT_create_context_es2_profile;
GLboolean ARB_context_flush_control;
#if defined(_GLFW_DLOPEN_LIBGL)
// dlopen handle for libGL.so (for glfwGetProcAddress)
void* libGL;
#endif
} _GLFWlibraryGLX;
@@ -117,4 +132,4 @@ int _glfwCreateContext(_GLFWwindow* window,
const _GLFWfbconfig* fbconfig);
void _glfwDestroyContext(_GLFWwindow* window);
#endif // _glx_context_h_
#endif // _glfw3_glx_context_h_
+3 -10
View File
@@ -33,8 +33,8 @@
#include <stdarg.h>
// The three global variables below comprise all global data in GLFW, except for
// various static const translation tables. Any other global variable is a bug.
// The three global variables below comprise all global data in GLFW.
// Any other global variable is a bug.
// Global state shared between compilation units of GLFW
// These are documented in internal.h
@@ -86,7 +86,7 @@ void _glfwInputError(int error, const char* format, ...)
{
if (_glfwErrorCallback)
{
char buffer[16384];
char buffer[8192];
const char* description;
if (format)
@@ -129,13 +129,6 @@ GLFWAPI int glfwInit(void)
}
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
if (!_glfw.monitorCount)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "No monitors found");
_glfwPlatformTerminate();
return GL_FALSE;
}
_glfwInitialized = GL_TRUE;
// Not all window hints have zero as their default value
+2 -2
View File
@@ -55,7 +55,7 @@ static void setCursorMode(_GLFWwindow* window, int newMode)
window->cursorMode = newMode;
if (_glfw.focusedWindow == window)
if (_glfw.cursorWindow == window)
{
if (oldMode == GLFW_CURSOR_DISABLED)
{
@@ -343,7 +343,7 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
_GLFW_REQUIRE_INIT();
if (_glfw.focusedWindow != window)
if (_glfw.cursorWindow != window)
return;
if (window->cursorMode == GLFW_CURSOR_DISABLED)
+22 -41
View File
@@ -25,15 +25,15 @@
//
//========================================================================
#ifndef _internal_h_
#define _internal_h_
#ifndef _glfw3_internal_h_
#define _glfw3_internal_h_
#if defined(_GLFW_USE_CONFIG_H)
#include "glfw_config.h"
#endif
#define _GLFW_VERSION_NUMBER "3.1.1"
#define _GLFW_VERSION_NUMBER "3.1.2"
#if defined(GLFW_INCLUDE_GLCOREARB) || \
defined(GLFW_INCLUDE_ES1) || \
@@ -69,6 +69,10 @@
#include "../deps/GL/glext.h"
#endif
typedef void (APIENTRY * PFNGLCLEARPROC)(GLbitfield);
typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGPROC)(GLenum);
typedef void (APIENTRY * PFNGLGETINTEGERVPROC)(GLenum,GLint*);
typedef struct _GLFWwndconfig _GLFWwndconfig;
typedef struct _GLFWctxconfig _GLFWctxconfig;
typedef struct _GLFWfbconfig _GLFWfbconfig;
@@ -261,6 +265,9 @@ struct _GLFWwindow
#if defined(_GLFW_USE_OPENGL)
PFNGLGETSTRINGIPROC GetStringi;
#endif
PFNGLGETINTEGERVPROC GetIntegerv;
PFNGLGETSTRINGPROC GetString;
PFNGLCLEARPROC Clear;
struct {
GLFWwindowposfun pos;
@@ -323,47 +330,21 @@ struct _GLFWcursor
struct _GLFWlibrary
{
struct {
int redBits;
int greenBits;
int blueBits;
int alphaBits;
int depthBits;
int stencilBits;
int accumRedBits;
int accumGreenBits;
int accumBlueBits;
int accumAlphaBits;
int auxBuffers;
int stereo;
int resizable;
int visible;
int decorated;
int focused;
int autoIconify;
int floating;
int samples;
int sRGB;
int refreshRate;
int doublebuffer;
int api;
int major;
int minor;
int forward;
int debug;
int profile;
int robustness;
int release;
_GLFWfbconfig framebuffer;
_GLFWwndconfig window;
_GLFWctxconfig context;
int refreshRate;
} hints;
double cursorPosX, cursorPosY;
double cursorPosX, cursorPosY;
_GLFWcursor* cursorListHead;
_GLFWcursor* cursorListHead;
_GLFWwindow* windowListHead;
_GLFWwindow* focusedWindow;
_GLFWwindow* windowListHead;
_GLFWwindow* cursorWindow;
_GLFWmonitor** monitors;
int monitorCount;
_GLFWmonitor** monitors;
int monitorCount;
struct {
GLFWmonitorfun monitor;
@@ -825,7 +806,7 @@ void _glfwSplitBPP(int bpp, int* red, int* green, int* blue);
* @return `GL_TRUE` if the extension was found, or `GL_FALSE` otherwise.
* @ingroup utility
*/
int _glfwStringInExtensionString(const char* string, const GLubyte* extensions);
int _glfwStringInExtensionString(const char* string, const char* extensions);
/*! @brief Chooses the framebuffer config that best matches the desired one.
* @param[in] desired The desired framebuffer config.
@@ -894,4 +875,4 @@ void _glfwFreeMonitor(_GLFWmonitor* monitor);
*/
void _glfwFreeMonitors(_GLFWmonitor** monitors, int count);
#endif // _internal_h_
#endif // _glfw3_internal_h_
+14 -7
View File
@@ -24,8 +24,8 @@
//
//========================================================================
#ifndef _iokit_joystick_h_
#define _iokit_joystick_h_
#ifndef _glfw3_iokit_joystick_h_
#define _glfw3_iokit_joystick_h_
#include <IOKit/IOKitLib.h>
#include <IOKit/IOCFPlugIn.h>
@@ -33,17 +33,17 @@
#include <IOKit/hid/IOHIDKeys.h>
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
_GLFWjoystickIOKit iokit_js[GLFW_JOYSTICK_LAST + 1]
_GLFWjoystickIOKit iokit_js
// IOKit-specific per-joystick data
//
typedef struct _GLFWjoystickIOKit
typedef struct _GLFWjoydevice
{
int present;
char name[256];
IOHIDDeviceInterface** interface;
IOHIDDeviceRef deviceRef;
CFMutableArrayRef axisElements;
CFMutableArrayRef buttonElements;
@@ -51,11 +51,18 @@ typedef struct _GLFWjoystickIOKit
float* axes;
unsigned char* buttons;
} _GLFWjoydevice;
// IOKit-specific joystick API data
//
typedef struct _GLFWjoystickIOKit
{
_GLFWjoydevice devices[GLFW_JOYSTICK_LAST + 1];
IOHIDManagerRef managerRef;
} _GLFWjoystickIOKit;
void _glfwInitJoysticks(void);
void _glfwTerminateJoysticks(void);
#endif // _iokit_joystick_h_
#endif // _glfw3_iokit_joystick_h_
+262 -261
View File
@@ -42,7 +42,7 @@
//------------------------------------------------------------------------
typedef struct
{
IOHIDElementCookie cookie;
IOHIDElementRef elementRef;
long min;
long max;
@@ -55,89 +55,68 @@ typedef struct
static void getElementsCFArrayHandler(const void* value, void* parameter);
// Adds an element to the specified joystick
//
static void addJoystickElement(_GLFWjoystickIOKit* joystick, CFTypeRef elementRef)
static void addJoystickElement(_GLFWjoydevice* joystick,
IOHIDElementRef elementRef)
{
long elementType, usagePage, usage;
IOHIDElementType elementType;
long usagePage, usage;
CFMutableArrayRef elementsArray = NULL;
CFNumberGetValue(CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementTypeKey)),
kCFNumberLongType, &elementType);
CFNumberGetValue(CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementUsagePageKey)),
kCFNumberLongType, &usagePage);
CFNumberGetValue(CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementUsageKey)),
kCFNumberLongType, &usage);
elementType = IOHIDElementGetType(elementRef);
usagePage = IOHIDElementGetUsagePage(elementRef);
usage = IOHIDElementGetUsage(elementRef);
if ((elementType == kIOHIDElementTypeInput_Axis) ||
(elementType == kIOHIDElementTypeInput_Button) ||
(elementType == kIOHIDElementTypeInput_Misc))
if ((elementType != kIOHIDElementTypeInput_Axis) &&
(elementType != kIOHIDElementTypeInput_Button) &&
(elementType != kIOHIDElementTypeInput_Misc))
{
switch (usagePage)
{
case kHIDPage_GenericDesktop:
{
switch (usage)
{
case kHIDUsage_GD_X:
case kHIDUsage_GD_Y:
case kHIDUsage_GD_Z:
case kHIDUsage_GD_Rx:
case kHIDUsage_GD_Ry:
case kHIDUsage_GD_Rz:
case kHIDUsage_GD_Slider:
case kHIDUsage_GD_Dial:
case kHIDUsage_GD_Wheel:
elementsArray = joystick->axisElements;
break;
case kHIDUsage_GD_Hatswitch:
elementsArray = joystick->hatElements;
break;
}
break;
}
case kHIDPage_Button:
elementsArray = joystick->buttonElements;
break;
default:
break;
}
if (elementsArray)
{
long number;
CFTypeRef numberRef;
_GLFWjoyelement* element = calloc(1, sizeof(_GLFWjoyelement));
CFArrayAppendValue(elementsArray, element);
numberRef = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementCookieKey));
if (numberRef && CFNumberGetValue(numberRef, kCFNumberLongType, &number))
element->cookie = (IOHIDElementCookie) number;
numberRef = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementMinKey));
if (numberRef && CFNumberGetValue(numberRef, kCFNumberLongType, &number))
element->minReport = element->min = number;
numberRef = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementMaxKey));
if (numberRef && CFNumberGetValue(numberRef, kCFNumberLongType, &number))
element->maxReport = element->max = number;
}
return;
}
else
switch (usagePage)
{
CFTypeRef array = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementKey));
if (array)
case kHIDPage_GenericDesktop:
{
if (CFGetTypeID(array) == CFArrayGetTypeID())
switch (usage)
{
CFRange range = { 0, CFArrayGetCount(array) };
CFArrayApplyFunction(array, range, getElementsCFArrayHandler, joystick);
case kHIDUsage_GD_X:
case kHIDUsage_GD_Y:
case kHIDUsage_GD_Z:
case kHIDUsage_GD_Rx:
case kHIDUsage_GD_Ry:
case kHIDUsage_GD_Rz:
case kHIDUsage_GD_Slider:
case kHIDUsage_GD_Dial:
case kHIDUsage_GD_Wheel:
elementsArray = joystick->axisElements;
break;
case kHIDUsage_GD_Hatswitch:
elementsArray = joystick->hatElements;
break;
}
break;
}
case kHIDPage_Button:
elementsArray = joystick->buttonElements;
break;
default:
break;
}
if (elementsArray)
{
_GLFWjoyelement* element = calloc(1, sizeof(_GLFWjoyelement));
CFArrayAppendValue(elementsArray, element);
element->elementRef = elementRef;
element->minReport = IOHIDElementGetLogicalMin(elementRef);
element->maxReport = IOHIDElementGetLogicalMax(elementRef);
}
}
@@ -145,40 +124,46 @@ static void addJoystickElement(_GLFWjoystickIOKit* joystick, CFTypeRef elementRe
//
static void getElementsCFArrayHandler(const void* value, void* parameter)
{
if (CFGetTypeID(value) == CFDictionaryGetTypeID())
addJoystickElement((_GLFWjoystickIOKit*) parameter, (CFTypeRef) value);
if (CFGetTypeID(value) == IOHIDElementGetTypeID())
{
addJoystickElement((_GLFWjoydevice*) parameter,
(IOHIDElementRef) value);
}
}
// Returns the value of the specified element of the specified joystick
//
static long getElementValue(_GLFWjoystickIOKit* joystick, _GLFWjoyelement* element)
static long getElementValue(_GLFWjoydevice* joystick, _GLFWjoyelement* element)
{
IOReturn result = kIOReturnSuccess;
IOHIDEventStruct hidEvent;
hidEvent.value = 0;
IOHIDValueRef valueRef;
long value = 0;
if (joystick && element && joystick->interface)
if (joystick && element && joystick->deviceRef)
{
result = (*(joystick->interface))->getElementValue(joystick->interface,
element->cookie,
&hidEvent);
result = IOHIDDeviceGetValue(joystick->deviceRef,
element->elementRef,
&valueRef);
if (kIOReturnSuccess == result)
{
value = IOHIDValueGetIntegerValue(valueRef);
// Record min and max for auto calibration
if (hidEvent.value < element->minReport)
element->minReport = hidEvent.value;
if (hidEvent.value > element->maxReport)
element->maxReport = hidEvent.value;
if (value < element->minReport)
element->minReport = value;
if (value > element->maxReport)
element->maxReport = value;
}
}
// Auto user scale
return (long) hidEvent.value;
return value;
}
// Removes the specified joystick
//
static void removeJoystick(_GLFWjoystickIOKit* joystick)
static void removeJoystick(_GLFWjoydevice* joystick)
{
int i;
@@ -188,29 +173,22 @@ static void removeJoystick(_GLFWjoystickIOKit* joystick)
for (i = 0; i < CFArrayGetCount(joystick->axisElements); i++)
free((void*) CFArrayGetValueAtIndex(joystick->axisElements, i));
CFArrayRemoveAllValues(joystick->axisElements);
CFRelease(joystick->axisElements);
for (i = 0; i < CFArrayGetCount(joystick->buttonElements); i++)
free((void*) CFArrayGetValueAtIndex(joystick->buttonElements, i));
CFArrayRemoveAllValues(joystick->buttonElements);
CFRelease(joystick->buttonElements);
for (i = 0; i < CFArrayGetCount(joystick->hatElements); i++)
free((void*) CFArrayGetValueAtIndex(joystick->hatElements, i));
CFArrayRemoveAllValues(joystick->hatElements);
CFRelease(joystick->hatElements);
free(joystick->axes);
free(joystick->buttons);
(*(joystick->interface))->close(joystick->interface);
(*(joystick->interface))->Release(joystick->interface);
memset(joystick, 0, sizeof(_GLFWjoystickIOKit));
}
// Callback for user-initiated joystick removal
//
static void removalCallback(void* target, IOReturn result, void* refcon, void* sender)
{
removeJoystick((_GLFWjoystickIOKit*) refcon);
memset(joystick, 0, sizeof(_GLFWjoydevice));
}
// Polls for joystick events and updates GLFW state
@@ -223,15 +201,15 @@ static void pollJoystickEvents(void)
{
CFIndex i;
int buttonIndex = 0;
_GLFWjoystickIOKit* joystick = _glfw.iokit_js + joy;
_GLFWjoydevice* joystick = _glfw.iokit_js.devices + joy;
if (!joystick->present)
continue;
for (i = 0; i < CFArrayGetCount(joystick->buttonElements); i++)
{
_GLFWjoyelement* button =
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->buttonElements, i);
_GLFWjoyelement* button = (_GLFWjoyelement*)
CFArrayGetValueAtIndex(joystick->buttonElements, i);
if (getElementValue(joystick, button))
joystick->buttons[buttonIndex++] = GLFW_PRESS;
@@ -241,8 +219,8 @@ static void pollJoystickEvents(void)
for (i = 0; i < CFArrayGetCount(joystick->axisElements); i++)
{
_GLFWjoyelement* axis =
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->axisElements, i);
_GLFWjoyelement* axis = (_GLFWjoyelement*)
CFArrayGetValueAtIndex(joystick->axisElements, i);
long value = getElementValue(joystick, axis);
long readScale = axis->maxReport - axis->minReport;
@@ -255,8 +233,8 @@ static void pollJoystickEvents(void)
for (i = 0; i < CFArrayGetCount(joystick->hatElements); i++)
{
_GLFWjoyelement* hat =
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->hatElements, i);
_GLFWjoyelement* hat = (_GLFWjoyelement*)
CFArrayGetValueAtIndex(joystick->hatElements, i);
// Bit fields of button presses for each direction, including nil
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
@@ -276,6 +254,129 @@ static void pollJoystickEvents(void)
}
}
// Callback for user-initiated joystick addition
//
static void matchCallback(void* context,
IOReturn result,
void* sender,
IOHIDDeviceRef deviceRef)
{
_GLFWjoydevice* joystick;
int joy;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{
joystick = _glfw.iokit_js.devices + joy;
if (!joystick->present)
continue;
if (joystick->deviceRef == deviceRef)
return;
}
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{
joystick = _glfw.iokit_js.devices + joy;
if (!joystick->present)
break;
}
if (joy > GLFW_JOYSTICK_LAST)
return;
joystick->present = GL_TRUE;
joystick->deviceRef = deviceRef;
CFStringRef name = IOHIDDeviceGetProperty(deviceRef,
CFSTR(kIOHIDProductKey));
CFStringGetCString(name,
joystick->name,
sizeof(joystick->name),
kCFStringEncodingUTF8);
joystick->axisElements = CFArrayCreateMutable(NULL, 0, NULL);
joystick->buttonElements = CFArrayCreateMutable(NULL, 0, NULL);
joystick->hatElements = CFArrayCreateMutable(NULL, 0, NULL);
CFArrayRef arrayRef = IOHIDDeviceCopyMatchingElements(deviceRef,
NULL,
kIOHIDOptionsTypeNone);
CFRange range = { 0, CFArrayGetCount(arrayRef) };
CFArrayApplyFunction(arrayRef,
range,
getElementsCFArrayHandler,
(void*) joystick);
CFRelease(arrayRef);
joystick->axes = calloc(CFArrayGetCount(joystick->axisElements),
sizeof(float));
joystick->buttons = calloc(CFArrayGetCount(joystick->buttonElements) +
CFArrayGetCount(joystick->hatElements) * 4, 1);
}
// Callback for user-initiated joystick removal
//
static void removeCallback(void* context,
IOReturn result,
void* sender,
IOHIDDeviceRef deviceRef)
{
int joy;
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
{
_GLFWjoydevice* joystick = _glfw.iokit_js.devices + joy;
if (joystick->deviceRef == deviceRef)
{
removeJoystick(joystick);
break;
}
}
}
// Creates a dictionary to match against devices with the specified usage page
// and usage
//
static CFMutableDictionaryRef createMatchingDictionary(long usagePage,
long usage)
{
CFMutableDictionaryRef result =
CFDictionaryCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (result)
{
CFNumberRef pageRef = CFNumberCreate(kCFAllocatorDefault,
kCFNumberLongType,
&usagePage);
if (pageRef)
{
CFDictionarySetValue(result,
CFSTR(kIOHIDDeviceUsagePageKey),
pageRef);
CFRelease(pageRef);
CFNumberRef usageRef = CFNumberCreate(kCFAllocatorDefault,
kCFNumberLongType,
&usage);
if (usageRef)
{
CFDictionarySetValue(result,
CFSTR(kIOHIDDeviceUsageKey),
usageRef);
CFRelease(usageRef);
}
}
}
return result;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
@@ -285,177 +386,77 @@ static void pollJoystickEvents(void)
//
void _glfwInitJoysticks(void)
{
int joy = 0;
IOReturn result = kIOReturnSuccess;
mach_port_t masterPort = 0;
io_iterator_t objectIterator = 0;
CFMutableDictionaryRef hidMatchDictionary = NULL;
io_object_t ioHIDDeviceObject = 0;
CFMutableArrayRef matchingCFArrayRef;
result = IOMasterPort(bootstrap_port, &masterPort);
hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey);
if (kIOReturnSuccess != result || !hidMatchDictionary)
_glfw.iokit_js.managerRef = IOHIDManagerCreate(kCFAllocatorDefault,
kIOHIDOptionsTypeNone);
matchingCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks);
if (matchingCFArrayRef)
{
if (hidMatchDictionary)
CFRelease(hidMatchDictionary);
CFDictionaryRef matchingCFDictRef =
createMatchingDictionary(kHIDPage_GenericDesktop,
kHIDUsage_GD_Joystick);
if (matchingCFDictRef)
{
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
CFRelease(matchingCFDictRef);
}
return;
matchingCFDictRef = createMatchingDictionary(kHIDPage_GenericDesktop,
kHIDUsage_GD_GamePad);
if (matchingCFDictRef)
{
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
CFRelease(matchingCFDictRef);
}
matchingCFDictRef =
createMatchingDictionary(kHIDPage_GenericDesktop,
kHIDUsage_GD_MultiAxisController);
if (matchingCFDictRef)
{
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
CFRelease(matchingCFDictRef);
}
IOHIDManagerSetDeviceMatchingMultiple(_glfw.iokit_js.managerRef,
matchingCFArrayRef);
CFRelease(matchingCFArrayRef);
}
result = IOServiceGetMatchingServices(masterPort,
hidMatchDictionary,
&objectIterator);
if (result != kIOReturnSuccess)
return;
IOHIDManagerRegisterDeviceMatchingCallback(_glfw.iokit_js.managerRef,
&matchCallback, NULL);
IOHIDManagerRegisterDeviceRemovalCallback(_glfw.iokit_js.managerRef,
&removeCallback, NULL);
if (!objectIterator)
{
// There are no joysticks
return;
}
IOHIDManagerScheduleWithRunLoop(_glfw.iokit_js.managerRef,
CFRunLoopGetMain(),
kCFRunLoopDefaultMode);
while ((ioHIDDeviceObject = IOIteratorNext(objectIterator)))
{
CFMutableDictionaryRef propsRef = NULL;
CFTypeRef valueRef = NULL;
kern_return_t result;
IOHIDManagerOpen(_glfw.iokit_js.managerRef, kIOHIDOptionsTypeNone);
IOCFPlugInInterface** ppPlugInInterface = NULL;
HRESULT plugInResult = S_OK;
SInt32 score = 0;
long usagePage = 0;
long usage = 0;
valueRef = IORegistryEntryCreateCFProperty(ioHIDDeviceObject,
CFSTR(kIOHIDPrimaryUsagePageKey),
kCFAllocatorDefault, kNilOptions);
if (valueRef)
{
CFNumberGetValue(valueRef, kCFNumberLongType, &usagePage);
CFRelease(valueRef);
}
valueRef = IORegistryEntryCreateCFProperty(ioHIDDeviceObject,
CFSTR(kIOHIDPrimaryUsageKey),
kCFAllocatorDefault, kNilOptions);
if (valueRef)
{
CFNumberGetValue(valueRef, kCFNumberLongType, &usage);
CFRelease(valueRef);
}
if (usagePage != kHIDPage_GenericDesktop)
{
// This device is not relevant to GLFW
continue;
}
if ((usage != kHIDUsage_GD_Joystick &&
usage != kHIDUsage_GD_GamePad &&
usage != kHIDUsage_GD_MultiAxisController))
{
// This device is not relevant to GLFW
continue;
}
result = IORegistryEntryCreateCFProperties(ioHIDDeviceObject,
&propsRef,
kCFAllocatorDefault,
kNilOptions);
if (result != kIOReturnSuccess)
continue;
_GLFWjoystickIOKit* joystick = _glfw.iokit_js + joy;
joystick->present = GL_TRUE;
result = IOCreatePlugInInterfaceForService(ioHIDDeviceObject,
kIOHIDDeviceUserClientTypeID,
kIOCFPlugInInterfaceID,
&ppPlugInInterface,
&score);
if (kIOReturnSuccess != result)
{
CFRelease(propsRef);
return;
}
plugInResult = (*ppPlugInInterface)->QueryInterface(
ppPlugInInterface,
CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID),
(void *) &(joystick->interface));
if (plugInResult != S_OK)
{
CFRelease(propsRef);
return;
}
(*ppPlugInInterface)->Release(ppPlugInInterface);
(*(joystick->interface))->open(joystick->interface, 0);
(*(joystick->interface))->setRemovalCallback(joystick->interface,
removalCallback,
joystick,
joystick);
// Get product string
valueRef = CFDictionaryGetValue(propsRef, CFSTR(kIOHIDProductKey));
if (valueRef)
{
CFStringGetCString(valueRef,
joystick->name,
sizeof(joystick->name),
kCFStringEncodingUTF8);
}
joystick->axisElements = CFArrayCreateMutable(NULL, 0, NULL);
joystick->buttonElements = CFArrayCreateMutable(NULL, 0, NULL);
joystick->hatElements = CFArrayCreateMutable(NULL, 0, NULL);
valueRef = CFDictionaryGetValue(propsRef, CFSTR(kIOHIDElementKey));
if (CFGetTypeID(valueRef) == CFArrayGetTypeID())
{
CFRange range = { 0, CFArrayGetCount(valueRef) };
CFArrayApplyFunction(valueRef,
range,
getElementsCFArrayHandler,
(void*) joystick);
}
CFRelease(propsRef);
joystick->axes = calloc(CFArrayGetCount(joystick->axisElements),
sizeof(float));
joystick->buttons = calloc(CFArrayGetCount(joystick->buttonElements) +
CFArrayGetCount(joystick->hatElements) * 4, 1);
joy++;
if (joy > GLFW_JOYSTICK_LAST)
break;
}
// Execute the run loop once in order to register any initially-attached
// joysticks
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false);
}
// Close all opened joystick handles
//
void _glfwTerminateJoysticks(void)
{
int i;
int joy;
for (i = 0; i < GLFW_JOYSTICK_LAST + 1; i++)
for (joy = 0; joy <= GLFW_JOYSTICK_LAST; joy++)
{
_GLFWjoystickIOKit* joystick = &_glfw.iokit_js[i];
_GLFWjoydevice* joystick = _glfw.iokit_js.devices + joy;
removeJoystick(joystick);
if (joystick->axisElements)
CFRelease(joystick->axisElements);
if (joystick->buttonElements)
CFRelease(joystick->buttonElements);
if (joystick->hatElements)
CFRelease(joystick->hatElements);
}
CFRelease(_glfw.iokit_js.managerRef);
_glfw.iokit_js.managerRef = NULL;
}
@@ -467,12 +468,12 @@ int _glfwPlatformJoystickPresent(int joy)
{
pollJoystickEvents();
return _glfw.iokit_js[joy].present;
return _glfw.iokit_js.devices[joy].present;
}
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
{
_GLFWjoystickIOKit* joystick = _glfw.iokit_js + joy;
_GLFWjoydevice* joystick = _glfw.iokit_js.devices + joy;
pollJoystickEvents();
@@ -485,7 +486,7 @@ const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
{
_GLFWjoystickIOKit* joystick = _glfw.iokit_js + joy;
_GLFWjoydevice* joystick = _glfw.iokit_js.devices + joy;
pollJoystickEvents();
@@ -501,6 +502,6 @@ const char* _glfwPlatformGetJoystickName(int joy)
{
pollJoystickEvents();
return _glfw.iokit_js[joy].name;
return _glfw.iokit_js.devices[joy].name;
}
+3 -3
View File
@@ -24,8 +24,8 @@
//
//========================================================================
#ifndef _linux_joystick_h_
#define _linux_joystick_h_
#ifndef _glfw3_linux_joystick_h_
#define _glfw3_linux_joystick_h_
#include <regex.h>
@@ -60,4 +60,4 @@ typedef struct _GLFWjoystickLinux
int _glfwInitJoysticks(void);
void _glfwTerminateJoysticks(void);
#endif // _linux_joystick_h_
#endif // _glfw3_linux_joystick_h_
+10 -4
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.1 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -55,6 +55,9 @@ int _glfwPlatformInit(void)
if (!_glfwInitContextAPI())
return GL_FALSE;
// Need the default conf for when we set a NULL cursor
_glfw.mir.default_conf = mir_cursor_configuration_from_name(mir_arrow_cursor_name);
_glfwInitTimer();
_glfwInitJoysticks();
@@ -87,15 +90,18 @@ void _glfwPlatformTerminate(void)
const char* _glfwPlatformGetVersionString(void)
{
const char* version = _GLFW_VERSION_NUMBER " Mir EGL"
return _GLFW_VERSION_NUMBER " Mir EGL"
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
" clock_gettime"
#else
" gettimeofday"
#endif
#if defined(__linux__)
" /dev/js"
#endif
#if defined(_GLFW_BUILD_DLL)
" shared"
#endif
;
return version;
}
+36 -4
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.1 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -86,6 +86,39 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
*ypos = monitor->mir.y;
}
void FillInRGBBitsFromPixelFormat(GLFWvidmode* mode, const MirPixelFormat pf)
{
switch (pf)
{
case mir_pixel_format_rgb_565:
mode->redBits = 5;
mode->greenBits = 6;
mode->blueBits = 5;
break;
case mir_pixel_format_rgba_5551:
mode->redBits = 5;
mode->greenBits = 5;
mode->blueBits = 5;
break;
case mir_pixel_format_rgba_4444:
mode->redBits = 4;
mode->greenBits = 4;
mode->blueBits = 4;
break;
case mir_pixel_format_abgr_8888:
case mir_pixel_format_xbgr_8888:
case mir_pixel_format_argb_8888:
case mir_pixel_format_xrgb_8888:
case mir_pixel_format_bgr_888:
case mir_pixel_format_rgb_888:
default:
mode->redBits = 8;
mode->greenBits = 8;
mode->blueBits = 8;
break;
}
}
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
{
int i;
@@ -106,9 +139,8 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
modes[*found].width = out->modes[*found].horizontal_resolution;
modes[*found].height = out->modes[*found].vertical_resolution;
modes[*found].refreshRate = out->modes[*found].refresh_rate;
modes[*found].redBits = 8;
modes[*found].greenBits = 8;
modes[*found].blueBits = 8;
FillInRGBBitsFromPixelFormat(&modes[*found], out->output_formats[*found]);
}
break;
+12 -8
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.1 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -24,18 +24,18 @@
//
//========================================================================
#ifndef _mir_platform_h_
#define _mir_platform_h_
#ifndef _glfw3_mir_platform_h_
#define _glfw3_mir_platform_h_
#include <sys/queue.h>
#include <pthread.h>
#include <mir_toolkit/mir_client_library.h>
#include "posix_tls.h"
#include "posix_time.h"
#include "linux_joystick.h"
#include <sys/queue.h>
#include <pthread.h>
#include "xkb_unicode.h"
#if defined(_GLFW_EGL)
#include "egl_context.h"
@@ -51,6 +51,7 @@
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir
// Mir-specific Event Queue
//
typedef struct EventQueue
@@ -88,6 +89,7 @@ typedef struct _GLFWlibraryMir
{
MirConnection* connection;
MirEGLNativeDisplayType display;
MirCursorConfiguration* default_conf;
EventQueue* event_queue;
pthread_mutex_t event_mutex;
@@ -101,10 +103,12 @@ typedef struct _GLFWlibraryMir
//
typedef struct _GLFWcursorMir
{
MirCursorConfiguration* conf;
MirBufferStream* custom_cursor;
} _GLFWcursorMir;
extern void _glfwInitEventQueue(EventQueue* queue);
extern void _glfwDeleteEventQueue(EventQueue* queue);
#endif // _mir_platform_h_
#endif // _glfw3_mir_platform_h_
+237 -123
View File
@@ -1,7 +1,7 @@
//========================================================================
// GLFW 3.1 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
@@ -25,7 +25,6 @@
//========================================================================
#include "internal.h"
#include "xkb_unicode.h"
#include <linux/input.h>
#include <stdlib.h>
@@ -35,13 +34,13 @@
typedef struct EventNode
{
TAILQ_ENTRY(EventNode) entries;
MirEvent* event;
const MirEvent* event;
_GLFWwindow* window;
} EventNode;
static void deleteNode(EventQueue* queue, EventNode* node)
{
free(node->event);
mir_event_unref(node->event);
free(node);
}
@@ -50,17 +49,19 @@ static int emptyEventQueue(EventQueue* queue)
return queue->head.tqh_first == NULL ? GL_TRUE : GL_FALSE;
}
static EventNode* newEventNode(MirEvent const* event, _GLFWwindow* context)
// TODO The mir_event_ref is not supposed to be used but ... its needed
// in this case. Need to wait until we can read from an FD set up by mir
// for single threaded event handling.
static EventNode* newEventNode(const MirEvent* event, _GLFWwindow* context)
{
EventNode* new_node = calloc(1, sizeof(EventNode));
new_node->event = calloc(1, sizeof(MirEvent));
new_node->event = mir_event_ref(event);
new_node->window = context;
memcpy(new_node->event, event, sizeof(MirEvent));
return new_node;
}
static void enqueueEvent(MirEvent const* event, _GLFWwindow* context)
static void enqueueEvent(const MirEvent* event, _GLFWwindow* context)
{
pthread_mutex_lock(&_glfw.mir.event_mutex);
@@ -88,6 +89,9 @@ static EventNode* dequeueEvent(EventQueue* queue)
return node;
}
/* FIXME Soon to be changed upstream mir! So we can use an egl config to figure out
the best pixel format!
*/
static MirPixelFormat findValidPixelFormat(void)
{
unsigned int i, validFormats, mirPixelFormats = 32;
@@ -114,13 +118,13 @@ static int mirModToGLFWMod(uint32_t mods)
{
int publicMods = 0x0;
if (mods & mir_key_modifier_alt)
if (mods & mir_input_event_modifier_alt)
publicMods |= GLFW_MOD_ALT;
else if (mods & mir_key_modifier_shift)
else if (mods & mir_input_event_modifier_shift)
publicMods |= GLFW_MOD_SHIFT;
else if (mods & mir_key_modifier_ctrl)
else if (mods & mir_input_event_modifier_ctrl)
publicMods |= GLFW_MOD_CONTROL;
else if (mods & mir_key_modifier_meta)
else if (mods & mir_input_event_modifier_meta)
publicMods |= GLFW_MOD_SUPER;
return publicMods;
@@ -251,97 +255,93 @@ static int toGLFWKeyCode(uint32_t key)
}
}
static void handleKeyEvent(const MirKeyEvent key, _GLFWwindow* window)
static void handleKeyEvent(const MirKeyboardEvent* key_event, _GLFWwindow* window)
{
const int pressed = key.action == mir_key_action_up ? GLFW_RELEASE : GLFW_PRESS;
const int mods = mirModToGLFWMod(key.modifiers);
const long text = _glfwKeySym2Unicode(key.key_code);
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
const int action = mir_keyboard_event_action (key_event);
const int scan_code = mir_keyboard_event_scan_code(key_event);
const int key_code = mir_keyboard_event_key_code (key_event);
const int modifiers = mir_keyboard_event_modifiers(key_event);
_glfwInputKey(window, toGLFWKeyCode(key.scan_code), key.scan_code, pressed, mods);
const int pressed = action == mir_keyboard_action_up ? GLFW_RELEASE : GLFW_PRESS;
const int mods = mirModToGLFWMod(modifiers);
const long text = _glfwKeySym2Unicode(key_code);
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
_glfwInputKey(window, toGLFWKeyCode(scan_code), scan_code, pressed, mods);
if (text != -1)
_glfwInputChar(window, text, mods, plain);
}
static void handleMouseButton(_GLFWwindow* window,
int pressed, int mods, MirMotionButton button)
static void handlePointerButton(_GLFWwindow* window,
int pressed,
const MirPointerEvent* pointer_event)
{
static int lastButton;
MirPointerButton button = mir_pointer_event_buttons (pointer_event);
int mods = mir_pointer_event_modifiers(pointer_event);
const int publicMods = mirModToGLFWMod(mods);
int publicButton;
const int publicMods = mirModToGLFWMod(mods);
switch (button)
{
case mir_motion_button_primary:
case mir_pointer_button_primary:
publicButton = GLFW_MOUSE_BUTTON_LEFT;
break;
case mir_motion_button_secondary:
case mir_pointer_button_secondary:
publicButton = GLFW_MOUSE_BUTTON_RIGHT;
break;
case mir_motion_button_tertiary:
case mir_pointer_button_tertiary:
publicButton = GLFW_MOUSE_BUTTON_MIDDLE;
break;
case mir_motion_button_forward:
case mir_pointer_button_forward:
// FIXME What is the forward button?
publicButton = GLFW_MOUSE_BUTTON_4;
break;
case mir_motion_button_back:
case mir_pointer_button_back:
// FIXME What is the back button?
publicButton = GLFW_MOUSE_BUTTON_5;
break;
default:
publicButton = lastButton;
break;
}
lastButton = publicButton;
_glfwInputMouseClick(window, publicButton, pressed, publicMods);
}
static void handleMouseMotion(_GLFWwindow* window, int x, int y)
static void handlePointerMotion(_GLFWwindow* window,
const MirPointerEvent* pointer_event)
{
_glfwInputCursorMotion(window, x, y);
int current_x = window->cursorPosX;
int current_y = window->cursorPosY;
int x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x);
int y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y);
int dx = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll);
int dy = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll);
if (current_x != x || current_y != y)
_glfwInputCursorMotion(window, x, y);
if (dx != 0 || dy != 0)
_glfwInputScroll(window, dx, dy);
}
static void handleMouseScroll(_GLFWwindow* window, int dx, int dy)
{
_glfwInputScroll(window, dx, dy);
}
static void handleMouseEvent(const MirMotionEvent motion,
int cord_index,
static void handlePointerEvent(const MirPointerEvent* pointer_event,
_GLFWwindow* window)
{
switch (motion.action)
int action = mir_pointer_event_action(pointer_event);
switch (action)
{
case mir_motion_action_down:
case mir_motion_action_pointer_down:
handleMouseButton(window, GLFW_PRESS,
motion.modifiers, motion.button_state);
case mir_pointer_action_button_down:
handlePointerButton(window, GLFW_PRESS, pointer_event);
break;
case mir_motion_action_up:
case mir_motion_action_pointer_up:
handleMouseButton(window, GLFW_RELEASE,
motion.modifiers, motion.button_state);
case mir_pointer_action_button_up:
handlePointerButton(window, GLFW_RELEASE, pointer_event);
break;
case mir_motion_action_hover_move:
case mir_motion_action_move:
handleMouseMotion(window,
motion.pointer_coordinates[cord_index].x,
motion.pointer_coordinates[cord_index].y);
case mir_pointer_action_motion:
handlePointerMotion(window, pointer_event);
break;
case mir_motion_action_outside:
break;
case mir_motion_action_scroll:
handleMouseScroll(window,
motion.pointer_coordinates[cord_index].hscroll,
motion.pointer_coordinates[cord_index].vscroll);
break;
case mir_motion_action_cancel:
case mir_motion_action_hover_enter:
case mir_motion_action_hover_exit:
case mir_pointer_action_enter:
case mir_pointer_action_leave:
break;
default:
break;
@@ -349,61 +349,66 @@ static void handleMouseEvent(const MirMotionEvent motion,
}
}
static void handleMotionEvent(const MirMotionEvent motion, _GLFWwindow* window)
static void handleInput(const MirInputEvent* input_event, _GLFWwindow* window)
{
int i;
for (i = 0; i < motion.pointer_count; i++)
handleMouseEvent(motion, i, window);
}
int type = mir_input_event_get_type(input_event);
static void handleInput(MirEvent const* event, _GLFWwindow* window)
{
switch (event->type)
switch (type)
{
case mir_event_type_key:
handleKeyEvent(event->key, window);
case mir_input_event_type_key:
handleKeyEvent(mir_input_event_get_keyboard_event(input_event), window);
break;
case mir_event_type_motion:
handleMotionEvent(event->motion, window);
case mir_input_event_type_pointer:
handlePointerEvent(mir_input_event_get_pointer_event(input_event), window);
break;
default:
break;
}
}
static void addNewEvent(MirSurface* surface, MirEvent const* event, void* context)
static void handleEvent(const MirEvent* event, _GLFWwindow* window)
{
int type = mir_event_get_type(event);
switch (type)
{
case mir_event_type_input:
handleInput(mir_event_get_input_event(event), window);
break;
default:
break;
}
}
static void addNewEvent(MirSurface* surface, const MirEvent* event, void* context)
{
enqueueEvent(event, context);
}
static int createSurface(_GLFWwindow* window)
{
MirSurfaceParameters params =
{
.name = "MirSurface",
.width = window->mir.width,
.height = window->mir.height,
.pixel_format = mir_pixel_format_invalid,
.buffer_usage = mir_buffer_usage_hardware,
.output_id = mir_display_output_id_invalid
};
MirSurfaceSpec* spec;
MirBufferUsage buffer_usage = mir_buffer_usage_hardware;
MirPixelFormat pixel_format = findValidPixelFormat();
MirEventDelegate delegate =
{
addNewEvent,
window
};
params.pixel_format = findValidPixelFormat();
if (params.pixel_format == mir_pixel_format_invalid)
if (pixel_format == mir_pixel_format_invalid)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unable to find a correct pixel format");
return GL_FALSE;
}
spec = mir_connection_create_spec_for_normal_surface(_glfw.mir.connection,
window->mir.width,
window->mir.height,
pixel_format);
mir_surface_spec_set_buffer_usage(spec, buffer_usage);
mir_surface_spec_set_name(spec, "MirSurface");
window->mir.surface = mir_surface_create_sync(spec);
mir_surface_spec_release(spec);
window->mir.surface =
mir_connection_create_surface_sync(_glfw.mir.connection, &params);
if (!mir_surface_is_valid(window->mir.surface))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
@@ -413,7 +418,7 @@ static int createSurface(_GLFWwindow* window)
return GL_FALSE;
}
mir_surface_set_event_handler(window->mir.surface, &delegate);
mir_surface_set_event_handler(window->mir.surface, addNewEvent, window);
return GL_TRUE;
}
@@ -471,7 +476,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Requested surface size too large: %ix%i",
wndconfig->width, wndconfig->height);
wndconfig->width, wndconfig->height);
return GL_FALSE;
}
@@ -483,7 +488,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (!createSurface(window))
return GL_FALSE;
window->mir.window = mir_surface_get_egl_native_window(window->mir.surface);
window->mir.window = mir_buffer_stream_get_egl_native_window(
mir_surface_get_buffer_stream(window->mir.surface));
return GL_TRUE;
}
@@ -501,8 +507,26 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
MirSurfaceSpec* spec;
const char* e_title = title ? title : "";
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
mir_surface_spec_set_name(spec, e_title);
mir_surface_apply_spec(window->mir.surface, spec);
mir_surface_spec_release(spec);
}
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{
MirSurfaceSpec* spec;
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
mir_surface_spec_set_width (spec, width);
mir_surface_spec_set_height(spec, height);
mir_surface_apply_spec(window->mir.surface, spec);
mir_surface_spec_release(spec);
}
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
@@ -525,12 +549,6 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
{
if (width)
@@ -551,14 +569,24 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
void _glfwPlatformHideWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
MirSurfaceSpec* spec;
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
mir_surface_spec_set_state(spec, mir_surface_state_hidden);
mir_surface_apply_spec(window->mir.surface, spec);
mir_surface_spec_release(spec);
}
void _glfwPlatformShowWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
MirSurfaceSpec* spec;
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
mir_surface_spec_set_state(spec, mir_surface_state_restored);
mir_surface_apply_spec(window->mir.surface, spec);
mir_surface_spec_release(spec);
}
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
@@ -583,9 +611,7 @@ int _glfwPlatformWindowIconified(_GLFWwindow* window)
int _glfwPlatformWindowVisible(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return GL_FALSE;
return mir_surface_get_visibility(window->mir.surface) == mir_surface_visibility_exposed;
}
void _glfwPlatformPollEvents(void)
@@ -594,7 +620,7 @@ void _glfwPlatformPollEvents(void)
while ((node = dequeueEvent(_glfw.mir.event_queue)))
{
handleInput(node->event, node->window);
handleEvent(node->event, node->window);
deleteNode(_glfw.mir.event_queue, node);
}
}
@@ -623,34 +649,122 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* heigh
*height = window->mir.height;
}
// FIXME implement
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image,
int xhot, int yhot)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
MirBufferStream* stream;
MirPixelFormat pixel_format = findValidPixelFormat();
return GL_FALSE;
int i_w = image->width;
int i_h = image->height;
if (pixel_format == mir_pixel_format_invalid)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unable to find a correct pixel format");
return GL_FALSE;
}
stream = mir_connection_create_buffer_stream_sync(_glfw.mir.connection,
i_w, i_h,
pixel_format,
mir_buffer_usage_software);
cursor->mir.conf = mir_cursor_configuration_from_buffer_stream(stream, xhot, yhot);
char* dest;
unsigned char *pixels;
int i, r_stride, bytes_per_pixel, bytes_per_row;
MirGraphicsRegion region;
mir_buffer_stream_get_graphics_region(stream, &region);
// FIXME Figure this out based on the current_pf
bytes_per_pixel = 4;
bytes_per_row = bytes_per_pixel * i_w;
dest = region.vaddr;
pixels = image->pixels;
r_stride = region.stride;
for (i = 0; i < i_h; i++)
{
memcpy(dest, pixels, bytes_per_row);
dest += r_stride;
pixels += r_stride;
}
cursor->mir.custom_cursor = stream;
return GL_TRUE;
}
const char* getSystemCursorName(int shape)
{
switch (shape)
{
case GLFW_ARROW_CURSOR:
return mir_arrow_cursor_name;
case GLFW_IBEAM_CURSOR:
return mir_caret_cursor_name;
case GLFW_CROSSHAIR_CURSOR:
return mir_crosshair_cursor_name;
case GLFW_HAND_CURSOR:
return mir_open_hand_cursor_name;
case GLFW_HRESIZE_CURSOR:
return mir_horizontal_resize_cursor_name;
case GLFW_VRESIZE_CURSOR:
return mir_vertical_resize_cursor_name;
}
return NULL;
}
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
const char* cursor_name = getSystemCursorName(shape);
if (cursor_name)
{
cursor->mir.conf = mir_cursor_configuration_from_name(cursor_name);
cursor->mir.custom_cursor = NULL;
return GL_TRUE;
}
return GL_FALSE;
}
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
if (cursor->mir.conf)
mir_cursor_configuration_destroy(cursor->mir.conf);
if (cursor->mir.custom_cursor)
mir_buffer_stream_release_sync(cursor->mir.custom_cursor);
}
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
if (cursor && cursor->mir.conf)
{
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, cursor->mir.conf));
if (cursor->mir.custom_cursor)
{
/* FIXME Bug https://bugs.launchpad.net/mir/+bug/1477285
Requires a triple buffer swap to get the cursor buffer on top! (since mir is tripled buffered)
*/
mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor);
mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor);
mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor);
}
}
else
{
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, _glfw.mir.default_conf));
}
}
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
+4
View File
@@ -305,6 +305,10 @@ GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (!_glfw.monitorCount)
return NULL;
return (GLFWmonitor*) _glfw.monitors[0];
}
+3 -3
View File
@@ -24,8 +24,8 @@
//
//========================================================================
#ifndef _nsgl_context_h_
#define _nsgl_context_h_
#ifndef _glfw3_nsgl_context_h_
#define _glfw3_nsgl_context_h_
#define _GLFW_PLATFORM_FBCONFIG
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl
@@ -59,4 +59,4 @@ int _glfwCreateContext(_GLFWwindow* window,
const _GLFWfbconfig* fbconfig);
void _glfwDestroyContext(_GLFWwindow* window);
#endif // _nsgl_context_h_
#endif // _glfw3_nsgl_context_h_
+7 -7
View File
@@ -35,7 +35,7 @@
//
int _glfwInitContextAPI(void)
{
if (!_glfwInitTLS())
if (!_glfwCreateContextTLS())
return GL_FALSE;
_glfw.nsgl.framework =
@@ -54,7 +54,7 @@ int _glfwInitContextAPI(void)
//
void _glfwTerminateContextAPI(void)
{
_glfwTerminateTLS();
_glfwDestroyContextTLS();
}
// Create the OpenGL context
@@ -67,8 +67,8 @@ int _glfwCreateContext(_GLFWwindow* window,
if (ctxconfig->api == GLFW_OPENGL_ES_API)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"NSGL: This API does not support OpenGL ES");
_glfwInputError(GLFW_API_UNAVAILABLE,
"NSGL: OpenGL ES is not available on OS X");
return GL_FALSE;
}
@@ -211,8 +211,8 @@ int _glfwCreateContext(_GLFWwindow* window,
[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
if (window->nsgl.pixelFormat == nil)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"NSGL: Failed to create OpenGL pixel format");
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"NSGL: Failed to find a suitable pixel format");
return GL_FALSE;
}
@@ -257,7 +257,7 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
else
[NSOpenGLContext clearCurrentContext];
_glfwSetCurrentContext(window);
_glfwSetContextTLS(window);
}
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
+3 -3
View File
@@ -25,8 +25,8 @@
//
//========================================================================
#ifndef _posix_time_h_
#define _posix_time_h_
#ifndef _glfw3_posix_time_h_
#define _glfw3_posix_time_h_
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimePOSIX posix_time
@@ -46,4 +46,4 @@ typedef struct _GLFWtimePOSIX
void _glfwInitTimer(void);
#endif // _posix_time_h_
#endif // _glfw3_posix_time_h_
+3 -3
View File
@@ -32,7 +32,7 @@
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
int _glfwInitTLS(void)
int _glfwCreateContextTLS(void)
{
if (pthread_key_create(&_glfw.posix_tls.context, NULL) != 0)
{
@@ -44,12 +44,12 @@ int _glfwInitTLS(void)
return GL_TRUE;
}
void _glfwTerminateTLS(void)
void _glfwDestroyContextTLS(void)
{
pthread_key_delete(_glfw.posix_tls.context);
}
void _glfwSetCurrentContext(_GLFWwindow* context)
void _glfwSetContextTLS(_GLFWwindow* context)
{
pthread_setspecific(_glfw.posix_tls.context, context);
}
+6 -6
View File
@@ -25,8 +25,8 @@
//
//========================================================================
#ifndef _posix_tls_h_
#define _posix_tls_h_
#ifndef _glfw3_posix_tls_h_
#define _glfw3_posix_tls_h_
#include <pthread.h>
@@ -42,8 +42,8 @@ typedef struct _GLFWtlsPOSIX
} _GLFWtlsPOSIX;
int _glfwInitTLS(void);
void _glfwTerminateTLS(void);
void _glfwSetCurrentContext(_GLFWwindow* context);
int _glfwCreateContextTLS(void);
void _glfwDestroyContextTLS(void);
void _glfwSetContextTLS(_GLFWwindow* context);
#endif // _posix_tls_h_
#endif // _glfw3_posix_tls_h_
+120 -140
View File
@@ -33,110 +33,67 @@
// Initialize WGL-specific extensions
// This function is called once before initial context creation, i.e. before
// any WGL extensions could be present. This is done in order to have both
// extension variable clearing and loading in the same place, hopefully
// decreasing the possibility of forgetting to add one without the other.
//
static void initWGLExtensions(_GLFWwindow* window)
{
// This needs to include every function pointer loaded below
window->wgl.SwapIntervalEXT = NULL;
window->wgl.GetPixelFormatAttribivARB = NULL;
window->wgl.GetExtensionsStringARB = NULL;
window->wgl.GetExtensionsStringEXT = NULL;
window->wgl.CreateContextAttribsARB = NULL;
// Functions for WGL_EXT_extension_string
// NOTE: These are needed by _glfwPlatformExtensionSupported
window->wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
_glfw_wglGetProcAddress("wglGetExtensionsStringEXT");
window->wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
_glfw_wglGetProcAddress("wglGetExtensionsStringARB");
// Functions for WGL_ARB_create_context
window->wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
_glfw_wglGetProcAddress("wglCreateContextAttribsARB");
// Functions for WGL_EXT_swap_control
window->wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
_glfw_wglGetProcAddress("wglSwapIntervalEXT");
// Functions for WGL_ARB_pixel_format
window->wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
_glfw_wglGetProcAddress("wglGetPixelFormatAttribivARB");
// This needs to include every extension used below except for
// WGL_ARB_extensions_string and WGL_EXT_extensions_string
window->wgl.ARB_multisample = GL_FALSE;
window->wgl.ARB_framebuffer_sRGB = GL_FALSE;
window->wgl.ARB_create_context = GL_FALSE;
window->wgl.ARB_create_context_profile = GL_FALSE;
window->wgl.EXT_create_context_es2_profile = GL_FALSE;
window->wgl.ARB_create_context_robustness = GL_FALSE;
window->wgl.EXT_swap_control = GL_FALSE;
window->wgl.ARB_pixel_format = GL_FALSE;
window->wgl.ARB_context_flush_control = GL_FALSE;
window->wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
wglGetProcAddress("wglGetExtensionsStringEXT");
if (!window->wgl.GetExtensionsStringEXT)
{
window->wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
wglGetProcAddress("wglGetExtensionsStringARB");
if (!window->wgl.GetExtensionsStringARB)
return;
}
if (_glfwPlatformExtensionSupported("WGL_ARB_multisample"))
window->wgl.ARB_multisample = GL_TRUE;
if (_glfwPlatformExtensionSupported("WGL_ARB_framebuffer_sRGB"))
window->wgl.ARB_framebuffer_sRGB = GL_TRUE;
if (_glfwPlatformExtensionSupported("WGL_ARB_create_context"))
{
window->wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
wglGetProcAddress("wglCreateContextAttribsARB");
if (window->wgl.CreateContextAttribsARB)
window->wgl.ARB_create_context = GL_TRUE;
}
if (window->wgl.ARB_create_context)
{
if (_glfwPlatformExtensionSupported("WGL_ARB_create_context_profile"))
window->wgl.ARB_create_context_profile = GL_TRUE;
}
if (window->wgl.ARB_create_context &&
window->wgl.ARB_create_context_profile)
{
if (_glfwPlatformExtensionSupported("WGL_EXT_create_context_es2_profile"))
window->wgl.EXT_create_context_es2_profile = GL_TRUE;
}
if (window->wgl.ARB_create_context)
{
if (_glfwPlatformExtensionSupported("WGL_ARB_create_context_robustness"))
window->wgl.ARB_create_context_robustness = GL_TRUE;
}
if (_glfwPlatformExtensionSupported("WGL_EXT_swap_control"))
{
window->wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
wglGetProcAddress("wglSwapIntervalEXT");
if (window->wgl.SwapIntervalEXT)
window->wgl.EXT_swap_control = GL_TRUE;
}
if (_glfwPlatformExtensionSupported("WGL_ARB_pixel_format"))
{
window->wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
wglGetProcAddress("wglGetPixelFormatAttribivARB");
if (window->wgl.GetPixelFormatAttribivARB)
window->wgl.ARB_pixel_format = GL_TRUE;
}
if (_glfwPlatformExtensionSupported("WGL_ARB_context_flush_control"))
window->wgl.ARB_context_flush_control = GL_TRUE;
window->wgl.ARB_multisample =
_glfwPlatformExtensionSupported("WGL_ARB_multisample");
window->wgl.ARB_framebuffer_sRGB =
_glfwPlatformExtensionSupported("WGL_ARB_framebuffer_sRGB");
window->wgl.EXT_framebuffer_sRGB =
_glfwPlatformExtensionSupported("WGL_EXT_framebuffer_sRGB");
window->wgl.ARB_create_context =
_glfwPlatformExtensionSupported("WGL_ARB_create_context");
window->wgl.ARB_create_context_profile =
_glfwPlatformExtensionSupported("WGL_ARB_create_context_profile");
window->wgl.EXT_create_context_es2_profile =
_glfwPlatformExtensionSupported("WGL_EXT_create_context_es2_profile");
window->wgl.ARB_create_context_robustness =
_glfwPlatformExtensionSupported("WGL_ARB_create_context_robustness");
window->wgl.EXT_swap_control =
_glfwPlatformExtensionSupported("WGL_EXT_swap_control");
window->wgl.ARB_pixel_format =
_glfwPlatformExtensionSupported("WGL_ARB_pixel_format");
window->wgl.ARB_context_flush_control =
_glfwPlatformExtensionSupported("WGL_ARB_context_flush_control");
}
// Returns the specified attribute of the specified pixel format
// NOTE: Do not call this unless we have found WGL_ARB_pixel_format
//
static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib)
{
int value = 0;
assert(window->wgl.ARB_pixel_format);
if (!window->wgl.GetPixelFormatAttribivARB(window->wgl.dc,
pixelFormat,
0, 1, &attrib, &value))
{
// NOTE: We should probably handle this error somehow
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve pixel format attribute %i",
attrib);
return 0;
}
@@ -177,7 +134,8 @@ static GLboolean choosePixelFormat(_GLFWwindow* window,
if (window->wgl.ARB_pixel_format)
{
// Get pixel format attributes through WGL_ARB_pixel_format
// Get pixel format attributes through "modern" extension
if (!getPixelFormatAttrib(window, n, WGL_SUPPORT_OPENGL_ARB) ||
!getPixelFormatAttrib(window, n, WGL_DRAW_TO_WINDOW_ARB))
{
@@ -219,7 +177,8 @@ static GLboolean choosePixelFormat(_GLFWwindow* window,
if (window->wgl.ARB_multisample)
u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
if (window->wgl.ARB_framebuffer_sRGB)
if (window->wgl.ARB_framebuffer_sRGB ||
window->wgl.EXT_framebuffer_sRGB)
{
if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
u->sRGB = GL_TRUE;
@@ -229,7 +188,7 @@ static GLboolean choosePixelFormat(_GLFWwindow* window,
{
PIXELFORMATDESCRIPTOR pfd;
// Get pixel format attributes through old-fashioned PFDs
// Get pixel format attributes through legacy PFDs
if (!DescribePixelFormat(window->wgl.dc,
n,
@@ -291,7 +250,7 @@ static GLboolean choosePixelFormat(_GLFWwindow* window,
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
if (!closest)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"WGL: Failed to find a suitable pixel format");
free(usableConfigs);
@@ -313,7 +272,7 @@ static GLboolean choosePixelFormat(_GLFWwindow* window,
//
int _glfwInitContextAPI(void)
{
if (!_glfwInitTLS())
if (!_glfwCreateContextTLS())
return GL_FALSE;
_glfw.wgl.opengl32.instance = LoadLibraryW(L"opengl32.dll");
@@ -323,6 +282,28 @@ int _glfwInitContextAPI(void)
return GL_FALSE;
}
_glfw.wgl.opengl32.CreateContext = (WGLCREATECONTEXT_T)
GetProcAddress(_glfw.wgl.opengl32.instance, "wglCreateContext");
_glfw.wgl.opengl32.DeleteContext = (WGLDELETECONTEXT_T)
GetProcAddress(_glfw.wgl.opengl32.instance, "wglDeleteContext");
_glfw.wgl.opengl32.GetProcAddress = (WGLGETPROCADDRESS_T)
GetProcAddress(_glfw.wgl.opengl32.instance, "wglGetProcAddress");
_glfw.wgl.opengl32.MakeCurrent = (WGLMAKECURRENT_T)
GetProcAddress(_glfw.wgl.opengl32.instance, "wglMakeCurrent");
_glfw.wgl.opengl32.ShareLists = (WGLSHARELISTS_T)
GetProcAddress(_glfw.wgl.opengl32.instance, "wglShareLists");
if (!_glfw.wgl.opengl32.CreateContext ||
!_glfw.wgl.opengl32.DeleteContext ||
!_glfw.wgl.opengl32.GetProcAddress ||
!_glfw.wgl.opengl32.MakeCurrent ||
!_glfw.wgl.opengl32.ShareLists)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to load opengl32 functions");
return GL_FALSE;
}
return GL_TRUE;
}
@@ -333,7 +314,7 @@ void _glfwTerminateContextAPI(void)
if (_glfw.wgl.opengl32.instance)
FreeLibrary(_glfw.wgl.opengl32.instance);
_glfwTerminateTLS();
_glfwDestroyContextTLS();
}
#define setWGLattrib(attribName, attribValue) \
@@ -384,20 +365,17 @@ int _glfwCreateContext(_GLFWwindow* window,
if (window->wgl.ARB_create_context)
{
int index = 0, mask = 0, flags = 0, strategy = 0;
int index = 0, mask = 0, flags = 0;
if (ctxconfig->api == GLFW_OPENGL_API)
{
if (ctxconfig->forward)
flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
if (ctxconfig->profile)
{
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
}
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
}
else
mask |= WGL_CONTEXT_ES2_PROFILE_BIT_EXT;
@@ -410,9 +388,15 @@ int _glfwCreateContext(_GLFWwindow* window,
if (window->wgl.ARB_create_context_robustness)
{
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
strategy = WGL_NO_RESET_NOTIFICATION_ARB;
{
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
WGL_NO_RESET_NOTIFICATION_ARB);
}
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
strategy = WGL_LOSE_CONTEXT_ON_RESET_ARB;
{
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
WGL_LOSE_CONTEXT_ON_RESET_ARB);
}
flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
}
@@ -435,12 +419,11 @@ int _glfwCreateContext(_GLFWwindow* window,
}
}
// NOTE: Only request an explicitly versioned context when necessary, as
// explicitly requesting version 1.0 does not always return the
// highest version supported by the driver
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
// NOTE: Only request an explicitly versioned context when
// necessary, as explicitly requesting version 1.0 does not
// always return the highest available version
setWGLattrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
setWGLattrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
}
@@ -451,9 +434,6 @@ int _glfwCreateContext(_GLFWwindow* window,
if (mask)
setWGLattrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
if (strategy)
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, strategy);
setWGLattrib(0, 0);
window->wgl.context = window->wgl.CreateContextAttribsARB(window->wgl.dc,
@@ -468,7 +448,7 @@ int _glfwCreateContext(_GLFWwindow* window,
}
else
{
window->wgl.context = wglCreateContext(window->wgl.dc);
window->wgl.context = _glfw_wglCreateContext(window->wgl.dc);
if (!window->wgl.context)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
@@ -478,7 +458,7 @@ int _glfwCreateContext(_GLFWwindow* window,
if (share)
{
if (!wglShareLists(share, window->wgl.context))
if (!_glfw_wglShareLists(share, window->wgl.context))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to enable sharing with specified OpenGL context");
@@ -501,7 +481,7 @@ void _glfwDestroyContext(_GLFWwindow* window)
{
if (window->wgl.context)
{
wglDeleteContext(window->wgl.context);
_glfw_wglDeleteContext(window->wgl.context);
window->wgl.context = NULL;
}
@@ -580,24 +560,18 @@ int _glfwAnalyzeContext(const _GLFWwindow* window,
if (fbconfig->samples > 0)
{
// We want FSAA, but can we get it?
// FSAA is not a hard constraint, so otherwise we just don't care
// MSAA is not a hard constraint, so do nothing if it's not supported
if (window->wgl.ARB_multisample && window->wgl.ARB_pixel_format)
{
// We appear to have both the extension and the means to ask for it
required = GL_TRUE;
}
}
if (fbconfig->sRGB)
{
// We want sRGB, but can we get it?
// sRGB is not a hard constraint, so otherwise we just don't care
if (window->wgl.ARB_framebuffer_sRGB && window->wgl.ARB_pixel_format)
// sRGB is not a hard constraint, so do nothing if it's not supported
if ((window->wgl.ARB_framebuffer_sRGB ||
window->wgl.EXT_framebuffer_sRGB) &&
window->wgl.ARB_pixel_format)
{
// We appear to have both the extension and the means to ask for it
required = GL_TRUE;
}
}
@@ -616,15 +590,23 @@ int _glfwAnalyzeContext(const _GLFWwindow* window,
void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
{
if (window)
wglMakeCurrent(window->wgl.dc, window->wgl.context);
_glfw_wglMakeCurrent(window->wgl.dc, window->wgl.context);
else
wglMakeCurrent(NULL, NULL);
_glfw_wglMakeCurrent(NULL, NULL);
_glfwSetCurrentContext(window);
_glfwSetContextTLS(window);
}
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
{
// HACK: Use DwmFlush when desktop composition is enabled
if (_glfwIsCompositionEnabled() && !window->monitor)
{
int count = abs(window->wgl.interval);
while (count--)
_glfw_DwmFlush();
}
SwapBuffers(window->wgl.dc);
}
@@ -632,14 +614,12 @@ void _glfwPlatformSwapInterval(int interval)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
#if !defined(_GLFW_USE_DWM_SWAP_INTERVAL)
if (_glfwIsCompositionEnabled() && interval)
{
// Don't enabled vsync when desktop compositing is enabled, as it leads
// to frame jitter
return;
}
#endif
window->wgl.interval = interval;
// HACK: Disable WGL swap interval when desktop composition is enabled to
// avoid interfering with DWM vsync
if (_glfwIsCompositionEnabled() && !window->monitor)
interval = 0;
if (window->wgl.EXT_swap_control)
window->wgl.SwapIntervalEXT(interval);
@@ -647,14 +627,14 @@ void _glfwPlatformSwapInterval(int interval)
int _glfwPlatformExtensionSupported(const char* extension)
{
const GLubyte* extensions;
const char* extensions;
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (window->wgl.GetExtensionsStringEXT != NULL)
{
extensions = (GLubyte*) window->wgl.GetExtensionsStringEXT();
if (extensions != NULL)
extensions = window->wgl.GetExtensionsStringEXT();
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GL_TRUE;
@@ -663,8 +643,8 @@ int _glfwPlatformExtensionSupported(const char* extension)
if (window->wgl.GetExtensionsStringARB != NULL)
{
extensions = (GLubyte*) window->wgl.GetExtensionsStringARB(window->wgl.dc);
if (extensions != NULL)
extensions = window->wgl.GetExtensionsStringARB(window->wgl.dc);
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GL_TRUE;
@@ -676,7 +656,7 @@ int _glfwPlatformExtensionSupported(const char* extension)
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
{
const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
const GLFWglproc proc = (GLFWglproc) _glfw_wglGetProcAddress(procname);
if (proc)
return proc;
+23 -5
View File
@@ -25,14 +25,26 @@
//
//========================================================================
#ifndef _wgl_context_h_
#define _wgl_context_h_
#ifndef _glfw3_wgl_context_h_
#define _glfw3_wgl_context_h_
// This path may need to be changed if you build GLFW using your own setup
// We ship and use our own copy of wglext.h since GLFW uses fairly new
// extensions and not all operating systems come with an up-to-date version
#include "../deps/GL/wglext.h"
// opengl32.dll function pointer typedefs
typedef HGLRC (WINAPI * WGLCREATECONTEXT_T)(HDC);
typedef BOOL (WINAPI * WGLDELETECONTEXT_T)(HGLRC);
typedef PROC (WINAPI * WGLGETPROCADDRESS_T)(LPCSTR);
typedef BOOL (WINAPI * WGLMAKECURRENT_T)(HDC,HGLRC);
typedef BOOL (WINAPI * WGLSHARELISTS_T)(HGLRC,HGLRC);
#define _glfw_wglCreateContext _glfw.wgl.opengl32.CreateContext
#define _glfw_wglDeleteContext _glfw.wgl.opengl32.DeleteContext
#define _glfw_wglGetProcAddress _glfw.wgl.opengl32.GetProcAddress
#define _glfw_wglMakeCurrent _glfw.wgl.opengl32.MakeCurrent
#define _glfw_wglShareLists _glfw.wgl.opengl32.ShareLists
#define _GLFW_PLATFORM_FBCONFIG int wgl
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL wgl
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl
@@ -44,6 +56,7 @@ typedef struct _GLFWcontextWGL
{
HDC dc; // Private GDI device context
HGLRC context; // Permanent rendering context
int interval;
// WGL extensions (context specific)
PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;
@@ -54,6 +67,7 @@ typedef struct _GLFWcontextWGL
GLboolean EXT_swap_control;
GLboolean ARB_multisample;
GLboolean ARB_framebuffer_sRGB;
GLboolean EXT_framebuffer_sRGB;
GLboolean ARB_pixel_format;
GLboolean ARB_create_context;
GLboolean ARB_create_context_profile;
@@ -68,9 +82,13 @@ typedef struct _GLFWcontextWGL
//
typedef struct _GLFWlibraryWGL
{
// opengl32.dll (for glfwGetProcAddress)
struct {
HINSTANCE instance;
HINSTANCE instance;
WGLCREATECONTEXT_T CreateContext;
WGLDELETECONTEXT_T DeleteContext;
WGLGETPROCADDRESS_T GetProcAddress;
WGLMAKECURRENT_T MakeCurrent;
WGLSHARELISTS_T ShareLists;
} opengl32;
} _GLFWlibraryWGL;
@@ -86,4 +104,4 @@ int _glfwAnalyzeContext(const _GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig);
#endif // _wgl_context_h_
#endif // _glfw3_wgl_context_h_
+17 -7
View File
@@ -31,14 +31,21 @@
#include <malloc.h>
#if defined(_GLFW_USE_OPTIMUS_HPG)
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
// Applications exporting this symbol with this value will be automatically
// directed to the high-performance GPU on Nvidia Optimus systems
// directed to the high-performance GPU on Nvidia Optimus systems with
// up-to-date drivers
//
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
__declspec(dllexport) DWORD NvOptimusEnablement = 1;
#endif // _GLFW_USE_OPTIMUS_HPG
// Applications exporting this symbol with this value will be automatically
// directed to the high-performance GPU on AMD PowerXpress systems with
// up-to-date drivers
//
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
#endif // _GLFW_USE_HYBRID_HPG
#if defined(_GLFW_BUILD_DLL)
@@ -96,6 +103,8 @@ static GLboolean initLibraries(void)
{
_glfw.win32.dwmapi.DwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED_T)
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
_glfw.win32.dwmapi.DwmFlush = (DWMFLUSH_T)
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
}
return GL_TRUE;
@@ -360,7 +369,7 @@ void _glfwPlatformTerminate(void)
const char* _glfwPlatformGetVersionString(void)
{
const char* version = _GLFW_VERSION_NUMBER " Win32"
return _GLFW_VERSION_NUMBER " Win32"
#if defined(_GLFW_WGL)
" WGL"
#elif defined(_GLFW_EGL)
@@ -371,11 +380,12 @@ const char* _glfwPlatformGetVersionString(void)
#elif defined(_MSC_VER)
" VisualC"
#endif
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
" hybrid-GPU"
#endif
#if defined(_GLFW_BUILD_DLL)
" DLL"
#endif
;
return version;
}
+48 -39
View File
@@ -103,7 +103,7 @@ void _glfwRestoreVideoMode(_GLFWmonitor* monitor)
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
{
int size = 0, found = 0;
int found = 0;
_GLFWmonitor** monitors = NULL;
DWORD adapterIndex, displayIndex;
@@ -125,6 +125,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
for (displayIndex = 0; ; displayIndex++)
{
DISPLAY_DEVICEW display;
_GLFWmonitor* monitor;
char* name;
HDC dc;
@@ -134,12 +135,6 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
break;
if (found == size)
{
size += 4;
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * size);
}
name = _glfwCreateUTF8FromWideString(display.DeviceString);
if (!name)
{
@@ -150,35 +145,40 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
dc = CreateDCW(L"DISPLAY", adapter.DeviceName, NULL, NULL);
monitors[found] = _glfwAllocMonitor(name,
GetDeviceCaps(dc, HORZSIZE),
GetDeviceCaps(dc, VERTSIZE));
monitor = _glfwAllocMonitor(name,
GetDeviceCaps(dc, HORZSIZE),
GetDeviceCaps(dc, VERTSIZE));
DeleteDC(dc);
free(name);
wcscpy(monitors[found]->win32.adapterName, adapter.DeviceName);
wcscpy(monitors[found]->win32.displayName, display.DeviceName);
if (adapter.StateFlags & DISPLAY_DEVICE_MODESPRUNED)
monitor->win32.modesPruned = GL_TRUE;
wcscpy(monitor->win32.adapterName, adapter.DeviceName);
wcscpy(monitor->win32.displayName, display.DeviceName);
WideCharToMultiByte(CP_UTF8, 0,
adapter.DeviceName, -1,
monitors[found]->win32.publicAdapterName,
sizeof(monitors[found]->win32.publicAdapterName),
monitor->win32.publicAdapterName,
sizeof(monitor->win32.publicAdapterName),
NULL, NULL);
WideCharToMultiByte(CP_UTF8, 0,
display.DeviceName, -1,
monitors[found]->win32.publicDisplayName,
sizeof(monitors[found]->win32.publicDisplayName),
monitor->win32.publicDisplayName,
sizeof(monitor->win32.publicDisplayName),
NULL, NULL);
found++;
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
monitors[found - 1] = monitor;
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE &&
displayIndex == 0)
{
_GLFW_SWAP_POINTERS(monitors[0], monitors[found]);
_GLFW_SWAP_POINTERS(monitors[0], monitors[found - 1]);
}
found++;
}
}
@@ -208,12 +208,12 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
*ypos = settings.dmPosition.y;
}
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
{
int modeIndex = 0, count = 0;
int modeIndex = 0, size = 0;
GLFWvidmode* result = NULL;
*found = 0;
*count = 0;
for (;;)
{
@@ -229,11 +229,9 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
modeIndex++;
// Skip modes with less than 15 BPP
if (dm.dmBitsPerPel < 15)
{
// Skip modes with less than 15 BPP
continue;
}
mode.width = dm.dmPelsWidth;
mode.height = dm.dmPelsHeight;
@@ -243,30 +241,41 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
&mode.greenBits,
&mode.blueBits);
for (i = 0; i < *found; i++)
for (i = 0; i < *count; i++)
{
if (_glfwCompareVideoModes(result + i, &mode) == 0)
break;
}
if (i < *found)
{
// This is a duplicate, so skip it
// Skip duplicate modes
if (i < *count)
continue;
}
if (*found == count)
if (monitor->win32.modesPruned)
{
if (count)
count *= 2;
else
count = 128;
result = (GLFWvidmode*) realloc(result, count * sizeof(GLFWvidmode));
// Skip modes not supported by the connected displays
if (ChangeDisplaySettingsExW(monitor->win32.adapterName,
&dm,
NULL,
CDS_TEST,
NULL) != DISP_CHANGE_SUCCESSFUL)
{
continue;
}
}
result[*found] = mode;
(*found)++;
if (*count == size)
{
if (*count)
size *= 2;
else
size = 128;
result = (GLFWvidmode*) realloc(result, size * sizeof(GLFWvidmode));
}
(*count)++;
result[*count - 1] = mode;
}
return result;
+9 -14
View File
@@ -25,9 +25,8 @@
//
//========================================================================
#ifndef _win32_platform_h_
#define _win32_platform_h_
#ifndef _glfw3_win32_platform_h_
#define _glfw3_win32_platform_h_
// We don't need all the fancy stuff
#ifndef NOMINMAX
@@ -71,9 +70,7 @@
#define strdup _strdup
#endif
// HACK: Define macros that some older windows.h variants don't
#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x020E
#endif
@@ -102,7 +99,6 @@ typedef struct tagCHANGEFILTERSTRUCT
#endif
#endif /*Windows 7*/
// winmm.dll function pointer typedefs
typedef MMRESULT (WINAPI * JOYGETDEVCAPS_T)(UINT,LPJOYCAPS,UINT);
typedef MMRESULT (WINAPI * JOYGETPOS_T)(UINT,LPJOYINFO);
@@ -121,15 +117,16 @@ typedef BOOL (WINAPI * CHANGEWINDOWMESSAGEFILTEREX_T)(HWND,UINT,DWORD,PCHANGEFIL
// dwmapi.dll function pointer typedefs
typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*);
typedef HRESULT (WINAPI * DWMFLUSH_T)(VOID);
#define _glfw_DwmIsCompositionEnabled _glfw.win32.dwmapi.DwmIsCompositionEnabled
#define _glfw_DwmFlush _glfw.win32.dwmapi.DwmFlush
#define _GLFW_RECREATION_NOT_NEEDED 0
#define _GLFW_RECREATION_REQUIRED 1
#define _GLFW_RECREATION_IMPOSSIBLE 2
#include "win32_tls.h"
#include "winmm_joystick.h"
#if defined(_GLFW_WGL)
#include "wgl_context.h"
@@ -141,8 +138,6 @@ typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*);
#error "No supported context creation API selected"
#endif
#include "winmm_joystick.h"
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time
@@ -155,10 +150,8 @@ typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*);
typedef struct _GLFWwindowWin32
{
HWND handle;
DWORD dwStyle;
DWORD dwExStyle;
GLboolean cursorInside;
GLboolean cursorTracked;
GLboolean iconified;
// The last received cursor position, regardless of source
@@ -195,6 +188,7 @@ typedef struct _GLFWlibraryWin32
struct {
HINSTANCE instance;
DWMISCOMPOSITIONENABLED_T DwmIsCompositionEnabled;
DWMFLUSH_T DwmFlush;
} dwmapi;
} _GLFWlibraryWin32;
@@ -209,6 +203,7 @@ typedef struct _GLFWmonitorWin32
WCHAR displayName[32];
char publicAdapterName[64];
char publicDisplayName[64];
GLboolean modesPruned;
GLboolean modeChanged;
} _GLFWmonitorWin32;
@@ -247,4 +242,4 @@ void _glfwInitTimer(void);
GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwRestoreVideoMode(_GLFWmonitor* monitor);
#endif // _win32_platform_h_
#endif // _glfw3_win32_platform_h_
+3 -3
View File
@@ -32,7 +32,7 @@
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
int _glfwInitTLS(void)
int _glfwCreateContextTLS(void)
{
_glfw.win32_tls.context = TlsAlloc();
if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES)
@@ -46,13 +46,13 @@ int _glfwInitTLS(void)
return GL_TRUE;
}
void _glfwTerminateTLS(void)
void _glfwDestroyContextTLS(void)
{
if (_glfw.win32_tls.allocated)
TlsFree(_glfw.win32_tls.context);
}
void _glfwSetCurrentContext(_GLFWwindow* context)
void _glfwSetContextTLS(_GLFWwindow* context)
{
TlsSetValue(_glfw.win32_tls.context, context);
}
+6 -6
View File
@@ -25,8 +25,8 @@
//
//========================================================================
#ifndef _win32_tls_h_
#define _win32_tls_h_
#ifndef _glfw3_win32_tls_h_
#define _glfw3_win32_tls_h_
#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsWin32 win32_tls
@@ -41,8 +41,8 @@ typedef struct _GLFWtlsWin32
} _GLFWtlsWin32;
int _glfwInitTLS(void);
void _glfwTerminateTLS(void);
void _glfwSetCurrentContext(_GLFWwindow* context);
int _glfwCreateContextTLS(void);
void _glfwDestroyContextTLS(void);
void _glfwSetContextTLS(_GLFWwindow* context);
#endif // _win32_tls_h_
#endif // _glfw3_win32_tls_h_
+97 -84
View File
@@ -38,6 +38,37 @@
#define _GLFW_WNDCLASSNAME L"GLFW30"
// Returns the window style for the specified window
//
static DWORD getWindowStyle(const _GLFWwindow* window)
{
DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
if (window->decorated && !window->monitor)
{
style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
if (window->resizable)
style |= WS_MAXIMIZEBOX | WS_SIZEBOX;
}
else
style |= WS_POPUP;
return style;
}
// Returns the extended window style for the specified window
//
static DWORD getWindowExStyle(const _GLFWwindow* window)
{
DWORD style = WS_EX_APPWINDOW;
if (window->decorated && !window->monitor)
style |= WS_EX_WINDOWEDGE;
return style;
}
// Updates the cursor clip rect
//
static void updateClipRect(_GLFWwindow* window)
@@ -249,9 +280,6 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (window->cursorMode != GLFW_CURSOR_NORMAL)
_glfwPlatformApplyCursorMode(window);
if (window->monitor && window->autoIconify)
enterFullscreenMode(window);
_glfwInputWindowFocus(window, GL_TRUE);
return 0;
}
@@ -262,10 +290,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
restoreCursor(window);
if (window->monitor && window->autoIconify)
{
_glfwPlatformIconifyWindow(window);
leaveFullscreenMode(window);
}
_glfwInputWindowFocus(window, GL_FALSE);
return 0;
@@ -431,12 +456,12 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
if (_glfw.focusedWindow != window)
if (_glfw.cursorWindow != window)
break;
_glfwInputCursorMotion(window,
x - window->win32.cursorPosX,
y - window->win32.cursorPosY);
x - window->win32.cursorPosX,
y - window->win32.cursorPosY);
}
else
_glfwInputCursorMotion(window, x, y);
@@ -444,7 +469,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
window->win32.cursorPosX = x;
window->win32.cursorPosY = y;
if (!window->win32.cursorInside)
if (!window->win32.cursorTracked)
{
TRACKMOUSEEVENT tme;
ZeroMemory(&tme, sizeof(tme));
@@ -453,7 +478,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
tme.hwndTrack = window->win32.handle;
TrackMouseEvent(&tme);
window->win32.cursorInside = GL_TRUE;
window->win32.cursorTracked = GL_TRUE;
_glfwInputCursorEnter(window, GL_TRUE);
}
@@ -462,7 +487,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_MOUSELEAVE:
{
window->win32.cursorInside = GL_FALSE;
window->win32.cursorTracked = GL_FALSE;
_glfwInputCursorEnter(window, GL_FALSE);
return 0;
}
@@ -483,7 +508,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_SIZE:
{
if (_glfw.focusedWindow == window)
if (_glfw.cursorWindow == window)
{
if (window->cursorMode == GLFW_CURSOR_DISABLED)
updateClipRect(window);
@@ -492,12 +517,18 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (!window->win32.iconified && wParam == SIZE_MINIMIZED)
{
window->win32.iconified = GL_TRUE;
if (window->monitor)
leaveFullscreenMode(window);
_glfwInputWindowIconify(window, GL_TRUE);
}
else if (window->win32.iconified &&
(wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED))
{
window->win32.iconified = GL_FALSE;
if (window->monitor)
enterFullscreenMode(window);
_glfwInputWindowIconify(window, GL_FALSE);
}
@@ -508,7 +539,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_MOVE:
{
if (_glfw.focusedWindow == window)
if (_glfw.cursorWindow == window)
{
if (window->cursorMode == GLFW_CURSOR_DISABLED)
updateClipRect(window);
@@ -535,7 +566,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_SETCURSOR:
{
if (_glfw.focusedWindow == window && LOWORD(lParam) == HTCLIENT)
if (_glfw.cursorWindow == window && LOWORD(lParam) == HTCLIENT)
{
if (window->cursorMode == GLFW_CURSOR_HIDDEN ||
window->cursorMode == GLFW_CURSOR_DISABLED)
@@ -563,39 +594,25 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
break;
}
case WM_DWMCOMPOSITIONCHANGED:
{
if (_glfwIsCompositionEnabled())
{
_GLFWwindow* previous = _glfwPlatformGetCurrentContext();
_glfwPlatformMakeContextCurrent(window);
_glfwPlatformSwapInterval(0);
_glfwPlatformMakeContextCurrent(previous);
}
// TODO: Restore vsync if compositing was disabled
break;
}
case WM_DROPFILES:
{
HDROP hDrop = (HDROP) wParam;
HDROP drop = (HDROP) wParam;
POINT pt;
int i;
const int count = DragQueryFileW(hDrop, 0xffffffff, NULL, 0);
const int count = DragQueryFileW(drop, 0xffffffff, NULL, 0);
char** paths = calloc(count, sizeof(char*));
// Move the mouse to the position of the drop
DragQueryPoint(hDrop, &pt);
DragQueryPoint(drop, &pt);
_glfwInputCursorMotion(window, pt.x, pt.y);
for (i = 0; i < count; i++)
{
const UINT length = DragQueryFileW(hDrop, i, NULL, 0);
const UINT length = DragQueryFileW(drop, i, NULL, 0);
WCHAR* buffer = calloc(length + 1, sizeof(WCHAR));
DragQueryFileW(hDrop, i, buffer, length + 1);
DragQueryFileW(drop, i, buffer, length + 1);
paths[i] = _glfwCreateUTF8FromWideString(buffer);
free(buffer);
@@ -607,7 +624,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
free(paths[i]);
free(paths);
DragFinish(hDrop);
DragFinish(drop);
return 0;
}
}
@@ -622,8 +639,8 @@ static void getFullWindowSize(_GLFWwindow* window,
int* fullWidth, int* fullHeight)
{
RECT rect = { 0, 0, clientWidth, clientHeight };
AdjustWindowRectEx(&rect, window->win32.dwStyle,
FALSE, window->win32.dwExStyle);
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
*fullWidth = rect.right - rect.left;
*fullHeight = rect.bottom - rect.top;
}
@@ -638,35 +655,20 @@ static int createWindow(_GLFWwindow* window,
int xpos, ypos, fullWidth, fullHeight;
WCHAR* wideTitle;
window->win32.dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
window->win32.dwExStyle = WS_EX_APPWINDOW;
if (window->monitor)
if (wndconfig->monitor)
{
window->win32.dwStyle |= WS_POPUP;
GLFWvidmode mode;
// NOTE: This window placement is temporary and approximate, as the
// correct position and size cannot be known until the monitor
// video mode has been set
_glfwPlatformGetMonitorPos(wndconfig->monitor, &xpos, &ypos);
fullWidth = wndconfig->width;
fullHeight = wndconfig->height;
_glfwPlatformGetVideoMode(wndconfig->monitor, &mode);
fullWidth = mode.width;
fullHeight = mode.height;
}
else
{
if (wndconfig->decorated)
{
window->win32.dwStyle |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
if (wndconfig->resizable)
{
window->win32.dwStyle |= WS_MAXIMIZEBOX | WS_SIZEBOX;
window->win32.dwExStyle |= WS_EX_WINDOWEDGE;
}
}
else
window->win32.dwStyle |= WS_POPUP;
xpos = CW_USEDEFAULT;
ypos = CW_USEDEFAULT;
@@ -683,10 +685,10 @@ static int createWindow(_GLFWwindow* window,
return GL_FALSE;
}
window->win32.handle = CreateWindowExW(window->win32.dwExStyle,
window->win32.handle = CreateWindowExW(getWindowExStyle(window),
_GLFW_WNDCLASSNAME,
wideTitle,
window->win32.dwStyle,
getWindowStyle(window),
xpos, ypos,
fullWidth, fullHeight,
NULL, // No parent window
@@ -715,9 +717,9 @@ static int createWindow(_GLFWwindow* window,
if (wndconfig->floating && !wndconfig->monitor)
{
SetWindowPos(window->win32.handle,
HWND_TOPMOST,
0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
HWND_TOPMOST,
0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
}
DragAcceptFiles(window->win32.handle, TRUE);
@@ -884,8 +886,8 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
{
RECT rect = { xpos, ypos, xpos, ypos };
AdjustWindowRectEx(&rect, window->win32.dwStyle,
FALSE, window->win32.dwExStyle);
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
SetWindowPos(window->win32.handle, NULL, rect.left, rect.top, 0, 0,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
}
@@ -930,8 +932,8 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
_glfwPlatformGetWindowSize(window, &width, &height);
SetRect(&rect, 0, 0, width, height);
AdjustWindowRectEx(&rect, window->win32.dwStyle,
FALSE, window->win32.dwExStyle);
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
if (left)
*left = -rect.left;
@@ -989,7 +991,6 @@ int _glfwPlatformWindowVisible(_GLFWwindow* window)
void _glfwPlatformPollEvents(void)
{
MSG msg;
_GLFWwindow* window;
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
{
@@ -999,7 +1000,7 @@ void _glfwPlatformPollEvents(void)
// While GLFW does not itself post WM_QUIT, other processes may post
// it to this one, for example Task Manager
window = _glfw.windowListHead;
_GLFWwindow* window = _glfw.windowListHead;
while (window)
{
_glfwInputWindowCloseRequest(window);
@@ -1013,9 +1014,10 @@ void _glfwPlatformPollEvents(void)
}
}
window = _glfw.focusedWindow;
if (window)
if (_glfw.cursorWindow)
{
_GLFWwindow* window = _glfw.cursorWindow;
// LSHIFT/RSHIFT fixup (keys tend to "stick" without this fix)
// This is the only async event handling in GLFW, but it solves some
// nasty problems
@@ -1035,12 +1037,18 @@ void _glfwPlatformPollEvents(void)
_glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, 0, GLFW_RELEASE, mods);
}
// Did the cursor move in an focused window that has disabled the cursor
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
int width, height;
_glfwPlatformGetWindowSize(window, &width, &height);
_glfwPlatformSetCursorPos(window, width / 2, height / 2);
// NOTE: Re-center the cursor only if it has moved since the last
// call, to avoid breaking glfwWaitEvents with WM_MOUSEMOVE
if (window->win32.cursorPosX != width / 2 ||
window->win32.cursorPosY != height / 2)
{
_glfwPlatformSetCursorPos(window, width / 2, height / 2);
}
}
}
}
@@ -1188,19 +1196,24 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{
// It should be guaranteed that the cursor is not being used by this window if
// the following condition is not met. That way it should be safe to destroy the
// cursor after calling glfwSetCursor(window, NULL) on all windows using the cursor.
POINT pos;
if (_glfw.focusedWindow == window &&
window->cursorMode == GLFW_CURSOR_NORMAL &&
window->win32.cursorInside)
{
if (cursor)
SetCursor(cursor->win32.handle);
else
SetCursor(LoadCursorW(NULL, IDC_ARROW));
}
if (_glfw.cursorWindow != window)
return;
if (window->cursorMode != GLFW_CURSOR_NORMAL)
return;
if (!GetCursorPos(&pos))
return;
if (WindowFromPoint(pos) != window->win32.handle)
return;
if (cursor)
SetCursor(cursor->win32.handle);
else
SetCursor(LoadCursorW(NULL, IDC_ARROW));
}
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
+106 -139
View File
@@ -40,7 +40,7 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLboolean focused)
{
if (focused)
{
_glfw.focusedWindow = window;
_glfw.cursorWindow = window;
if (window->callbacks.focus)
window->callbacks.focus((GLFWwindow*) window, focused);
@@ -49,7 +49,7 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLboolean focused)
{
int i;
_glfw.focusedWindow = NULL;
_glfw.cursorWindow = NULL;
if (window->callbacks.focus)
window->callbacks.focus((GLFWwindow*) window, focused);
@@ -132,45 +132,22 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
return NULL;
}
// Set up desired framebuffer config
fbconfig.redBits = _glfw.hints.redBits;
fbconfig.greenBits = _glfw.hints.greenBits;
fbconfig.blueBits = _glfw.hints.blueBits;
fbconfig.alphaBits = _glfw.hints.alphaBits;
fbconfig.depthBits = _glfw.hints.depthBits;
fbconfig.stencilBits = _glfw.hints.stencilBits;
fbconfig.accumRedBits = _glfw.hints.accumRedBits;
fbconfig.accumGreenBits = _glfw.hints.accumGreenBits;
fbconfig.accumBlueBits = _glfw.hints.accumBlueBits;
fbconfig.accumAlphaBits = _glfw.hints.accumAlphaBits;
fbconfig.auxBuffers = _glfw.hints.auxBuffers;
fbconfig.stereo = _glfw.hints.stereo ? GL_TRUE : GL_FALSE;
fbconfig.samples = _glfw.hints.samples;
fbconfig.sRGB = _glfw.hints.sRGB;
fbconfig.doublebuffer = _glfw.hints.doublebuffer ? GL_TRUE : GL_FALSE;
fbconfig = _glfw.hints.framebuffer;
ctxconfig = _glfw.hints.context;
wndconfig = _glfw.hints.window;
// Set up desired window config
wndconfig.width = width;
wndconfig.height = height;
wndconfig.title = title;
wndconfig.resizable = _glfw.hints.resizable ? GL_TRUE : GL_FALSE;
wndconfig.visible = _glfw.hints.visible ? GL_TRUE : GL_FALSE;
wndconfig.decorated = _glfw.hints.decorated ? GL_TRUE : GL_FALSE;
wndconfig.focused = _glfw.hints.focused ? GL_TRUE : GL_FALSE;
wndconfig.autoIconify = _glfw.hints.autoIconify ? GL_TRUE : GL_FALSE;
wndconfig.floating = _glfw.hints.floating ? GL_TRUE : GL_FALSE;
wndconfig.monitor = (_GLFWmonitor*) monitor;
wndconfig.width = width;
wndconfig.height = height;
wndconfig.title = title;
wndconfig.monitor = (_GLFWmonitor*) monitor;
ctxconfig.share = (_GLFWwindow*) share;
// Set up desired context config
ctxconfig.api = _glfw.hints.api;
ctxconfig.major = _glfw.hints.major;
ctxconfig.minor = _glfw.hints.minor;
ctxconfig.forward = _glfw.hints.forward ? GL_TRUE : GL_FALSE;
ctxconfig.debug = _glfw.hints.debug ? GL_TRUE : GL_FALSE;
ctxconfig.profile = _glfw.hints.profile;
ctxconfig.robustness = _glfw.hints.robustness;
ctxconfig.release = _glfw.hints.release;
ctxconfig.share = (_GLFWwindow*) share;
if (wndconfig.monitor)
{
wndconfig.resizable = GL_TRUE;
wndconfig.visible = GL_TRUE;
wndconfig.focused = GL_TRUE;
}
// Check the OpenGL bits of the window config
if (!_glfwIsValidContextConfig(&ctxconfig))
@@ -180,23 +157,13 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
window->next = _glfw.windowListHead;
_glfw.windowListHead = window;
if (wndconfig.monitor)
{
wndconfig.resizable = GL_TRUE;
wndconfig.visible = GL_TRUE;
wndconfig.focused = GL_TRUE;
window->videoMode.width = width;
window->videoMode.height = height;
window->videoMode.redBits = fbconfig.redBits;
window->videoMode.greenBits = fbconfig.greenBits;
window->videoMode.blueBits = fbconfig.blueBits;
window->videoMode.refreshRate = _glfw.hints.refreshRate;
// Set up desired video mode
window->videoMode.width = width;
window->videoMode.height = height;
window->videoMode.redBits = _glfw.hints.redBits;
window->videoMode.greenBits = _glfw.hints.greenBits;
window->videoMode.blueBits = _glfw.hints.blueBits;
window->videoMode.refreshRate = _glfw.hints.refreshRate;
}
// Transfer window hints that are persistent settings and not
// just initial states
window->monitor = wndconfig.monitor;
window->resizable = wndconfig.resizable;
window->decorated = wndconfig.decorated;
@@ -235,7 +202,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
// Clearing the front buffer to black to avoid garbage pixels left over
// from previous uses of our bit of VRAM
glClear(GL_COLOR_BUFFER_BIT);
window->Clear(GL_COLOR_BUFFER_BIT);
_glfwPlatformSwapBuffers(window);
// Restore the previously current context (or NULL)
@@ -272,29 +239,29 @@ void glfwDefaultWindowHints(void)
memset(&_glfw.hints, 0, sizeof(_glfw.hints));
// The default is OpenGL with minimum version 1.0
_glfw.hints.api = GLFW_OPENGL_API;
_glfw.hints.major = 1;
_glfw.hints.minor = 0;
_glfw.hints.context.api = GLFW_OPENGL_API;
_glfw.hints.context.major = 1;
_glfw.hints.context.minor = 0;
// The default is a focused, visible, resizable window with decorations
_glfw.hints.resizable = GL_TRUE;
_glfw.hints.visible = GL_TRUE;
_glfw.hints.decorated = GL_TRUE;
_glfw.hints.focused = GL_TRUE;
_glfw.hints.autoIconify = GL_TRUE;
// The default is to select the highest available refresh rate
_glfw.hints.refreshRate = GLFW_DONT_CARE;
_glfw.hints.window.resizable = GL_TRUE;
_glfw.hints.window.visible = GL_TRUE;
_glfw.hints.window.decorated = GL_TRUE;
_glfw.hints.window.focused = GL_TRUE;
_glfw.hints.window.autoIconify = GL_TRUE;
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
// double buffered
_glfw.hints.redBits = 8;
_glfw.hints.greenBits = 8;
_glfw.hints.blueBits = 8;
_glfw.hints.alphaBits = 8;
_glfw.hints.depthBits = 24;
_glfw.hints.stencilBits = 8;
_glfw.hints.doublebuffer = GL_TRUE;
_glfw.hints.framebuffer.redBits = 8;
_glfw.hints.framebuffer.greenBits = 8;
_glfw.hints.framebuffer.blueBits = 8;
_glfw.hints.framebuffer.alphaBits = 8;
_glfw.hints.framebuffer.depthBits = 24;
_glfw.hints.framebuffer.stencilBits = 8;
_glfw.hints.framebuffer.doublebuffer = GL_TRUE;
// The default is to select the highest available refresh rate
_glfw.hints.refreshRate = GLFW_DONT_CARE;
}
GLFWAPI void glfwWindowHint(int target, int hint)
@@ -304,95 +271,95 @@ GLFWAPI void glfwWindowHint(int target, int hint)
switch (target)
{
case GLFW_RED_BITS:
_glfw.hints.redBits = hint;
_glfw.hints.framebuffer.redBits = hint;
break;
case GLFW_GREEN_BITS:
_glfw.hints.greenBits = hint;
_glfw.hints.framebuffer.greenBits = hint;
break;
case GLFW_BLUE_BITS:
_glfw.hints.blueBits = hint;
_glfw.hints.framebuffer.blueBits = hint;
break;
case GLFW_ALPHA_BITS:
_glfw.hints.alphaBits = hint;
_glfw.hints.framebuffer.alphaBits = hint;
break;
case GLFW_DEPTH_BITS:
_glfw.hints.depthBits = hint;
_glfw.hints.framebuffer.depthBits = hint;
break;
case GLFW_STENCIL_BITS:
_glfw.hints.stencilBits = hint;
_glfw.hints.framebuffer.stencilBits = hint;
break;
case GLFW_ACCUM_RED_BITS:
_glfw.hints.accumRedBits = hint;
_glfw.hints.framebuffer.accumRedBits = hint;
break;
case GLFW_ACCUM_GREEN_BITS:
_glfw.hints.accumGreenBits = hint;
_glfw.hints.framebuffer.accumGreenBits = hint;
break;
case GLFW_ACCUM_BLUE_BITS:
_glfw.hints.accumBlueBits = hint;
_glfw.hints.framebuffer.accumBlueBits = hint;
break;
case GLFW_ACCUM_ALPHA_BITS:
_glfw.hints.accumAlphaBits = hint;
_glfw.hints.framebuffer.accumAlphaBits = hint;
break;
case GLFW_AUX_BUFFERS:
_glfw.hints.auxBuffers = hint;
_glfw.hints.framebuffer.auxBuffers = hint;
break;
case GLFW_STEREO:
_glfw.hints.stereo = hint;
_glfw.hints.framebuffer.stereo = hint ? GL_TRUE : GL_FALSE;
break;
case GLFW_DOUBLEBUFFER:
_glfw.hints.framebuffer.doublebuffer = hint ? GL_TRUE : GL_FALSE;
break;
case GLFW_SAMPLES:
_glfw.hints.framebuffer.samples = hint;
break;
case GLFW_SRGB_CAPABLE:
_glfw.hints.framebuffer.sRGB = hint ? GL_TRUE : GL_FALSE;
break;
case GLFW_RESIZABLE:
_glfw.hints.window.resizable = hint ? GL_TRUE : GL_FALSE;
break;
case GLFW_DECORATED:
_glfw.hints.window.decorated = hint ? GL_TRUE : GL_FALSE;
break;
case GLFW_FOCUSED:
_glfw.hints.window.focused = hint ? GL_TRUE : GL_FALSE;
break;
case GLFW_AUTO_ICONIFY:
_glfw.hints.window.autoIconify = hint ? GL_TRUE : GL_FALSE;
break;
case GLFW_FLOATING:
_glfw.hints.window.floating = hint ? GL_TRUE : GL_FALSE;
break;
case GLFW_VISIBLE:
_glfw.hints.window.visible = hint ? GL_TRUE : GL_FALSE;
break;
case GLFW_CLIENT_API:
_glfw.hints.context.api = hint;
break;
case GLFW_CONTEXT_VERSION_MAJOR:
_glfw.hints.context.major = hint;
break;
case GLFW_CONTEXT_VERSION_MINOR:
_glfw.hints.context.minor = hint;
break;
case GLFW_CONTEXT_ROBUSTNESS:
_glfw.hints.context.robustness = hint;
break;
case GLFW_OPENGL_FORWARD_COMPAT:
_glfw.hints.context.forward = hint ? GL_TRUE : GL_FALSE;
break;
case GLFW_OPENGL_DEBUG_CONTEXT:
_glfw.hints.context.debug = hint ? GL_TRUE : GL_FALSE;
break;
case GLFW_OPENGL_PROFILE:
_glfw.hints.context.profile = hint;
break;
case GLFW_CONTEXT_RELEASE_BEHAVIOR:
_glfw.hints.context.release = hint;
break;
case GLFW_REFRESH_RATE:
_glfw.hints.refreshRate = hint;
break;
case GLFW_DOUBLEBUFFER:
_glfw.hints.doublebuffer = hint;
break;
case GLFW_RESIZABLE:
_glfw.hints.resizable = hint;
break;
case GLFW_DECORATED:
_glfw.hints.decorated = hint;
break;
case GLFW_FOCUSED:
_glfw.hints.focused = hint;
break;
case GLFW_AUTO_ICONIFY:
_glfw.hints.autoIconify = hint;
break;
case GLFW_FLOATING:
_glfw.hints.floating = hint;
break;
case GLFW_VISIBLE:
_glfw.hints.visible = hint;
break;
case GLFW_SAMPLES:
_glfw.hints.samples = hint;
break;
case GLFW_SRGB_CAPABLE:
_glfw.hints.sRGB = hint;
break;
case GLFW_CLIENT_API:
_glfw.hints.api = hint;
break;
case GLFW_CONTEXT_VERSION_MAJOR:
_glfw.hints.major = hint;
break;
case GLFW_CONTEXT_VERSION_MINOR:
_glfw.hints.minor = hint;
break;
case GLFW_CONTEXT_ROBUSTNESS:
_glfw.hints.robustness = hint;
break;
case GLFW_OPENGL_FORWARD_COMPAT:
_glfw.hints.forward = hint;
break;
case GLFW_OPENGL_DEBUG_CONTEXT:
_glfw.hints.debug = hint;
break;
case GLFW_OPENGL_PROFILE:
_glfw.hints.profile = hint;
break;
case GLFW_CONTEXT_RELEASE_BEHAVIOR:
_glfw.hints.release = hint;
break;
default:
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint");
break;
@@ -418,8 +385,8 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
_glfwPlatformMakeContextCurrent(NULL);
// Clear the focused window pointer if this is the focused window
if (_glfw.focusedWindow == window)
_glfw.focusedWindow = NULL;
if (_glfw.cursorWindow == window)
_glfw.cursorWindow = NULL;
_glfwPlatformDestroyWindow(window);
+3 -3
View File
@@ -24,8 +24,8 @@
//
//========================================================================
#ifndef _winmm_joystick_h_
#define _winmm_joystick_h_
#ifndef _glfw3_winmm_joystick_h_
#define _glfw3_winmm_joystick_h_
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
_GLFWjoystickWinMM winmm_js[GLFW_JOYSTICK_LAST + 1]
@@ -44,4 +44,4 @@ typedef struct _GLFWjoystickWinMM
void _glfwInitJoysticks(void);
void _glfwTerminateJoysticks(void);
#endif // _winmm_joystick_h_
#endif // _glfw3_winmm_joystick_h_
+11 -4
View File
@@ -35,7 +35,6 @@
#include <wayland-client.h>
#include <wayland-cursor.h>
#include "xkb_unicode.h"
static void pointerHandleEnter(void* data,
struct wl_pointer* pointer,
@@ -86,6 +85,11 @@ static void pointerHandleMotion(void* data,
"Wayland: GLFW_CURSOR_DISABLED not supported");
return;
}
else
{
window->wl.cursorPosX = wl_fixed_to_double(sx);
window->wl.cursorPosY = wl_fixed_to_double(sy);
}
_glfwInputCursorMotion(window,
wl_fixed_to_double(sx),
@@ -616,15 +620,18 @@ void _glfwPlatformTerminate(void)
const char* _glfwPlatformGetVersionString(void)
{
const char* version = _GLFW_VERSION_NUMBER " Wayland EGL "
return _GLFW_VERSION_NUMBER " Wayland EGL"
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
" clock_gettime"
#else
" gettimeofday"
#endif
#if defined(__linux__)
" /dev/js"
#endif
#if defined(_GLFW_BUILD_DLL)
" shared"
#endif
;
return version;
}
+9 -8
View File
@@ -24,23 +24,23 @@
//
//========================================================================
#ifndef _wayland_platform_h_
#define _wayland_platform_h_
#ifndef _glfw3_wayland_platform_h_
#define _glfw3_wayland_platform_h_
#include <wayland-client.h>
#include <xkbcommon/xkbcommon.h>
#include "posix_tls.h"
#include "posix_time.h"
#include "linux_joystick.h"
#include "xkb_unicode.h"
#if defined(_GLFW_EGL)
#include "egl_context.h"
#else
#error "The Wayland backend depends on EGL platform support"
#endif
#include "posix_tls.h"
#include "posix_time.h"
#include "linux_joystick.h"
#define _GLFW_EGL_NATIVE_WINDOW window->wl.native
#define _GLFW_EGL_NATIVE_DISPLAY _glfw.wl.display
@@ -66,6 +66,7 @@ typedef struct _GLFWwindowWayland
struct wl_shell_surface* shell_surface;
struct wl_callback* callback;
_GLFWcursor* currentCursor;
double cursorPosX, cursorPosY;
} _GLFWwindowWayland;
@@ -137,4 +138,4 @@ typedef struct _GLFWcursorWayland
void _glfwAddOutput(uint32_t name, uint32_t version);
#endif // _wayland_platform_h_
#endif // _glfw3_wayland_platform_h_
+44 -37
View File
@@ -114,6 +114,43 @@ createTmpfileCloexec(char* tmpname)
return fd;
}
static void
handleEvents(int timeout)
{
struct wl_display* display = _glfw.wl.display;
struct pollfd fds[] = {
{ wl_display_get_fd(display), POLLIN },
};
while (wl_display_prepare_read(display) != 0)
wl_display_dispatch_pending(display);
// If an error different from EAGAIN happens, we have likely been
// disconnected from the Wayland session, try to handle that the best we
// can.
if (wl_display_flush(display) < 0 && errno != EAGAIN)
{
_GLFWwindow* window = _glfw.windowListHead;
while (window)
{
_glfwInputWindowCloseRequest(window);
window = window->next;
}
wl_display_cancel_read(display);
return;
}
if (poll(fds, 1, timeout) > 0)
{
wl_display_read_events(display);
wl_display_dispatch_pending(display);
}
else
{
wl_display_cancel_read(display);
}
}
/*
* Create a new, unique, anonymous file of the given size, and
* return the file descriptor for it. The file descriptor is set
@@ -150,7 +187,7 @@ createAnonymousFile(off_t size)
return -1;
}
name = malloc(strlen(path) + sizeof(template));
name = calloc(strlen(path) + sizeof(template), 1);
strcpy(name, path);
strcat(name, template);
@@ -327,44 +364,12 @@ int _glfwPlatformWindowVisible(_GLFWwindow* window)
void _glfwPlatformPollEvents(void)
{
struct wl_display* display = _glfw.wl.display;
struct pollfd fds[] = {
{ wl_display_get_fd(display), POLLIN },
};
while (wl_display_prepare_read(display) != 0)
wl_display_dispatch_pending(display);
wl_display_flush(display);
if (poll(fds, 1, 0) > 0)
{
wl_display_read_events(display);
wl_display_dispatch_pending(display);
}
else
{
wl_display_cancel_read(display);
}
handleEvents(0);
}
void _glfwPlatformWaitEvents(void)
{
struct wl_display* display = _glfw.wl.display;
struct pollfd fds[] = {
{ wl_display_get_fd(display), POLLIN },
};
while (wl_display_prepare_read(display) != 0)
wl_display_dispatch_pending(display);
wl_display_flush(display);
if (poll(fds, 1, -1) > 0)
{
wl_display_read_events(display);
wl_display_dispatch_pending(display);
}
else
{
wl_display_cancel_read(display);
}
handleEvents(-1);
}
void _glfwPlatformPostEmptyEvent(void)
@@ -374,8 +379,10 @@ void _glfwPlatformPostEmptyEvent(void)
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
{
// TODO
fprintf(stderr, "_glfwPlatformGetCursorPos not implemented yet\n");
if (xpos)
*xpos = window->wl.cursorPosX;
if (ypos)
*ypos = window->wl.cursorPosY;
}
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
+51 -43
View File
@@ -38,7 +38,7 @@
// Translate an X11 key code to a GLFW key code.
//
static int translateKey(int scancode)
static int translateKeyCode(int scancode)
{
int keySym;
@@ -241,15 +241,14 @@ static void createKeyTables(void)
// keyboard layout
char name[XkbKeyNameLength + 1];
XkbDescPtr descr = XkbGetKeyboard(_glfw.x11.display,
XkbAllComponentsMask,
XkbUseCoreKbd);
XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd);
XkbGetNames(_glfw.x11.display, XkbKeyNamesMask, desc);
// Find the X11 key code -> GLFW key code mapping
for (scancode = descr->min_key_code; scancode <= descr->max_key_code; scancode++)
for (scancode = desc->min_key_code; scancode <= desc->max_key_code; scancode++)
{
memcpy(name, descr->names->keys[scancode].name, XkbKeyNameLength);
name[XkbKeyNameLength] = 0;
memcpy(name, desc->names->keys[scancode].name, XkbKeyNameLength);
name[XkbKeyNameLength] = '\0';
// Map the key name to a GLFW key code. Note: We only map printable
// keys here, and we use the US keyboard layout. The rest of the
@@ -309,7 +308,8 @@ static void createKeyTables(void)
_glfw.x11.publicKeys[scancode] = key;
}
XkbFreeKeyboard(descr, 0, True);
XkbFreeNames(desc, XkbKeyNamesMask, True);
XkbFreeClientMap(desc, 0, True);
}
// Translate the un-translated key codes using traditional X11 KeySym
@@ -317,7 +317,7 @@ static void createKeyTables(void)
for (scancode = 0; scancode < 256; scancode++)
{
if (_glfw.x11.publicKeys[scancode] < 0)
_glfw.x11.publicKeys[scancode] = translateKey(scancode);
_glfw.x11.publicKeys[scancode] = translateKeyCode(scancode);
}
}
@@ -459,8 +459,6 @@ static void detectEWMH(void)
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_BYPASS_COMPOSITOR");
XFree(supportedAtoms);
_glfw.x11.hasEWMH = GL_TRUE;
}
// Initialize X11 display and look for supported X11 extensions
@@ -498,8 +496,8 @@ static GLboolean initExtensions(void)
XRRScreenResources* sr;
if (!XRRQueryVersion(_glfw.x11.display,
&_glfw.x11.randr.versionMajor,
&_glfw.x11.randr.versionMinor))
&_glfw.x11.randr.major,
&_glfw.x11.randr.minor))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"X11: Failed to query RandR version");
@@ -507,11 +505,8 @@ static GLboolean initExtensions(void)
}
// The GLFW RandR path requires at least version 1.3
if (_glfw.x11.randr.versionMajor == 1 &&
_glfw.x11.randr.versionMinor < 3)
{
if (_glfw.x11.randr.major == 1 && _glfw.x11.randr.minor < 3)
_glfw.x11.randr.available = GL_FALSE;
}
sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root);
@@ -530,8 +525,8 @@ static GLboolean initExtensions(void)
}
if (XineramaQueryExtension(_glfw.x11.display,
&_glfw.x11.xinerama.versionMajor,
&_glfw.x11.xinerama.versionMinor))
&_glfw.x11.xinerama.major,
&_glfw.x11.xinerama.minor))
{
if (XineramaIsActive(_glfw.x11.display))
_glfw.x11.xinerama.available = GL_TRUE;
@@ -544,12 +539,12 @@ static GLboolean initExtensions(void)
&_glfw.x11.xi.eventBase,
&_glfw.x11.xi.errorBase))
{
_glfw.x11.xi.versionMajor = 2;
_glfw.x11.xi.versionMinor = 0;
_glfw.x11.xi.major = 2;
_glfw.x11.xi.minor = 0;
if (XIQueryVersion(_glfw.x11.display,
&_glfw.x11.xi.versionMajor,
&_glfw.x11.xi.versionMinor) != BadRequest)
&_glfw.x11.xi.major,
&_glfw.x11.xi.minor) != BadRequest)
{
_glfw.x11.xi.available = GL_TRUE;
}
@@ -557,15 +552,15 @@ static GLboolean initExtensions(void)
#endif /*_GLFW_HAS_XINPUT*/
// Check if Xkb is supported on this display
_glfw.x11.xkb.versionMajor = 1;
_glfw.x11.xkb.versionMinor = 0;
_glfw.x11.xkb.major = 1;
_glfw.x11.xkb.minor = 0;
_glfw.x11.xkb.available =
XkbQueryExtension(_glfw.x11.display,
&_glfw.x11.xkb.majorOpcode,
&_glfw.x11.xkb.eventBase,
&_glfw.x11.xkb.errorBase,
&_glfw.x11.xkb.versionMajor,
&_glfw.x11.xkb.versionMinor);
&_glfw.x11.xkb.major,
&_glfw.x11.xkb.minor);
if (_glfw.x11.xkb.available)
{
@@ -714,17 +709,30 @@ Cursor _glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)
int _glfwPlatformInit(void)
{
#if !defined(X_HAVE_UTF8_STRING)
// HACK: If the current locale is C, apply the environment's locale
// This is done because the C locale breaks character input
// This is done because the C locale breaks wide character input
if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0)
setlocale(LC_CTYPE, "");
#endif
XInitThreads();
_glfw.x11.display = XOpenDisplay(NULL);
if (!_glfw.x11.display)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to open X display");
const char* display = getenv("DISPLAY");
if (display)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"X11: Failed to open display %s", display);
}
else
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"X11: The DISPLAY environment variable is missing");
}
return GL_FALSE;
}
@@ -741,7 +749,7 @@ int _glfwPlatformInit(void)
{
XSetLocaleModifiers("");
_glfw.x11.im = XOpenIM(_glfw.x11.display, 0, 0, 0);
_glfw.x11.im = XOpenIM(_glfw.x11.display, 0, NULL, NULL);
if (_glfw.x11.im)
{
if (!hasUsableInputMethodStyle())
@@ -780,43 +788,43 @@ void _glfwPlatformTerminate(void)
}
_glfwTerminateJoysticks();
_glfwTerminateContextAPI();
if (_glfw.x11.display)
{
XCloseDisplay(_glfw.x11.display);
_glfw.x11.display = NULL;
}
// NOTE: This needs to be done after XCloseDisplay, as libGL registers
// internal cleanup callbacks in libX11
_glfwTerminateContextAPI();
}
const char* _glfwPlatformGetVersionString(void)
{
const char* version = _GLFW_VERSION_NUMBER " X11"
return _GLFW_VERSION_NUMBER " X11"
#if defined(_GLFW_GLX)
" GLX"
#elif defined(_GLFW_EGL)
" EGL"
#endif
#if defined(_GLFW_HAS_GLXGETPROCADDRESS)
" glXGetProcAddress"
#elif defined(_GLFW_HAS_GLXGETPROCADDRESSARB)
" glXGetProcAddressARB"
#elif defined(_GLFW_HAS_GLXGETPROCADDRESSEXT)
" glXGetProcAddressEXT"
#elif defined(_GLFW_DLOPEN_LIBGL)
" dlsym(libGL)"
#endif
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
" clock_gettime"
#else
" gettimeofday"
#endif
#if defined(__linux__)
" /dev/js"
#endif
#if defined(_GLFW_HAS_XINPUT)
" XI"
#endif
#if defined(_GLFW_HAS_XF86VM)
" Xf86vm"
#endif
#if defined(_GLFW_BUILD_DLL)
" shared"
#endif
;
return version;
}
+23 -26
View File
@@ -200,7 +200,7 @@ void _glfwRestoreVideoMode(_GLFWmonitor* monitor)
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
{
int i, j, k, size = 0, found = 0;
int i, j, k, found = 0;
_GLFWmonitor** monitors = NULL;
*count = 0;
@@ -214,6 +214,8 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
RROutput primary = XRRGetOutputPrimary(_glfw.x11.display,
_glfw.x11.root);
monitors = calloc(sr->noutput, sizeof(_GLFWmonitor*));
if (_glfw.x11.xinerama.available)
screens = XineramaQueryScreens(_glfw.x11.display, &screenCount);
@@ -225,6 +227,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
for (j = 0; j < ci->noutput; j++)
{
int widthMM, heightMM;
_GLFWmonitor* monitor;
XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display,
sr, ci->outputs[j]);
if (oi->connection != RR_Connected)
@@ -233,12 +236,6 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
continue;
}
if (found == size)
{
size += 4;
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * size);
}
if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
{
widthMM = oi->mm_height;
@@ -250,9 +247,9 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
heightMM = oi->mm_height;
}
monitors[found] = _glfwAllocMonitor(oi->name, widthMM, heightMM);
monitors[found]->x11.output = ci->outputs[j];
monitors[found]->x11.crtc = oi->crtc;
monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);
monitor->x11.output = ci->outputs[j];
monitor->x11.crtc = oi->crtc;
for (k = 0; k < screenCount; k++)
{
@@ -261,17 +258,18 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
screens[k].width == ci->width &&
screens[k].height == ci->height)
{
monitors[found]->x11.index = k;
monitor->x11.index = k;
break;
}
}
XRRFreeOutputInfo(oi);
if (ci->outputs[j] == primary)
_GLFW_SWAP_POINTERS(monitors[0], monitors[found]);
found++;
monitors[found - 1] = monitor;
if (ci->outputs[j] == primary)
_GLFW_SWAP_POINTERS(monitors[0], monitors[found - 1]);
}
XRRFreeCrtcInfo(ci);
@@ -286,7 +284,10 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"X11: RandR monitor support seems broken");
_glfw.x11.randr.monitorBroken = GL_TRUE;
free(monitors);
monitors = NULL;
}
}
@@ -330,13 +331,11 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
}
}
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
{
GLFWvidmode* result;
*found = 0;
// Build array of available resolutions
*count = 0;
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
{
@@ -359,20 +358,18 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
for (j = 0; j < *found; j++)
for (j = 0; j < *count; j++)
{
if (_glfwCompareVideoModes(result + j, &mode) == 0)
break;
}
if (j < *found)
{
// This is a duplicate, so skip it
// Skip duplicate modes
if (j < *count)
continue;
}
result[*found] = mode;
(*found)++;
(*count)++;
result[*count - 1] = mode;
}
XRRFreeOutputInfo(oi);
@@ -381,7 +378,7 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
}
else
{
*found = 1;
*count = 1;
result = calloc(1, sizeof(GLFWvidmode));
_glfwPlatformGetVideoMode(monitor, result);
}
+20 -19
View File
@@ -25,8 +25,8 @@
//
//========================================================================
#ifndef _x11_platform_h_
#define _x11_platform_h_
#ifndef _glfw3_x11_platform_h_
#define _glfw3_x11_platform_h_
#include <unistd.h>
#include <signal.h>
@@ -57,6 +57,9 @@
#endif
#include "posix_tls.h"
#include "posix_time.h"
#include "linux_joystick.h"
#include "xkb_unicode.h"
#if defined(_GLFW_GLX)
#define _GLFW_X11_CONTEXT_VISUAL window->glx.visual
@@ -70,10 +73,6 @@
#error "No supported context creation API selected"
#endif
#include "posix_time.h"
#include "linux_joystick.h"
#include "xkb_unicode.h"
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11
@@ -88,8 +87,6 @@ typedef struct _GLFWwindowX11
Window handle;
XIC ic;
GLboolean overrideRedirect;
// Cached position and size used to filter out duplicate events
int width, height;
int xpos, ypos;
@@ -99,6 +96,12 @@ typedef struct _GLFWwindowX11
// The last position the cursor was warped to by GLFW
int warpPosX, warpPosY;
// The information from the last KeyPress event
struct {
unsigned int keycode;
Time time;
} last;
} _GLFWwindowX11;
@@ -116,8 +119,6 @@ typedef struct _GLFWlibraryX11
XContext context;
// XIM input method
XIM im;
// True if window manager supports EWMH
GLboolean hasEWMH;
// Most recent error code received by X error handler
int errorCode;
// Clipboard string (while the selection is owned)
@@ -170,8 +171,8 @@ typedef struct _GLFWlibraryX11
GLboolean available;
int eventBase;
int errorBase;
int versionMajor;
int versionMinor;
int major;
int minor;
GLboolean gammaBroken;
GLboolean monitorBroken;
} randr;
@@ -182,8 +183,8 @@ typedef struct _GLFWlibraryX11
int majorOpcode;
int eventBase;
int errorBase;
int versionMajor;
int versionMinor;
int major;
int minor;
} xkb;
struct {
@@ -200,8 +201,8 @@ typedef struct _GLFWlibraryX11
struct {
GLboolean available;
int versionMajor;
int versionMinor;
int major;
int minor;
} xinerama;
#if defined(_GLFW_HAS_XINPUT)
@@ -210,8 +211,8 @@ typedef struct _GLFWlibraryX11
int majorOpcode;
int eventBase;
int errorBase;
int versionMajor;
int versionMinor;
int major;
int minor;
} xi;
#endif /*_GLFW_HAS_XINPUT*/
@@ -264,4 +265,4 @@ void _glfwGrabXErrorHandler(void);
void _glfwReleaseXErrorHandler(void);
void _glfwInputXError(int error, const char* message);
#endif // _x11_platform_h_
#endif // _glfw3_x11_platform_h_
+338 -273
View File
@@ -36,6 +36,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <assert.h>
// Action for EWMH client messages
#define _NET_WM_STATE_REMOVE 0
@@ -46,32 +48,29 @@
#define Button6 6
#define Button7 7
typedef struct
{
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long input_mode;
unsigned long status;
} MotifWmHints;
#define MWM_HINTS_DECORATIONS (1L << 1)
// Wait for data to arrive
//
void selectDisplayConnection(struct timeval* timeout)
{
fd_set fds;
int result;
const int fd = ConnectionNumber(_glfw.x11.display);
FD_ZERO(&fds);
FD_SET(fd, &fds);
// select(1) is used instead of an X function like XNextEvent, as the
// wait inside those are guarded by the mutex protecting the display
// struct, locking out other threads from using X (including GLX)
select(fd + 1, &fds, NULL, NULL, timeout);
// NOTE: We use select instead of an X function like XNextEvent, as the
// wait inside those are guarded by the mutex protecting the display
// struct, locking out other threads from using X (including GLX)
// NOTE: Only retry on EINTR if there is no timeout, as select is not
// required to update it for the time elapsed
// TODO: Update timeout value manually
do
{
result = select(fd + 1, &fds, NULL, NULL, timeout);
}
while (result == -1 && errno == EINTR && timeout == NULL);
}
// Returns whether the window is iconified
@@ -114,7 +113,7 @@ static int translateCursorShape(int shape)
switch (shape)
{
case GLFW_ARROW_CURSOR:
return XC_arrow;
return XC_left_ptr;
case GLFW_IBEAM_CURSOR:
return XC_xterm;
case GLFW_CROSSHAIR_CURSOR:
@@ -148,7 +147,7 @@ static int translateState(int state)
return mods;
}
// Translates an X Window key to internal coding
// Translates an X11 key code to a GLFW key token
//
static int translateKey(int scancode)
{
@@ -176,9 +175,10 @@ static _GLFWwindow* findWindowByHandle(Window handle)
return window;
}
// Adds or removes an EWMH state to a window
// Sends an EWMH or ICCCM event to the window manager
//
static void changeWindowState(_GLFWwindow* window, Atom state, int action)
static void sendEventToWM(_GLFWwindow* window, Atom type,
long a, long b, long c, long d, long e)
{
XEvent event;
memset(&event, 0, sizeof(event));
@@ -186,14 +186,14 @@ static void changeWindowState(_GLFWwindow* window, Atom state, int action)
event.type = ClientMessage;
event.xclient.window = window->x11.handle;
event.xclient.format = 32; // Data is 32-bit longs
event.xclient.message_type = _glfw.x11.NET_WM_STATE;
event.xclient.data.l[0] = action;
event.xclient.data.l[1] = state;
event.xclient.data.l[2] = 0; // No secondary property
event.xclient.data.l[3] = 1; // Sender is a normal application
event.xclient.message_type = type;
event.xclient.data.l[0] = a;
event.xclient.data.l[1] = b;
event.xclient.data.l[2] = c;
event.xclient.data.l[3] = d;
event.xclient.data.l[4] = e;
XSendEvent(_glfw.x11.display,
_glfw.x11.root,
XSendEvent(_glfw.x11.display, _glfw.x11.root,
False,
SubstructureNotifyMask | SubstructureRedirectMask,
&event);
@@ -252,7 +252,7 @@ static GLboolean createWindow(_GLFWwindow* window,
{
unsigned long wamask;
XSetWindowAttributes wa;
XVisualInfo* visual = _GLFW_X11_CONTEXT_VISUAL;
XVisualInfo* vi = _GLFW_X11_CONTEXT_VISUAL;
// Every window needs a colormap
// Create one based on the visual used by the current context
@@ -260,7 +260,7 @@ static GLboolean createWindow(_GLFWwindow* window,
window->x11.colormap = XCreateColormap(_glfw.x11.display,
_glfw.x11.root,
visual->visual,
vi->visual,
AllocNone);
// Create the actual window
@@ -280,10 +280,10 @@ static GLboolean createWindow(_GLFWwindow* window,
_glfw.x11.root,
0, 0,
wndconfig->width, wndconfig->height,
0, // Border width
visual->depth, // Color depth
0, // Border width
vi->depth, // Color depth
InputOutput,
visual->visual,
vi->visual,
wamask,
&wa);
@@ -296,45 +296,69 @@ static GLboolean createWindow(_GLFWwindow* window,
return GL_FALSE;
}
if (!wndconfig->decorated)
{
MotifWmHints hints;
hints.flags = MWM_HINTS_DECORATIONS;
hints.decorations = 0;
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.MOTIF_WM_HINTS,
_glfw.x11.MOTIF_WM_HINTS, 32,
PropModeReplace,
(unsigned char*) &hints,
sizeof(MotifWmHints) / sizeof(long));
}
XSaveContext(_glfw.x11.display,
window->x11.handle,
_glfw.x11.context,
(XPointer) window);
}
if (window->monitor && !_glfw.x11.hasEWMH)
if (wndconfig->monitor)
{
// This is the butcher's way of removing window decorations
// Setting the override-redirect attribute on a window makes the window
// manager ignore the window completely (ICCCM, section 4)
// The good thing is that this makes undecorated full screen windows
// easy to do; the bad thing is that we have to do everything manually
// and some things (like iconify/restore) won't work at all, as those
// are tasks usually performed by the window manager
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_FULLSCREEN)
{
// This is the butcher's way of removing window decorations
// Setting the override-redirect attribute on a window makes the
// window manager ignore the window completely (ICCCM, section 4)
// The good thing is that this makes undecorated full screen windows
// easy to do; the bad thing is that we have to do everything
// manually and some things (like iconify/restore) won't work at
// all, as those are tasks usually performed by the window manager
XSetWindowAttributes attributes;
attributes.override_redirect = True;
XChangeWindowAttributes(_glfw.x11.display,
window->x11.handle,
CWOverrideRedirect,
&attributes);
window->x11.overrideRedirect = GL_TRUE;
XSetWindowAttributes attributes;
attributes.override_redirect = True;
XChangeWindowAttributes(_glfw.x11.display,
window->x11.handle,
CWOverrideRedirect,
&attributes);
}
}
else
{
if (!wndconfig->decorated)
{
struct
{
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long input_mode;
unsigned long status;
} hints;
hints.flags = 2; // Set decorations
hints.decorations = 0; // No decorations
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.MOTIF_WM_HINTS,
_glfw.x11.MOTIF_WM_HINTS, 32,
PropModeReplace,
(unsigned char*) &hints,
sizeof(hints) / sizeof(long));
}
if (wndconfig->floating)
{
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_ABOVE)
{
sendEventToWM(window,
_glfw.x11.NET_WM_STATE,
_NET_WM_STATE_ADD,
_glfw.x11.NET_WM_STATE_ABOVE,
0, 1, 0);
}
}
}
// Declare the WM protocols supported by GLFW
{
@@ -455,16 +479,6 @@ static GLboolean createWindow(_GLFWwindow* window,
PropModeReplace, (unsigned char*) &version, 1);
}
if (wndconfig->floating && !wndconfig->monitor)
{
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_ABOVE)
{
changeWindowState(window,
_glfw.x11.NET_WM_STATE_ABOVE,
_NET_WM_STATE_ADD);
}
}
_glfwPlatformSetWindowTitle(window, wndconfig->title);
XRRSelectInput(_glfw.x11.display, window->x11.handle,
@@ -673,18 +687,18 @@ static void handleSelectionRequest(XEvent* event)
{
const XSelectionRequestEvent* request = &event->xselectionrequest;
XEvent response;
memset(&response, 0, sizeof(response));
XEvent reply;
memset(&reply, 0, sizeof(reply));
response.xselection.property = writeTargetToProperty(request);
response.xselection.type = SelectionNotify;
response.xselection.display = request->display;
response.xselection.requestor = request->requestor;
response.xselection.selection = request->selection;
response.xselection.target = request->target;
response.xselection.time = request->time;
reply.xselection.property = writeTargetToProperty(request);
reply.xselection.type = SelectionNotify;
reply.xselection.display = request->display;
reply.xselection.requestor = request->requestor;
reply.xselection.selection = request->selection;
reply.xselection.target = request->target;
reply.xselection.time = request->time;
XSendEvent(_glfw.x11.display, request->requestor, False, 0, &response);
XSendEvent(_glfw.x11.display, request->requestor, False, 0, &reply);
}
static void pushSelectionToManager(_GLFWwindow* window)
@@ -763,80 +777,53 @@ static void enterFullscreenMode(_GLFWwindow* window)
PropModeReplace, (unsigned char*) &value, 1);
}
if (_glfw.x11.xinerama.available && _glfw.x11.NET_WM_FULLSCREEN_MONITORS)
// Position the window over its monitor
{
XEvent event;
memset(&event, 0, sizeof(event));
event.type = ClientMessage;
event.xclient.window = window->x11.handle;
event.xclient.format = 32; // Data is 32-bit longs
event.xclient.message_type = _glfw.x11.NET_WM_FULLSCREEN_MONITORS;
event.xclient.data.l[0] = window->monitor->x11.index;
event.xclient.data.l[1] = window->monitor->x11.index;
event.xclient.data.l[2] = window->monitor->x11.index;
event.xclient.data.l[3] = window->monitor->x11.index;
XSendEvent(_glfw.x11.display,
_glfw.x11.root,
False,
SubstructureNotifyMask | SubstructureRedirectMask,
&event);
}
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
{
int x, y;
_glfwPlatformGetMonitorPos(window->monitor, &x, &y);
_glfwPlatformSetWindowPos(window, x, y);
if (_glfw.x11.NET_ACTIVE_WINDOW)
{
// Ask the window manager to raise and focus the GLFW window
// Only focused windows with the _NET_WM_STATE_FULLSCREEN state end
// up on top of all other windows ("Stacking order" in EWMH spec)
XEvent event;
memset(&event, 0, sizeof(event));
event.type = ClientMessage;
event.xclient.window = window->x11.handle;
event.xclient.format = 32; // Data is 32-bit longs
event.xclient.message_type = _glfw.x11.NET_ACTIVE_WINDOW;
event.xclient.data.l[0] = 1; // Sender is a normal application
event.xclient.data.l[1] = 0; // We don't really know the timestamp
XSendEvent(_glfw.x11.display,
_glfw.x11.root,
False,
SubstructureNotifyMask | SubstructureRedirectMask,
&event);
}
// Ask the window manager to make the GLFW window a full screen window
// Full screen windows are undecorated and, when focused, are kept
// on top of all other windows
changeWindowState(window,
_glfw.x11.NET_WM_STATE_FULLSCREEN,
_NET_WM_STATE_ADD);
}
else if (window->x11.overrideRedirect)
{
// In override-redirect mode we have divorced ourselves from the
// window manager, so we need to do everything manually
int xpos, ypos;
GLFWvidmode mode;
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
_glfwPlatformGetVideoMode(window->monitor, &mode);
XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
xpos, ypos, mode.width, mode.height);
}
if (_glfw.x11.xinerama.available && _glfw.x11.NET_WM_FULLSCREEN_MONITORS)
{
sendEventToWM(window,
_glfw.x11.NET_WM_FULLSCREEN_MONITORS,
window->monitor->x11.index,
window->monitor->x11.index,
window->monitor->x11.index,
window->monitor->x11.index,
0);
}
if (_glfw.x11.NET_ACTIVE_WINDOW)
{
// Ask the window manager to raise and focus the GLFW window
// Only focused windows with the _NET_WM_STATE_FULLSCREEN state end up
// on top of all other windows ("Stacking order" in EWMH spec)
sendEventToWM(window, _glfw.x11.NET_ACTIVE_WINDOW, 1, 0, 0, 0, 0);
}
else
{
XRaiseWindow(_glfw.x11.display, window->x11.handle);
XSetInputFocus(_glfw.x11.display, window->x11.handle,
RevertToParent, CurrentTime);
XMoveWindow(_glfw.x11.display, window->x11.handle, xpos, ypos);
XResizeWindow(_glfw.x11.display, window->x11.handle,
mode.width, mode.height);
}
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
{
// Ask the window manager to make the GLFW window a full screen window
// Full screen windows are undecorated and, when focused, are kept
// on top of all other windows
sendEventToWM(window,
_glfw.x11.NET_WM_STATE,
_NET_WM_STATE_ADD,
_glfw.x11.NET_WM_STATE_FULLSCREEN,
0, 1, 0);
}
}
@@ -857,32 +844,47 @@ static void leaveFullscreenMode(_GLFWwindow* window)
_glfw.x11.saver.blanking,
_glfw.x11.saver.exposure);
}
if (_glfw.x11.NET_WM_BYPASS_COMPOSITOR)
{
const unsigned long value = 0;
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
PropModeReplace, (unsigned char*) &value, 1);
}
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
{
// Ask the window manager to make the GLFW window a normal window
// Normal windows usually have frames and other decorations
changeWindowState(window,
_glfw.x11.NET_WM_STATE_FULLSCREEN,
_NET_WM_STATE_REMOVE);
}
}
// Decode a Unicode code point from a UTF-8 stream
// Based on cutef8 by Jeff Bezanson (Public Domain)
//
#if defined(X_HAVE_UTF8_STRING)
static unsigned int decodeUTF8(const char** s)
{
unsigned int ch = 0, count = 0;
static const unsigned int offsets[] =
{
0x00000000u, 0x00003080u, 0x000e2080u,
0x03c82080u, 0xfa082080u, 0x82082080u
};
do
{
ch = (ch << 6) + (unsigned char) **s;
(*s)++;
count++;
} while ((**s & 0xc0) == 0x80);
assert(count <= 6);
return ch - offsets[count - 1];
}
#endif /*X_HAVE_UTF8_STRING*/
// Process the specified X event
//
static void processEvent(XEvent *event)
{
_GLFWwindow* window = NULL;
int keycode = 0;
Bool filtered = False;
// HACK: Save scancode as some IMs clear the field in XFilterEvent
if (event->type == KeyPress || event->type == KeyRelease)
keycode = event->xkey.keycode;
if (_glfw.x11.im)
filtered = XFilterEvent(event, None);
if (event->type != GenericEvent)
{
@@ -898,53 +900,101 @@ static void processEvent(XEvent *event)
{
case KeyPress:
{
const int key = translateKey(event->xkey.keycode);
const int key = translateKey(keycode);
const int mods = translateState(event->xkey.state);
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
if (event->xkey.keycode)
_glfwInputKey(window, key, event->xkey.keycode, GLFW_PRESS, mods);
if (window->x11.ic)
{
// Translate keys to characters with XIM input context
int i;
Status status;
wchar_t buffer[16];
if (XFilterEvent(event, None))
// HACK: Ignore duplicate key press events generated by ibus
// Corresponding release events are filtered out by the
// GLFW key repeat logic
if (window->x11.last.keycode != keycode ||
window->x11.last.time != event->xkey.time)
{
// Discard intermediary (dead key) events for character input
break;
if (keycode)
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
}
const int count = XwcLookupString(window->x11.ic,
&event->xkey,
buffer, sizeof(buffer),
NULL, &status);
window->x11.last.keycode = keycode;
window->x11.last.time = event->xkey.time;
for (i = 0; i < count; i++)
_glfwInputChar(window, buffer[i], mods, plain);
if (!filtered)
{
int count;
Status status;
#if defined(X_HAVE_UTF8_STRING)
char buffer[96];
char* chars = buffer;
count = Xutf8LookupString(window->x11.ic,
&event->xkey,
buffer, sizeof(buffer),
NULL, &status);
if (status == XBufferOverflow)
{
chars = calloc(count, 1);
count = Xutf8LookupString(window->x11.ic,
&event->xkey,
chars, count,
NULL, &status);
}
if (status == XLookupChars || status == XLookupBoth)
{
const char* c = chars;
while (c - chars < count)
_glfwInputChar(window, decodeUTF8(&c), mods, plain);
}
#else
wchar_t buffer[16];
wchar_t* chars = buffer;
count = XwcLookupString(window->x11.ic,
&event->xkey,
buffer, sizeof(buffer) / sizeof(wchar_t),
NULL, &status);
if (status == XBufferOverflow)
{
chars = calloc(count, sizeof(wchar_t));
count = XwcLookupString(window->x11.ic,
&event->xkey,
chars, count,
NULL, &status);
}
if (status == XLookupChars || status == XLookupBoth)
{
int i;
for (i = 0; i < count; i++)
_glfwInputChar(window, chars[i], mods, plain);
}
#endif
if (chars != buffer)
free(chars);
}
}
else
{
// Translate keys to characters with fallback lookup table
KeySym keysym;
XLookupString(&event->xkey, NULL, 0, &keysym, NULL);
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
const long character = _glfwKeySym2Unicode(keysym);
if (character != -1)
_glfwInputChar(window, character, mods, plain);
}
break;
return;
}
case KeyRelease:
{
const int key = translateKey(event->xkey.keycode);
const int key = translateKey(keycode);
const int mods = translateState(event->xkey.state);
if (!_glfw.x11.xkb.detectable)
@@ -955,12 +1005,12 @@ static void processEvent(XEvent *event)
// presses to repeat, so detect and discard release events
if (XEventsQueued(_glfw.x11.display, QueuedAfterReading))
{
XEvent nextEvent;
XPeekEvent(_glfw.x11.display, &nextEvent);
XEvent next;
XPeekEvent(_glfw.x11.display, &next);
if (nextEvent.type == KeyPress &&
nextEvent.xkey.window == event->xkey.window &&
nextEvent.xkey.keycode == event->xkey.keycode)
if (next.type == KeyPress &&
next.xkey.window == event->xkey.window &&
next.xkey.keycode == keycode)
{
// HACK: Repeat events sometimes leak through due to
// some sort of time drift, so add an epsilon
@@ -968,18 +1018,18 @@ static void processEvent(XEvent *event)
// per second so it's fairly safe to assume that
// no human is pressing the key 50 times per
// second (value is ms)
if ((nextEvent.xkey.time - event->xkey.time) < 20)
if ((next.xkey.time - event->xkey.time) < 20)
{
// This is very likely a server-generated key repeat
// event, so ignore it
break;
return;
}
}
}
}
_glfwInputKey(window, key, event->xkey.keycode, GLFW_RELEASE, mods);
break;
_glfwInputKey(window, key, keycode, GLFW_RELEASE, mods);
return;
}
case ButtonPress:
@@ -1013,7 +1063,7 @@ static void processEvent(XEvent *event)
mods);
}
break;
return;
}
case ButtonRelease:
@@ -1050,7 +1100,8 @@ static void processEvent(XEvent *event)
GLFW_RELEASE,
mods);
}
break;
return;
}
case EnterNotify:
@@ -1061,13 +1112,13 @@ static void processEvent(XEvent *event)
hideCursor(window);
_glfwInputCursorEnter(window, GL_TRUE);
break;
return;
}
case LeaveNotify:
{
_glfwInputCursorEnter(window, GL_FALSE);
break;
return;
}
case MotionNotify:
@@ -1081,8 +1132,8 @@ static void processEvent(XEvent *event)
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
if (_glfw.focusedWindow != window)
break;
if (_glfw.cursorWindow != window)
return;
_glfwInputCursorMotion(window,
x - window->x11.cursorPosX,
@@ -1094,7 +1145,7 @@ static void processEvent(XEvent *event)
window->x11.cursorPosX = x;
window->x11.cursorPosY = y;
break;
return;
}
case ConfigureNotify:
@@ -1125,38 +1176,43 @@ static void processEvent(XEvent *event)
window->x11.ypos = event->xconfigure.y;
}
break;
return;
}
case ClientMessage:
{
// Custom client message, probably from the window manager
if (filtered)
return;
if (event->xclient.message_type == None)
break;
return;
if (event->xclient.message_type == _glfw.x11.WM_PROTOCOLS)
{
if (_glfw.x11.WM_DELETE_WINDOW &&
(Atom) event->xclient.data.l[0] == _glfw.x11.WM_DELETE_WINDOW)
const Atom protocol = event->xclient.data.l[0];
if (protocol == None)
return;
if (protocol == _glfw.x11.WM_DELETE_WINDOW)
{
// The window manager was asked to close the window, for example by
// the user pressing a 'close' window decoration button
_glfwInputWindowCloseRequest(window);
}
else if (_glfw.x11.NET_WM_PING &&
(Atom) event->xclient.data.l[0] == _glfw.x11.NET_WM_PING)
else if (protocol == _glfw.x11.NET_WM_PING)
{
// The window manager is pinging the application to ensure it's
// still responding to events
event->xclient.window = _glfw.x11.root;
XSendEvent(_glfw.x11.display,
event->xclient.window,
False,
SubstructureNotifyMask | SubstructureRedirectMask,
event);
XEvent reply = *event;
reply.xclient.window = _glfw.x11.root;
XSendEvent(_glfw.x11.display, _glfw.x11.root,
False,
SubstructureNotifyMask | SubstructureRedirectMask,
&reply);
}
}
else if (event->xclient.message_type == _glfw.x11.XdndEnter)
@@ -1204,7 +1260,7 @@ static void processEvent(XEvent *event)
XFlush(_glfw.x11.display);
}
break;
return;
}
case SelectionNotify:
@@ -1250,39 +1306,56 @@ static void processEvent(XEvent *event)
XFlush(_glfw.x11.display);
}
break;
return;
}
case FocusIn:
{
if (event->xfocus.mode == NotifyNormal)
if (event->xfocus.mode == NotifyGrab ||
event->xfocus.mode == NotifyUngrab)
{
_glfwInputWindowFocus(window, GL_TRUE);
if (window->cursorMode == GLFW_CURSOR_DISABLED)
disableCursor(window);
// Ignore focus events from popup indicator windows, window menu
// key chords and window dragging
return;
}
break;
if (window->x11.ic)
XSetICFocus(window->x11.ic);
if (window->cursorMode == GLFW_CURSOR_DISABLED)
disableCursor(window);
_glfwInputWindowFocus(window, GL_TRUE);
return;
}
case FocusOut:
{
if (event->xfocus.mode == NotifyNormal)
if (event->xfocus.mode == NotifyGrab ||
event->xfocus.mode == NotifyUngrab)
{
_glfwInputWindowFocus(window, GL_FALSE);
if (window->cursorMode == GLFW_CURSOR_DISABLED)
restoreCursor(window);
// Ignore focus events from popup indicator windows, window menu
// key chords and window dragging
return;
}
break;
if (window->x11.ic)
XUnsetICFocus(window->x11.ic);
if (window->cursorMode == GLFW_CURSOR_DISABLED)
restoreCursor(window);
if (window->monitor && window->autoIconify)
_glfwPlatformIconifyWindow(window);
_glfwInputWindowFocus(window, GL_FALSE);
return;
}
case Expose:
{
_glfwInputWindowDamage(window);
break;
return;
}
case PropertyNotify:
@@ -1292,24 +1365,34 @@ static void processEvent(XEvent *event)
{
const int state = getWindowState(window);
if (state == IconicState)
{
if (window->monitor)
leaveFullscreenMode(window);
_glfwInputWindowIconify(window, GL_TRUE);
}
else if (state == NormalState)
{
if (window->monitor)
enterFullscreenMode(window);
_glfwInputWindowIconify(window, GL_FALSE);
}
}
break;
return;
}
case SelectionClear:
{
handleSelectionClear(event);
break;
return;
}
case SelectionRequest:
{
handleSelectionRequest(event);
break;
return;
}
case DestroyNotify:
@@ -1337,8 +1420,8 @@ static void processEvent(XEvent *event)
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
if (_glfw.focusedWindow != window)
break;
if (_glfw.cursorWindow != window)
return;
x = data->event_x - window->x11.cursorPosX;
y = data->event_y - window->x11.cursorPosY;
@@ -1359,23 +1442,15 @@ static void processEvent(XEvent *event)
}
XFreeEventData(_glfw.x11.display, &event->xcookie);
break;
return;
}
#endif /*_GLFW_HAS_XINPUT*/
}
default:
{
switch (event->type - _glfw.x11.randr.eventBase)
{
case RRScreenChangeNotify:
{
XRRUpdateConfiguration(event);
break;
}
}
break;
}
if (event->type - _glfw.x11.randr.eventBase == RRScreenChangeNotify)
{
XRRUpdateConfiguration(event);
return;
}
}
@@ -1560,7 +1635,7 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{
_glfwSetVideoMode(window->monitor, &window->videoMode);
if (window->x11.overrideRedirect)
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_FULLSCREEN)
{
GLFWvidmode mode;
_glfwPlatformGetVideoMode(window->monitor, &mode);
@@ -1607,27 +1682,17 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
if (!_glfwPlatformWindowVisible(window) &&
_glfw.x11.NET_REQUEST_FRAME_EXTENTS)
{
// Ensure _NET_FRAME_EXTENTS is set, allowing glfwGetWindowFrameSize to
// function before the window is mapped
double base;
XEvent event;
memset(&event, 0, sizeof(event));
event.type = ClientMessage;
event.xclient.window = window->x11.handle;
event.xclient.format = 32; // Data is 32-bit longs
event.xclient.message_type = _glfw.x11.NET_REQUEST_FRAME_EXTENTS;
// Ensure _NET_FRAME_EXTENTS is set, allowing glfwGetWindowFrameSize to
// function before the window is mapped
sendEventToWM(window, _glfw.x11.NET_REQUEST_FRAME_EXTENTS,
0, 0, 0, 0, 0);
XSendEvent(_glfw.x11.display,
_glfw.x11.root,
False,
SubstructureNotifyMask | SubstructureRedirectMask,
&event);
// HACK: Poll with timeout for the required response instead of blocking
// HACK: Poll with timeout for the required reply instead of blocking
// This is done because some window managers (at least Unity,
// Fluxbox and Xfwm) failed to send the required response
// Fluxbox and Xfwm) failed to send the required reply
// They have been fixed but broken versions are still in the wild
// If you are affected by this and your window manager is NOT
// listed above, PLEASE report it to their and our issue trackers
@@ -1675,12 +1740,12 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
{
if (window->x11.overrideRedirect)
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_FULLSCREEN)
{
// Override-redirect windows cannot be iconified or restored, as those
// tasks are performed by the window manager
_glfwInputError(GLFW_PLATFORM_ERROR,
"X11: Iconification of full screen windows requires a WM that supports EWMH");
"X11: Iconification of full screen windows requires a WM that supports EWMH full screen");
return;
}
@@ -1690,12 +1755,12 @@ void _glfwPlatformIconifyWindow(_GLFWwindow* window)
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
{
if (window->x11.overrideRedirect)
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_FULLSCREEN)
{
// Override-redirect windows cannot be iconified or restored, as those
// tasks are performed by the window manager
_glfwInputError(GLFW_PLATFORM_ERROR,
"X11: Iconification of full screen windows requires a WM that supports EWMH");
"X11: Iconification of full screen windows requires a WM that supports EWMH full screen");
return;
}
@@ -1752,7 +1817,7 @@ void _glfwPlatformPollEvents(void)
processEvent(&event);
}
_GLFWwindow* window = _glfw.focusedWindow;
_GLFWwindow* window = _glfw.cursorWindow;
if (window && window->cursorMode == GLFW_CURSOR_DISABLED)
{
int width, height;
@@ -1763,7 +1828,7 @@ void _glfwPlatformPollEvents(void)
void _glfwPlatformWaitEvents(void)
{
if (!XPending(_glfw.x11.display))
while (!XPending(_glfw.x11.display))
selectDisplayConnection(NULL);
_glfwPlatformPollEvents();
+3 -3
View File
@@ -24,10 +24,10 @@
//
//========================================================================
#ifndef _xkb_unicode_h_
#define _xkb_unicode_h_
#ifndef _glfw3_xkb_unicode_h_
#define _glfw3_xkb_unicode_h_
long _glfwKeySym2Unicode(unsigned int keysym);
#endif // _xkb_unicode_h_
#endif // _glfw3_xkb_unicode_h_
+6 -14
View File
@@ -21,31 +21,23 @@ set(TINYCTHREAD "${GLFW_SOURCE_DIR}/deps/tinycthread.h"
"${GLFW_SOURCE_DIR}/deps/tinycthread.c")
add_executable(clipboard clipboard.c ${GETOPT})
add_executable(defaults defaults.c)
add_executable(events events.c ${GETOPT})
add_executable(fsaa fsaa.c ${GETOPT})
add_executable(msaa msaa.c ${GETOPT})
add_executable(gamma gamma.c ${GETOPT})
add_executable(glfwinfo glfwinfo.c ${GETOPT})
add_executable(iconify iconify.c ${GETOPT})
add_executable(joysticks joysticks.c)
add_executable(monitors monitors.c ${GETOPT})
add_executable(peter peter.c)
add_executable(reopen reopen.c)
add_executable(cursor cursor.c)
add_executable(cursoranim WIN32 MACOSX_BUNDLE cursoranim.c)
set_target_properties(cursoranim PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Cursor animation")
add_executable(accuracy WIN32 MACOSX_BUNDLE accuracy.c)
set_target_properties(accuracy PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Accuracy")
add_executable(empty WIN32 MACOSX_BUNDLE empty.c ${TINYCTHREAD})
set_target_properties(empty PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Empty Event")
add_executable(sharing WIN32 MACOSX_BUNDLE sharing.c)
set_target_properties(sharing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Sharing")
add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c)
add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c ${GETOPT})
set_target_properties(tearing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Tearing")
add_executable(threads WIN32 MACOSX_BUNDLE threads.c ${TINYCTHREAD})
@@ -60,9 +52,9 @@ set_target_properties(windows PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Windows")
target_link_libraries(empty "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
target_link_libraries(threads "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
set(WINDOWS_BINARIES accuracy empty sharing tearing threads title windows cursoranim)
set(CONSOLE_BINARIES clipboard defaults events fsaa gamma glfwinfo
iconify joysticks monitors peter reopen cursor)
set(WINDOWS_BINARIES empty sharing tearing threads title windows)
set(CONSOLE_BINARIES clipboard events msaa gamma glfwinfo
iconify joysticks monitors reopen cursor)
set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
FOLDER "GLFW3/Tests")
@@ -77,6 +69,6 @@ if (APPLE)
set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}
MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION_FULL}
MACOSX_BUNDLE_INFO_PLIST "${GLFW_SOURCE_DIR}/CMake/AppleInfo.plist")
MACOSX_BUNDLE_INFO_PLIST "${GLFW_SOURCE_DIR}/CMake/MacOSXBundleInfo.plist.in")
endif()
-128
View File
@@ -1,128 +0,0 @@
//========================================================================
// Mouse cursor accuracy test
// Copyright (c) Camilla Berglund <elmindreda@elmindreda.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test came about as the result of bug #1867804
//
// No sign of said bug has so far been detected
//
//========================================================================
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
static double cursor_x = 0.0, cursor_y = 0.0;
static int window_width = 640, window_height = 480;
static int swap_interval = 1;
static void set_swap_interval(GLFWwindow* window, int interval)
{
char title[256];
swap_interval = interval;
glfwSwapInterval(swap_interval);
sprintf(title, "Cursor Inaccuracy Detector (interval %i)", swap_interval);
glfwSetWindowTitle(window, title);
}
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
window_width = width;
window_height = height;
glViewport(0, 0, window_width, window_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.f, window_width, 0.f, window_height, 0.f, 1.f);
}
static void cursor_position_callback(GLFWwindow* window, double x, double y)
{
cursor_x = x;
cursor_y = y;
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
set_swap_interval(window, 1 - swap_interval);
}
int main(void)
{
GLFWwindow* window;
int width, height;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
window = glfwCreateWindow(window_width, window_height, "", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetCursorPosCallback(window, cursor_position_callback);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetKeyCallback(window, key_callback);
glfwMakeContextCurrent(window);
glfwGetFramebufferSize(window, &width, &height);
framebuffer_size_callback(window, width, height);
set_swap_interval(window, swap_interval);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINES);
glVertex2f(0.f, (GLfloat) (window_height - cursor_y));
glVertex2f((GLfloat) window_width, (GLfloat) (window_height - cursor_y));
glVertex2f((GLfloat) cursor_x, 0.f);
glVertex2f((GLfloat) cursor_x, (GLfloat) window_height);
glEnd();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
exit(EXIT_SUCCESS);
}
+8 -2
View File
@@ -34,6 +34,12 @@
#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");
@@ -56,7 +62,7 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
break;
case GLFW_KEY_V:
if (mods == GLFW_MOD_CONTROL)
if (mods == MODIFIER)
{
const char* string;
@@ -69,7 +75,7 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
break;
case GLFW_KEY_C:
if (mods == GLFW_MOD_CONTROL)
if (mods == MODIFIER)
{
const char* string = "Hello GLFW World!";
glfwSetClipboardString(window, string);
+210 -195
View File
@@ -23,158 +23,83 @@
//
//========================================================================
//
// System cursors and input modes tests.
// This test provides an interface to the cursor image and cursor mode
// parts of the API.
//
// Custom cursor image generation by urraka.
//
//========================================================================
#include <GLFW/glfw3.h>
#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>
static int W = 640;
static int H = 480;
static int delay = 0;
#define CURSOR_FRAME_COUNT 60
static GLFWwindow* windows[2] = { NULL, NULL };
static GLFWwindow* activeWindow = NULL;
static GLFWcursor* cursor = NULL;
static struct
{
int key;
double time;
} commands[] = {
{GLFW_KEY_H, 0},
{GLFW_KEY_C, 0},
{GLFW_KEY_D, 0},
{GLFW_KEY_S, 0},
{GLFW_KEY_N, 0},
{GLFW_KEY_1, 0},
{GLFW_KEY_2, 0},
{GLFW_KEY_3, 0}
};
static int CommandCount = sizeof(commands) / sizeof(commands[0]);
static struct
{
int w, h;
} cursorSize[] = {
{ 24, 24 }, { 13, 37 }, { 5, 53 }, { 43, 64 }, { 300, 300 }
};
static int SizeCount = sizeof(cursorSize) / sizeof(cursorSize[0]);
static int currentSize = 0;
static void command_callback(int key)
{
switch (key)
{
case GLFW_KEY_H:
{
printf("H: show this help\n");
printf("C: call glfwCreateCursor()\n");
printf("D: call glfwDestroyCursor()\n");
printf("S: call glfwSetCursor()\n");
printf("N: call glfwSetCursor() with NULL\n");
printf("1: set GLFW_CURSOR_NORMAL\n");
printf("2: set GLFW_CURSOR_HIDDEN\n");
printf("3: set GLFW_CURSOR_DISABLED\n");
printf("T: enable 3s delay for all previous commands\n");
}
break;
case GLFW_KEY_C:
{
int x, y;
GLFWimage image;
unsigned char* pixels;
if (cursor)
break;
image.width = cursorSize[currentSize].w;
image.height = cursorSize[currentSize].h;
pixels = malloc(4 * image.width * image.height);
image.pixels = pixels;
for (y = 0; y < image.height; y++)
{
for (x = 0; x < image.width; x++)
{
*pixels++ = 0xff;
*pixels++ = 0;
*pixels++ = 255 * y / image.height;
*pixels++ = 255 * x / image.width;
}
}
cursor = glfwCreateCursor(&image, image.width / 2, image.height / 2);
currentSize = (currentSize + 1) % SizeCount;
free(image.pixels);
break;
}
case GLFW_KEY_D:
{
if (cursor != NULL)
{
glfwDestroyCursor(cursor);
cursor = NULL;
}
break;
}
case GLFW_KEY_S:
{
if (cursor != NULL)
glfwSetCursor(activeWindow, cursor);
else
printf("The cursor is not created\n");
break;
}
case GLFW_KEY_N:
glfwSetCursor(activeWindow, NULL);
break;
case GLFW_KEY_1:
glfwSetInputMode(activeWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
break;
case GLFW_KEY_2:
glfwSetInputMode(activeWindow, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
break;
case GLFW_KEY_3:
glfwSetInputMode(activeWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
break;
}
}
static double cursor_x;
static double cursor_y;
static int swap_interval = 1;
static GLboolean wait_events = GL_FALSE;
static GLboolean animate_cursor = GL_FALSE;
static GLboolean track_cursor = GL_FALSE;
static GLFWcursor* standard_cursors[6];
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)
static float star(int x, int y, float t)
{
W = width;
H = height;
const float c = 64 / 2.f;
glViewport(0, 0, W, H);
const float i = (0.25f * (float) sin(2.f * M_PI * t) + 0.75f);
const float k = 64 * 0.046875f * i;
const float dist = (float) sqrt((x - c) * (x - c) + (y - c) * (y - c));
const float salpha = 1.f - dist / c;
const float xalpha = (float) x == c ? c : k / (float) fabs(x - c);
const float yalpha = (float) y == c ? c : k / (float) fabs(y - c);
return (float) fmax(0.f, fmin(1.f, i * salpha * 0.2f + salpha * xalpha * yalpha));
}
static void refresh_callback(GLFWwindow* window)
static GLFWcursor* create_cursor_frame(float t)
{
glfwMakeContextCurrent(window);
glClearColor(0.0f, window == activeWindow ? 0.8f : 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
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 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)
@@ -184,104 +109,194 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
switch (key)
{
case GLFW_KEY_A:
{
animate_cursor = !animate_cursor;
if (!animate_cursor)
glfwSetCursor(window, NULL);
break;
}
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GL_TRUE);
{
if (glfwGetInputMode(window, GLFW_CURSOR) != GLFW_CURSOR_DISABLED)
{
glfwSetWindowShouldClose(window, GL_TRUE);
break;
}
/* FALLTHROUGH */
}
case GLFW_KEY_N:
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
printf("(( cursor is normal ))\n");
break;
case GLFW_KEY_D:
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
printf("(( cursor is disabled ))\n");
break;
case GLFW_KEY_H:
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
printf("(( cursor is hidden ))\n");
break;
case GLFW_KEY_SPACE:
swap_interval = 1 - swap_interval;
printf("(( swap interval: %i ))\n", swap_interval);
glfwSwapInterval(swap_interval);
break;
case GLFW_KEY_W:
wait_events = !wait_events;
printf("(( %sing for events ))\n", wait_events ? "wait" : "poll");
break;
case GLFW_KEY_T:
delay = !delay;
printf("Delay %s.\n", delay ? "enabled" : "disabled");
track_cursor = !track_cursor;
break;
default:
{
if (delay)
{
int i = 0;
case GLFW_KEY_0:
glfwSetCursor(window, NULL);
break;
while (i < CommandCount && commands[i].key != key)
i++;
case GLFW_KEY_1:
glfwSetCursor(window, standard_cursors[0]);
break;
if (i < CommandCount)
commands[i].time = glfwGetTime();
}
else
{
command_callback(key);
}
}
break;
}
}
case GLFW_KEY_2:
glfwSetCursor(window, standard_cursors[1]);
break;
static void focus_callback(GLFWwindow* window, int focused)
{
if (focused)
{
activeWindow = window;
refresh_callback(windows[0]);
refresh_callback(windows[1]);
case GLFW_KEY_3:
glfwSetCursor(window, standard_cursors[2]);
break;
case GLFW_KEY_4:
glfwSetCursor(window, standard_cursors[3]);
break;
case GLFW_KEY_5:
glfwSetCursor(window, standard_cursors[4]);
break;
case GLFW_KEY_6:
glfwSetCursor(window, standard_cursors[5]);
break;
}
}
int main(void)
{
int i;
GLboolean running = GL_TRUE;
GLFWwindow* window;
GLFWcursor* star_cursors[CURSOR_FRAME_COUNT];
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
for (i = 0; i < 2; i++)
for (i = 0; i < CURSOR_FRAME_COUNT; i++)
{
windows[i] = glfwCreateWindow(W, H, "Cursor testing", NULL, NULL);
if (!windows[i])
star_cursors[i] = create_cursor_frame(i / (float) CURSOR_FRAME_COUNT);
if (!star_cursors[i])
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetWindowPos(windows[i], 100 + (i & 1) * (W + 50), 100);
glfwSetWindowRefreshCallback(windows[i], refresh_callback);
glfwSetFramebufferSizeCallback(windows[i], framebuffer_size_callback);
glfwSetKeyCallback(windows[i], key_callback);
glfwSetWindowFocusCallback(windows[i], focus_callback);
glfwMakeContextCurrent(windows[i]);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(windows[i]);
}
activeWindow = windows[0];
key_callback(NULL, GLFW_KEY_H, 0, GLFW_PRESS, 0);
while (running)
for (i = 0; i < sizeof(standard_cursors) / sizeof(standard_cursors[0]); i++)
{
if (delay)
{
int i;
double t = glfwGetTime();
const int shapes[] = {
GLFW_ARROW_CURSOR,
GLFW_IBEAM_CURSOR,
GLFW_CROSSHAIR_CURSOR,
GLFW_HAND_CURSOR,
GLFW_HRESIZE_CURSOR,
GLFW_VRESIZE_CURSOR
};
for (i = 0; i < CommandCount; i++)
{
if (commands[i].time != 0 && t - commands[i].time >= 3.0)
{
command_callback(commands[i].key);
commands[i].time = 0;
}
}
standard_cursors[i] = glfwCreateStandardCursor(shapes[i]);
if (!standard_cursors[i])
{
glfwTerminate();
exit(EXIT_FAILURE);
}
}
window = glfwCreateWindow(640, 480, "Cursor Test", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
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;
glfwGetWindowSize(window, &wnd_width, &wnd_height);
glfwGetFramebufferSize(window, &fb_width, &fb_height);
scale = (float) fb_width / (float) wnd_width;
glViewport(0, 0, fb_width, fb_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.f, fb_width, 0.f, fb_height, 0.f, 1.f);
glBegin(GL_LINES);
glVertex2f(0.f, (GLfloat) (fb_height - cursor_y * scale));
glVertex2f((GLfloat) fb_width, (GLfloat) (fb_height - cursor_y * scale));
glVertex2f((GLfloat) cursor_x * scale, 0.f);
glVertex2f((GLfloat) cursor_x * scale, (GLfloat) fb_height);
glEnd();
}
running = !(glfwWindowShouldClose(windows[0]) || glfwWindowShouldClose(windows[1]));
glfwSwapBuffers(window);
glfwPollEvents();
if (animate_cursor)
{
const int i = (int) (glfwGetTime() * 30.0) % CURSOR_FRAME_COUNT;
glfwSetCursor(window, star_cursors[i]);
}
if (wait_events)
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);
}
-135
View File
@@ -1,135 +0,0 @@
//========================================================================
// Cursor animation
// Copyright (c) Camilla Berglund <elmindreda@elmindreda.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// Cursor animation test.
//
//========================================================================
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <math.h>
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
#define SIZE 64 // cursor size (width & height)
#define N 60 // number of frames
unsigned char buffer[4 * SIZE * SIZE];
static float max(float a, float b) { return a > b ? a : b; }
static float min(float a, float b) { return a < b ? a : b; }
static float star(int x, int y, float t)
{
float c = SIZE / 2.0f;
float i = (0.25f * (float)sin(2.0f * 3.1415926f * t) + 0.75f);
float k = SIZE * 0.046875f * i;
float dist = (float)sqrt((x - c) * (x - c) + (y - c) * (y - c));
float salpha = 1.0f - dist / c;
float xalpha = (float)x == c ? c : k / (float)fabs(x - c);
float yalpha = (float)y == c ? c : k / (float)fabs(y - c);
return max(0.0f, min(1.0f, i * salpha * 0.2f + salpha * xalpha * yalpha));
}
static GLFWcursor* load_frame(float t)
{
int i = 0, x, y;
const GLFWimage image = { SIZE, SIZE, buffer };
for (y = 0; y < image.width; y++)
{
for (x = 0; x < image.height; x++)
{
buffer[i++] = 255;
buffer[i++] = 255;
buffer[i++] = 255;
buffer[i++] = (unsigned char)(255 * star(x, y, t));
}
}
return glfwCreateCursor(&image, image.width / 2, image.height / 2);
}
int main(void)
{
int i;
double t0, t1, frameTime = 0.0;
GLFWwindow* window;
GLFWcursor* frames[N];
if (!glfwInit())
exit(EXIT_FAILURE);
window = glfwCreateWindow(640, 480, "Cursor animation", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
for (i = 0; i < N; i++)
frames[i] = load_frame(i / (float)N);
i = 0;
t0 = glfwGetTime();
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glfwSetCursor(window, frames[i]);
glfwSwapBuffers(window);
glfwPollEvents();
t1 = glfwGetTime();
frameTime += t1 - t0;
t0 = t1;
while (frameTime > 1.0 / (double)N)
{
i = (i + 1) % N;
frameTime -= 1.0 / (double)N;
}
}
glfwTerminate();
exit(EXIT_SUCCESS);
}
-131
View File
@@ -1,131 +0,0 @@
//========================================================================
// Default window/context test
// Copyright (c) Camilla Berglund <elmindreda@elmindreda.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test creates a windowed mode window with all window hints set to
// default values and then reports the actual attributes of the created
// window and context
//
//========================================================================
#define GLFW_INCLUDE_GLEXT
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int attrib;
const char* ext;
const char* name;
} AttribGL;
typedef struct
{
int attrib;
const char* name;
} AttribGLFW;
static AttribGL gl_attribs[] =
{
{ GL_RED_BITS, NULL, "red bits" },
{ GL_GREEN_BITS, NULL, "green bits" },
{ GL_BLUE_BITS, NULL, "blue bits" },
{ GL_ALPHA_BITS, NULL, "alpha bits" },
{ GL_DEPTH_BITS, NULL, "depth bits" },
{ GL_STENCIL_BITS, NULL, "stencil bits" },
{ GL_STEREO, NULL, "stereo" },
{ GL_SAMPLES_ARB, "GL_ARB_multisample", "FSAA samples" },
{ 0, NULL, NULL }
};
static AttribGLFW glfw_attribs[] =
{
{ GLFW_CONTEXT_VERSION_MAJOR, "Context version major" },
{ GLFW_CONTEXT_VERSION_MINOR, "Context version minor" },
{ GLFW_OPENGL_FORWARD_COMPAT, "OpenGL forward compatible" },
{ GLFW_OPENGL_DEBUG_CONTEXT, "OpenGL debug context" },
{ GLFW_OPENGL_PROFILE, "OpenGL profile" },
{ 0, NULL }
};
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
int main(void)
{
int i, width, height;
GLFWwindow* window;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
window = glfwCreateWindow(640, 480, "Defaults", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwGetFramebufferSize(window, &width, &height);
printf("framebuffer size: %ix%i\n", width, height);
for (i = 0; glfw_attribs[i].name; i++)
{
printf("%s: %i\n",
glfw_attribs[i].name,
glfwGetWindowAttrib(window, glfw_attribs[i].attrib));
}
for (i = 0; gl_attribs[i].name; i++)
{
GLint value = 0;
if (gl_attribs[i].ext)
{
if (!glfwExtensionSupported(gl_attribs[i].ext))
continue;
}
glGetIntegerv(gl_attribs[i].attrib, &value);
printf("%s: %i\n", gl_attribs[i].name, value);
}
glfwDestroyWindow(window);
window = NULL;
glfwTerminate();
exit(EXIT_SUCCESS);
}
+380 -158
View File
@@ -1,5 +1,5 @@
//========================================================================
// Version information dumper
// Context creation and information tool
// Copyright (c) Camilla Berglund <elmindreda@elmindreda.org>
//
// This software is provided 'as-is', without any express or implied
@@ -22,14 +22,13 @@
// distribution.
//
//========================================================================
//
// This test is a pale imitation of glxinfo(1), except not really
//
// It dumps GLFW and OpenGL version information
//
//========================================================================
#include <GLFW/glfw3.h>
/* HACK: Explicitly include the glext.h shipping with GLFW, as this program uses
* many modern symbols not provided by the versions in some development
* environments (for example on OS X).
*/
#include <GL/glext.h>
#include <stdio.h>
@@ -42,8 +41,8 @@
#define strcasecmp(x, y) _stricmp(x, y)
#endif
#define API_OPENGL "gl"
#define API_OPENGL_ES "es"
#define API_NAME_OPENGL "gl"
#define API_NAME_OPENGL_ES "es"
#define PROFILE_NAME_CORE "core"
#define PROFILE_NAME_COMPAT "compat"
@@ -56,18 +55,44 @@
static void usage(void)
{
printf("Usage: glfwinfo [-h] [-a API] [-m MAJOR] [-n MINOR] [-d] [-l] [-f] [-p PROFILE] [-s STRATEGY] [-b BEHAVIOR]\n");
printf("Usage: glfwinfo [OPTION]...\n");
printf("Options:\n");
printf(" -a the client API to use (" API_OPENGL " or " API_OPENGL_ES ")\n");
printf(" -b the release behavior to use (" BEHAVIOR_NAME_NONE " or " BEHAVIOR_NAME_FLUSH ")\n");
printf(" -d request a debug context\n");
printf(" -f require a forward-compatible context\n");
printf(" -h show this help\n");
printf(" -l list all client API extensions after context creation\n");
printf(" -m the major number of the required client API version\n");
printf(" -n the minor number of the required client API version\n");
printf(" -p the OpenGL profile to use (" PROFILE_NAME_CORE " or " PROFILE_NAME_COMPAT ")\n");
printf(" -s the robustness strategy to use (" STRATEGY_NAME_NONE " or " STRATEGY_NAME_LOSE ")\n");
printf(" -a, --client-api=API the client API to use ("
API_NAME_OPENGL " or "
API_NAME_OPENGL_ES ")\n");
printf(" -b, --behavior=BEHAVIOR the release behavior to use ("
BEHAVIOR_NAME_NONE " or "
BEHAVIOR_NAME_FLUSH ")\n");
printf(" -d, --debug request a debug context\n");
printf(" -f, --forward require a forward-compatible context\n");
printf(" -h, --help show this help\n");
printf(" -l, --list-extensions list all client API extensions\n");
printf(" -m, --major=MAJOR the major number of the required "
"client API version\n");
printf(" -n, --minor=MINOR the minor number of the required "
"client API version\n");
printf(" -p, --profile=PROFILE the OpenGL profile to use ("
PROFILE_NAME_CORE " or "
PROFILE_NAME_COMPAT ")\n");
printf(" -s, --robustness=STRATEGY the robustness strategy to use ("
STRATEGY_NAME_NONE " or "
STRATEGY_NAME_LOSE ")\n");
printf(" -v, --version print version information\n");
printf(" --red-bits=N the number of red bits to request\n");
printf(" --green-bits=N the number of green bits to request\n");
printf(" --blue-bits=N the number of blue bits to request\n");
printf(" --alpha-bits=N the number of alpha bits to request\n");
printf(" --depth-bits=N the number of depth bits to request\n");
printf(" --stencil-bits=N the number of stencil bits to request\n");
printf(" --accum-red-bits=N the number of red bits to request\n");
printf(" --accum-green-bits=N the number of green bits to request\n");
printf(" --accum-blue-bits=N the number of blue bits to request\n");
printf(" --accum-alpha-bits=N the number of alpha bits to request\n");
printf(" --aux-buffers=N the number of aux buffers to request\n");
printf(" --samples=N the number of MSAA samples to request\n");
printf(" --stereo request stereo rendering\n");
printf(" --srgb request an sRGB capable framebuffer\n");
printf(" --singlebuffer request single-buffering\n");
}
static void error_callback(int error, const char* description)
@@ -75,7 +100,7 @@ static void error_callback(int error, const char* description)
fprintf(stderr, "Error: %s\n", description);
}
static const char* get_client_api_name(int api)
static const char* get_api_name(int api)
{
if (api == GLFW_OPENGL_API)
return "OpenGL";
@@ -131,11 +156,12 @@ static void list_extensions(int api, int major, int minor)
GLint count;
const GLubyte* extensions;
printf("%s context supported extensions:\n", get_client_api_name(api));
printf("%s context supported extensions:\n", get_api_name(api));
if (api == GLFW_OPENGL_API && major > 2)
{
PFNGLGETSTRINGIPROC glGetStringi = (PFNGLGETSTRINGIPROC) glfwGetProcAddress("glGetStringi");
PFNGLGETSTRINGIPROC glGetStringi =
(PFNGLGETSTRINGIPROC) glfwGetProcAddress("glGetStringi");
if (!glGetStringi)
{
glfwTerminate();
@@ -167,16 +193,8 @@ static void list_extensions(int api, int major, int minor)
static GLboolean valid_version(void)
{
int major, minor, revision;
glfwGetVersion(&major, &minor, &revision);
printf("GLFW header version: %u.%u.%u\n",
GLFW_VERSION_MAJOR,
GLFW_VERSION_MINOR,
GLFW_VERSION_REVISION);
printf("GLFW library version: %u.%u.%u\n", major, minor, revision);
if (major != GLFW_VERSION_MAJOR)
{
printf("*** ERROR: GLFW major version mismatch! ***\n");
@@ -186,88 +204,64 @@ static GLboolean valid_version(void)
if (minor != GLFW_VERSION_MINOR || revision != GLFW_VERSION_REVISION)
printf("*** WARNING: GLFW version mismatch! ***\n");
printf("GLFW library version string: \"%s\"\n", glfwGetVersionString());
return GL_TRUE;
}
static void print_version(void)
{
int major, minor, revision;
glfwGetVersion(&major, &minor, &revision);
printf("GLFW header version: %u.%u.%u\n",
GLFW_VERSION_MAJOR,
GLFW_VERSION_MINOR,
GLFW_VERSION_REVISION);
printf("GLFW library version: %u.%u.%u\n", major, minor, revision);
printf("GLFW library version string: \"%s\"\n", glfwGetVersionString());
}
int main(int argc, char** argv)
{
int ch, api = 0, profile = 0, strategy = 0, behavior = 0, major = 1, minor = 0, revision;
GLboolean debug = GL_FALSE, forward = GL_FALSE, list = GL_FALSE;
GLint flags, mask;
int ch, api, major, minor, revision, profile;
GLint redbits, greenbits, bluebits, alphabits, depthbits, stencilbits;
GLboolean list = GL_FALSE;
GLFWwindow* window;
while ((ch = getopt(argc, argv, "a:b:dfhlm:n:p:s:")) != -1)
enum { API, BEHAVIOR, DEBUG, FORWARD, HELP, EXTENSIONS,
MAJOR, MINOR, PROFILE, ROBUSTNESS, VERSION,
REDBITS, GREENBITS, BLUEBITS, ALPHABITS, DEPTHBITS, STENCILBITS,
ACCUMREDBITS, ACCUMGREENBITS, ACCUMBLUEBITS, ACCUMALPHABITS,
AUXBUFFERS, SAMPLES, STEREO, SRGB, SINGLEBUFFER };
const struct option options[] =
{
switch (ch)
{
case 'a':
if (strcasecmp(optarg, API_OPENGL) == 0)
api = GLFW_OPENGL_API;
else if (strcasecmp(optarg, API_OPENGL_ES) == 0)
api = GLFW_OPENGL_ES_API;
else
{
usage();
exit(EXIT_FAILURE);
}
break;
case 'b':
if (strcasecmp(optarg, BEHAVIOR_NAME_NONE) == 0)
behavior = GLFW_RELEASE_BEHAVIOR_NONE;
else if (strcasecmp(optarg, BEHAVIOR_NAME_FLUSH) == 0)
behavior = GLFW_RELEASE_BEHAVIOR_FLUSH;
else
{
usage();
exit(EXIT_FAILURE);
}
break;
case 'd':
debug = GL_TRUE;
break;
case 'f':
forward = GL_TRUE;
break;
case 'h':
usage();
exit(EXIT_SUCCESS);
case 'l':
list = GL_TRUE;
break;
case 'm':
major = atoi(optarg);
break;
case 'n':
minor = atoi(optarg);
break;
case 'p':
if (strcasecmp(optarg, PROFILE_NAME_CORE) == 0)
profile = GLFW_OPENGL_CORE_PROFILE;
else if (strcasecmp(optarg, PROFILE_NAME_COMPAT) == 0)
profile = GLFW_OPENGL_COMPAT_PROFILE;
else
{
usage();
exit(EXIT_FAILURE);
}
break;
case 's':
if (strcasecmp(optarg, STRATEGY_NAME_NONE) == 0)
strategy = GLFW_NO_RESET_NOTIFICATION;
else if (strcasecmp(optarg, STRATEGY_NAME_LOSE) == 0)
strategy = GLFW_LOSE_CONTEXT_ON_RESET;
else
{
usage();
exit(EXIT_FAILURE);
}
break;
default:
usage();
exit(EXIT_FAILURE);
}
}
{ "behavior", 1, NULL, BEHAVIOR },
{ "client-api", 1, NULL, API },
{ "debug", 0, NULL, DEBUG },
{ "forward", 0, NULL, FORWARD },
{ "help", 0, NULL, HELP },
{ "list-extensions", 0, NULL, EXTENSIONS },
{ "major", 1, NULL, MAJOR },
{ "minor", 1, NULL, MINOR },
{ "profile", 1, NULL, PROFILE },
{ "robustness", 1, NULL, ROBUSTNESS },
{ "version", 0, NULL, VERSION },
{ "red-bits", 1, NULL, REDBITS },
{ "green-bits", 1, NULL, GREENBITS },
{ "blue-bits", 1, NULL, BLUEBITS },
{ "alpha-bits", 1, NULL, ALPHABITS },
{ "depth-bits", 1, NULL, DEPTHBITS },
{ "stencil-bits", 1, NULL, STENCILBITS },
{ "accum-red-bits", 1, NULL, ACCUMREDBITS },
{ "accum-green-bits", 1, NULL, ACCUMGREENBITS },
{ "accum-blue-bits", 1, NULL, ACCUMBLUEBITS },
{ "accum-alpha-bits", 1, NULL, ACCUMALPHABITS },
{ "aux-buffers", 1, NULL, AUXBUFFERS },
{ "samples", 1, NULL, SAMPLES },
{ "stereo", 0, NULL, STEREO },
{ "srgb", 0, NULL, SRGB },
{ "singlebuffer", 0, NULL, SINGLEBUFFER },
{ NULL, 0, NULL, 0 }
};
// Initialize GLFW and create window
@@ -279,43 +273,192 @@ int main(int argc, char** argv)
if (!glfwInit())
exit(EXIT_FAILURE);
if (major != 1 || minor != 0)
while ((ch = getopt_long(argc, argv, "a:b:dfhlm:n:p:s:v", options, NULL)) != -1)
{
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, major);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, minor);
switch (ch)
{
case 'a':
case API:
if (strcasecmp(optarg, API_NAME_OPENGL) == 0)
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
else if (strcasecmp(optarg, API_NAME_OPENGL_ES) == 0)
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
else
{
usage();
exit(EXIT_FAILURE);
}
break;
case 'b':
case BEHAVIOR:
if (strcasecmp(optarg, BEHAVIOR_NAME_NONE) == 0)
{
glfwWindowHint(GLFW_CONTEXT_RELEASE_BEHAVIOR,
GLFW_RELEASE_BEHAVIOR_NONE);
}
else if (strcasecmp(optarg, BEHAVIOR_NAME_FLUSH) == 0)
{
glfwWindowHint(GLFW_CONTEXT_RELEASE_BEHAVIOR,
GLFW_RELEASE_BEHAVIOR_FLUSH);
}
else
{
usage();
exit(EXIT_FAILURE);
}
break;
case 'd':
case DEBUG:
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
break;
case 'f':
case FORWARD:
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
break;
case 'h':
case HELP:
usage();
exit(EXIT_SUCCESS);
case 'l':
case EXTENSIONS:
list = GL_TRUE;
break;
case 'm':
case MAJOR:
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, atoi(optarg));
break;
case 'n':
case MINOR:
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, atoi(optarg));
break;
case 'p':
case PROFILE:
if (strcasecmp(optarg, PROFILE_NAME_CORE) == 0)
{
glfwWindowHint(GLFW_OPENGL_PROFILE,
GLFW_OPENGL_CORE_PROFILE);
}
else if (strcasecmp(optarg, PROFILE_NAME_COMPAT) == 0)
{
glfwWindowHint(GLFW_OPENGL_PROFILE,
GLFW_OPENGL_COMPAT_PROFILE);
}
else
{
usage();
exit(EXIT_FAILURE);
}
break;
case 's':
case ROBUSTNESS:
if (strcasecmp(optarg, STRATEGY_NAME_NONE) == 0)
{
glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS,
GLFW_NO_RESET_NOTIFICATION);
}
else if (strcasecmp(optarg, STRATEGY_NAME_LOSE) == 0)
{
glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS,
GLFW_LOSE_CONTEXT_ON_RESET);
}
else
{
usage();
exit(EXIT_FAILURE);
}
break;
case 'v':
case VERSION:
print_version();
exit(EXIT_SUCCESS);
case REDBITS:
if (strcmp(optarg, "-") == 0)
glfwWindowHint(GLFW_RED_BITS, GLFW_DONT_CARE);
else
glfwWindowHint(GLFW_RED_BITS, atoi(optarg));
break;
case GREENBITS:
if (strcmp(optarg, "-") == 0)
glfwWindowHint(GLFW_GREEN_BITS, GLFW_DONT_CARE);
else
glfwWindowHint(GLFW_GREEN_BITS, atoi(optarg));
break;
case BLUEBITS:
if (strcmp(optarg, "-") == 0)
glfwWindowHint(GLFW_BLUE_BITS, GLFW_DONT_CARE);
else
glfwWindowHint(GLFW_BLUE_BITS, atoi(optarg));
break;
case ALPHABITS:
if (strcmp(optarg, "-") == 0)
glfwWindowHint(GLFW_ALPHA_BITS, GLFW_DONT_CARE);
else
glfwWindowHint(GLFW_ALPHA_BITS, atoi(optarg));
break;
case DEPTHBITS:
if (strcmp(optarg, "-") == 0)
glfwWindowHint(GLFW_DEPTH_BITS, GLFW_DONT_CARE);
else
glfwWindowHint(GLFW_DEPTH_BITS, atoi(optarg));
break;
case STENCILBITS:
if (strcmp(optarg, "-") == 0)
glfwWindowHint(GLFW_STENCIL_BITS, GLFW_DONT_CARE);
else
glfwWindowHint(GLFW_STENCIL_BITS, atoi(optarg));
break;
case ACCUMREDBITS:
if (strcmp(optarg, "-") == 0)
glfwWindowHint(GLFW_ACCUM_RED_BITS, GLFW_DONT_CARE);
else
glfwWindowHint(GLFW_ACCUM_RED_BITS, atoi(optarg));
break;
case ACCUMGREENBITS:
if (strcmp(optarg, "-") == 0)
glfwWindowHint(GLFW_ACCUM_GREEN_BITS, GLFW_DONT_CARE);
else
glfwWindowHint(GLFW_ACCUM_GREEN_BITS, atoi(optarg));
break;
case ACCUMBLUEBITS:
if (strcmp(optarg, "-") == 0)
glfwWindowHint(GLFW_ACCUM_BLUE_BITS, GLFW_DONT_CARE);
else
glfwWindowHint(GLFW_ACCUM_BLUE_BITS, atoi(optarg));
break;
case ACCUMALPHABITS:
if (strcmp(optarg, "-") == 0)
glfwWindowHint(GLFW_ACCUM_ALPHA_BITS, GLFW_DONT_CARE);
else
glfwWindowHint(GLFW_ACCUM_ALPHA_BITS, atoi(optarg));
break;
case AUXBUFFERS:
if (strcmp(optarg, "-") == 0)
glfwWindowHint(GLFW_AUX_BUFFERS, GLFW_DONT_CARE);
else
glfwWindowHint(GLFW_AUX_BUFFERS, atoi(optarg));
break;
case SAMPLES:
if (strcmp(optarg, "-") == 0)
glfwWindowHint(GLFW_SAMPLES, GLFW_DONT_CARE);
else
glfwWindowHint(GLFW_SAMPLES, atoi(optarg));
break;
case STEREO:
glfwWindowHint(GLFW_STEREO, GL_TRUE);
break;
case SRGB:
glfwWindowHint(GLFW_SRGB_CAPABLE, GL_TRUE);
break;
case SINGLEBUFFER:
glfwWindowHint(GLFW_DOUBLEBUFFER, GL_FALSE);
break;
default:
usage();
exit(EXIT_FAILURE);
}
}
if (api != 0)
glfwWindowHint(GLFW_CLIENT_API, api);
if (debug)
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
if (forward)
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
if (profile != 0)
glfwWindowHint(GLFW_OPENGL_PROFILE, profile);
if (strategy)
glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS, strategy);
if (behavior)
glfwWindowHint(GLFW_CONTEXT_RELEASE_BEHAVIOR, behavior);
glfwWindowHint(GLFW_RED_BITS, GLFW_DONT_CARE);
glfwWindowHint(GLFW_GREEN_BITS, GLFW_DONT_CARE);
glfwWindowHint(GLFW_BLUE_BITS, GLFW_DONT_CARE);
glfwWindowHint(GLFW_ALPHA_BITS, GLFW_DONT_CARE);
glfwWindowHint(GLFW_DEPTH_BITS, GLFW_DONT_CARE);
glfwWindowHint(GLFW_STENCIL_BITS, GLFW_DONT_CARE);
glfwWindowHint(GLFW_ACCUM_RED_BITS, GLFW_DONT_CARE);
glfwWindowHint(GLFW_ACCUM_GREEN_BITS, GLFW_DONT_CARE);
glfwWindowHint(GLFW_ACCUM_BLUE_BITS, GLFW_DONT_CARE);
glfwWindowHint(GLFW_ACCUM_ALPHA_BITS, GLFW_DONT_CARE);
glfwWindowHint(GLFW_AUX_BUFFERS, GLFW_DONT_CARE);
glfwWindowHint(GLFW_SAMPLES, GLFW_DONT_CARE);
glfwWindowHint(GLFW_SRGB_CAPABLE, GLFW_DONT_CARE);
print_version();
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
@@ -334,13 +477,14 @@ int main(int argc, char** argv)
major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR);
minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR);
revision = glfwGetWindowAttrib(window, GLFW_CONTEXT_REVISION);
profile = glfwGetWindowAttrib(window, GLFW_OPENGL_PROFILE);
printf("%s context version string: \"%s\"\n",
get_client_api_name(api),
get_api_name(api),
glGetString(GL_VERSION));
printf("%s context version parsed by GLFW: %u.%u.%u\n",
get_client_api_name(api),
get_api_name(api),
major, minor, revision);
// Report client API context properties
@@ -349,8 +493,10 @@ int main(int argc, char** argv)
{
if (major >= 3)
{
GLint flags;
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
printf("%s context flags (0x%08x):", get_client_api_name(api), flags);
printf("%s context flags (0x%08x):", get_api_name(api), flags);
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
printf(" forward-compatible");
@@ -360,65 +506,141 @@ int main(int argc, char** argv)
printf(" robustness");
putchar('\n');
printf("%s context flags parsed by GLFW:", get_client_api_name(api));
printf("%s context flags parsed by GLFW:", get_api_name(api));
if (glfwGetWindowAttrib(window, GLFW_OPENGL_FORWARD_COMPAT))
printf(" forward-compatible");
if (glfwGetWindowAttrib(window, GLFW_OPENGL_DEBUG_CONTEXT))
printf(" debug");
if (glfwGetWindowAttrib(window, GLFW_CONTEXT_ROBUSTNESS) != GLFW_NO_ROBUSTNESS)
if (glfwGetWindowAttrib(window, GLFW_CONTEXT_ROBUSTNESS) == GLFW_LOSE_CONTEXT_ON_RESET)
printf(" robustness");
putchar('\n');
}
if (major > 3 || (major == 3 && minor >= 2))
if (major >= 4 || (major == 3 && minor >= 2))
{
int profile = glfwGetWindowAttrib(window, GLFW_OPENGL_PROFILE);
GLint mask;
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
printf("%s profile mask (0x%08x): %s\n",
get_client_api_name(api),
get_api_name(api),
mask,
get_profile_name_gl(mask));
printf("%s profile mask parsed by GLFW: %s\n",
get_client_api_name(api),
get_api_name(api),
get_profile_name_glfw(profile));
}
if (glfwExtensionSupported("GL_ARB_robustness"))
{
int robustness;
const int robustness = glfwGetWindowAttrib(window, GLFW_CONTEXT_ROBUSTNESS);
GLint strategy;
glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
printf("%s robustness strategy (0x%08x): %s\n",
get_client_api_name(api),
get_api_name(api),
strategy,
get_strategy_name_gl(strategy));
robustness = glfwGetWindowAttrib(window, GLFW_CONTEXT_ROBUSTNESS);
printf("%s robustness strategy parsed by GLFW: %s\n",
get_client_api_name(api),
get_api_name(api),
get_strategy_name_glfw(robustness));
}
}
printf("%s context renderer string: \"%s\"\n",
get_client_api_name(api),
get_api_name(api),
glGetString(GL_RENDERER));
printf("%s context vendor string: \"%s\"\n",
get_client_api_name(api),
get_api_name(api),
glGetString(GL_VENDOR));
if (major > 1)
if (major >= 2)
{
printf("%s context shading language version: \"%s\"\n",
get_client_api_name(api),
get_api_name(api),
glGetString(GL_SHADING_LANGUAGE_VERSION));
}
printf("Framebuffer:\n");
if (api == GLFW_OPENGL_API && profile == GLFW_OPENGL_CORE_PROFILE)
{
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC
glGetFramebufferAttachmentParameteriv =
(PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)
glfwGetProcAddress("glGetFramebufferAttachmentParameteriv");
if (!glGetFramebufferAttachmentParameteriv)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_BACK_LEFT,
GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE,
&redbits);
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_BACK_LEFT,
GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE,
&greenbits);
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_BACK_LEFT,
GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE,
&bluebits);
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_BACK_LEFT,
GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
&alphabits);
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_DEPTH,
GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE,
&depthbits);
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_STENCIL,
GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
&stencilbits);
}
else
{
glGetIntegerv(GL_RED_BITS, &redbits);
glGetIntegerv(GL_GREEN_BITS, &greenbits);
glGetIntegerv(GL_BLUE_BITS, &bluebits);
glGetIntegerv(GL_ALPHA_BITS, &alphabits);
glGetIntegerv(GL_DEPTH_BITS, &depthbits);
glGetIntegerv(GL_STENCIL_BITS, &stencilbits);
}
printf(" red: %u green: %u blue: %u alpha: %u depth: %u stencil: %u\n",
redbits, greenbits, bluebits, alphabits, depthbits, stencilbits);
if (api == GLFW_OPENGL_ES_API ||
glfwExtensionSupported("GL_ARB_multisample") ||
major > 1 || minor >= 3)
{
GLint samples, samplebuffers;
glGetIntegerv(GL_SAMPLES, &samples);
glGetIntegerv(GL_SAMPLE_BUFFERS, &samplebuffers);
printf(" samples: %u sample buffers: %u\n", samples, samplebuffers);
}
if (api == GLFW_OPENGL_API && profile != GLFW_OPENGL_CORE_PROFILE)
{
GLint accumredbits, accumgreenbits, accumbluebits, accumalphabits;
GLint auxbuffers;
glGetIntegerv(GL_ACCUM_RED_BITS, &accumredbits);
glGetIntegerv(GL_ACCUM_GREEN_BITS, &accumgreenbits);
glGetIntegerv(GL_ACCUM_BLUE_BITS, &accumbluebits);
glGetIntegerv(GL_ACCUM_ALPHA_BITS, &accumalphabits);
glGetIntegerv(GL_AUX_BUFFERS, &auxbuffers);
printf(" accum red: %u accum green: %u accum blue: %u accum alpha: %u aux buffers: %u\n",
accumredbits, accumgreenbits, accumbluebits, accumalphabits, auxbuffers);
}
// Report client API extensions
if (list)
list_extensions(api, major, minor);
+3
View File
@@ -99,6 +99,9 @@ static void window_iconify_callback(GLFWwindow* window, int iconified)
static void window_refresh_callback(GLFWwindow* window)
{
int width, height;
printf("%0.2f Window refresh\n", glfwGetTime());
glfwGetFramebufferSize(window, &width, &height);
glfwMakeContextCurrent(window);
+3 -3
View File
@@ -83,7 +83,7 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
static void list_modes(GLFWmonitor* monitor)
{
int count, x, y, widthMM, heightMM, dpi, i;
int count, x, y, widthMM, heightMM, i;
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
const GLFWvidmode* modes = glfwGetVideoModes(monitor, &count);
@@ -96,8 +96,8 @@ static void list_modes(GLFWmonitor* monitor)
printf("Current mode: %s\n", format_mode(mode));
printf("Virtual position: %i %i\n", x, y);
dpi = (int) ((float) mode->width * 25.4f / (float) widthMM);
printf("Physical size: %i x %i mm (%i dpi)\n", widthMM, heightMM, dpi);
printf("Physical size: %i x %i mm (%0.2f dpi)\n",
widthMM, heightMM, mode->width * 25.4f / widthMM);
printf("Modes:\n");
+7 -7
View File
@@ -1,5 +1,5 @@
//========================================================================
// Full screen anti-aliasing test
// Multisample anti-aliasing test
// Copyright (c) Camilla Berglund <elmindreda@elmindreda.org>
//
// This software is provided 'as-is', without any express or implied
@@ -25,7 +25,7 @@
//
// This test renders two high contrast, slowly rotating quads, one aliased
// and one (hopefully) anti-aliased, thus allowing for visual verification
// of whether FSAA is indeed enabled
// of whether MSAA is indeed enabled
//
//========================================================================
@@ -62,7 +62,7 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
static void usage(void)
{
printf("Usage: fsaa [-h] [-s SAMPLES]\n");
printf("Usage: msaa [-h] [-s SAMPLES]\n");
}
int main(int argc, char** argv)
@@ -92,9 +92,9 @@ int main(int argc, char** argv)
exit(EXIT_FAILURE);
if (samples)
printf("Requesting FSAA with %i samples\n", samples);
printf("Requesting MSAA with %i samples\n", samples);
else
printf("Requesting that FSAA not be available\n");
printf("Requesting that MSAA not be available\n");
glfwWindowHint(GLFW_SAMPLES, samples);
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
@@ -124,9 +124,9 @@ int main(int argc, char** argv)
glGetIntegerv(GL_SAMPLES_ARB, &samples);
if (samples)
printf("Context reports FSAA is available with %i samples\n", samples);
printf("Context reports MSAA is available with %i samples\n", samples);
else
printf("Context reports FSAA is unavailable\n");
printf("Context reports MSAA is unavailable\n");
glMatrixMode(GL_PROJECTION);
glOrtho(0.f, 1.f, 0.f, 0.5f, 0.f, 1.f);
-151
View File
@@ -1,151 +0,0 @@
//========================================================================
// Cursor mode test
// Copyright (c) Camilla Berglund <elmindreda@elmindreda.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//
// This test allows you to switch between the various cursor modes
//
//========================================================================
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
static GLboolean reopen = GL_FALSE;
static double cursor_x;
static double cursor_y;
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void cursor_position_callback(GLFWwindow* window, double x, double y)
{
printf("%0.3f: Cursor position: %f %f (%f %f)\n",
glfwGetTime(),
x, y, x - cursor_x, y - cursor_y);
cursor_x = x;
cursor_y = y;
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action != GLFW_PRESS)
return;
switch (key)
{
case GLFW_KEY_D:
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
printf("(( cursor is disabled ))\n");
break;
case GLFW_KEY_H:
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
printf("(( cursor is hidden ))\n");
break;
case GLFW_KEY_N:
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
printf("(( cursor is normal ))\n");
break;
case GLFW_KEY_R:
reopen = GL_TRUE;
break;
}
}
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
static GLFWwindow* open_window(void)
{
GLFWwindow* window = glfwCreateWindow(640, 480, "Peter Detector", NULL, NULL);
if (!window)
return NULL;
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwGetCursorPos(window, &cursor_x, &cursor_y);
printf("Cursor position: %f %f\n", cursor_x, cursor_y);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetCursorPosCallback(window, cursor_position_callback);
glfwSetKeyCallback(window, key_callback);
return window;
}
int main(void)
{
GLFWwindow* window;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
window = open_window();
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glClearColor(0.f, 0.f, 0.f, 0.f);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
if (reopen)
{
glfwDestroyWindow(window);
window = open_window();
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
reopen = GL_FALSE;
}
// Workaround for an issue with msvcrt and mintty
fflush(stdout);
}
glfwTerminate();
exit(EXIT_SUCCESS);
}
+14 -1
View File
@@ -122,6 +122,7 @@ int main(int argc, char** argv)
for (;;)
{
int width, height;
GLFWmonitor* monitor = NULL;
if (count % 2 == 0)
@@ -131,7 +132,19 @@ int main(int argc, char** argv)
monitor = monitors[rand() % monitorCount];
}
window = open_window(640, 480, monitor);
if (monitor)
{
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
width = mode->width;
height = mode->height;
}
else
{
width = 640;
height = 480;
}
window = open_window(width, height, monitor);
if (!window)
{
glfwTerminate();
+88 -6
View File
@@ -34,15 +34,28 @@
#include <stdlib.h>
#include <math.h>
#include "getopt.h"
static GLboolean swap_tear;
static int swap_interval;
static double frame_rate;
static void usage(void)
{
printf("Usage: iconify [-h] [-f]\n");
printf("Options:\n");
printf(" -f create full screen window\n");
printf(" -h show this help\n");
}
static void update_window_title(GLFWwindow* window)
{
char title[256];
sprintf(title, "Tearing detector (interval %i, %0.1f Hz)",
swap_interval, frame_rate);
sprintf(title, "Tearing detector (interval %i%s, %0.1f Hz)",
swap_interval,
(swap_tear && swap_interval < 0) ? " (swap tear)" : "",
frame_rate);
glfwSetWindowTitle(window, title);
}
@@ -66,23 +79,90 @@ static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
set_swap_interval(window, 1 - swap_interval);
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;
}
}
int main(void)
int main(int argc, char** argv)
{
int ch, width, height;
float position;
unsigned long frame_count = 0;
double last_time, current_time;
GLboolean fullscreen = GL_FALSE;
GLFWmonitor* monitor = NULL;
GLFWwindow* window;
while ((ch = getopt(argc, argv, "fh")) != -1)
{
switch (ch)
{
case 'h':
usage();
exit(EXIT_SUCCESS);
case 'f':
fullscreen = GL_TRUE;
break;
}
}
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
window = glfwCreateWindow(640, 480, "", NULL, NULL);
if (fullscreen)
{
const GLFWvidmode* mode;
monitor = glfwGetPrimaryMonitor();
mode = glfwGetVideoMode(monitor);
glfwWindowHint(GLFW_RED_BITS, mode->redBits);
glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
width = mode->width;
height = mode->height;
}
else
{
width = 640;
height = 480;
}
window = glfwCreateWindow(width, height, "", monitor, NULL);
if (!window)
{
glfwTerminate();
@@ -94,6 +174,8 @@ int main(void)
last_time = glfwGetTime();
frame_rate = 0.0;
swap_tear = (glfwExtensionSupported("WGL_EXT_swap_control_tear") ||
glfwExtensionSupported("GLX_EXT_swap_control_tear"));
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetKeyCallback(window, key_callback);
+34 -14
View File
@@ -32,12 +32,23 @@
#include <stdio.h>
#include <stdlib.h>
static const char* titles[4] =
static const char* titles[] =
{
"Foo",
"Bar",
"Baz",
"Quux"
"Red",
"Green",
"Blue",
"Yellow"
};
static const struct
{
float r, g, b;
} colors[] =
{
{ 0.95f, 0.32f, 0.11f },
{ 0.50f, 0.80f, 0.16f },
{ 0.f, 0.68f, 0.94f },
{ 0.98f, 0.74f, 0.04f }
};
static void error_callback(int error, const char* description)
@@ -47,15 +58,26 @@ static void error_callback(int error, const char* description)
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
if (action != GLFW_PRESS)
return;
switch (key)
{
int xpos, ypos;
glfwGetWindowPos(window, &xpos, &ypos);
glfwSetWindowPos(window, xpos, ypos);
case GLFW_KEY_SPACE:
{
int xpos, ypos;
glfwGetWindowPos(window, &xpos, &ypos);
glfwSetWindowPos(window, xpos, ypos);
break;
}
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GL_TRUE);
break;
}
}
int main(void)
int main(int argc, char** argv)
{
int i;
GLboolean running = GL_TRUE;
@@ -66,6 +88,7 @@ int main(void)
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_DECORATED, GL_FALSE);
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
for (i = 0; i < 4; i++)
@@ -82,10 +105,7 @@ int main(void)
glfwSetKeyCallback(windows[i], key_callback);
glfwMakeContextCurrent(windows[i]);
glClearColor((GLclampf) (i & 1),
(GLclampf) (i >> 1),
i ? 0.f : 1.f,
0.f);
glClearColor(colors[i].r, colors[i].g, colors[i].b, 1.f);
glfwGetWindowFrameSize(windows[i], &left, &top, &right, &bottom);
glfwSetWindowPos(windows[i],