mirror of
https://github.com/glfw/glfw.git
synced 2025-10-05 06:06:36 +00:00
Merge branch 'master' of https://github.com/glfw/glfw
This commit is contained in:
commit
a2f66a3966
18
CMake/modules/FindOSMesa.cmake
Normal file
18
CMake/modules/FindOSMesa.cmake
Normal file
@ -0,0 +1,18 @@
|
||||
# Try to find OSMesa on a Unix system
|
||||
#
|
||||
# This will define:
|
||||
#
|
||||
# OSMESA_LIBRARIES - Link these to use OSMesa
|
||||
# OSMESA_INCLUDE_DIR - Include directory for OSMesa
|
||||
#
|
||||
# Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||
|
||||
if (NOT WIN32)
|
||||
|
||||
find_package (PkgConfig)
|
||||
pkg_check_modules (PKG_OSMESA QUIET osmesa)
|
||||
|
||||
set (OSMESA_INCLUDE_DIR ${PKG_OSMESA_INCLUDE_DIRS})
|
||||
set (OSMESA_LIBRARIES ${PKG_OSMESA_LIBRARIES})
|
||||
|
||||
endif ()
|
@ -20,6 +20,13 @@ if (WIN32)
|
||||
"$ENV{VULKAN_SDK}/Bin32"
|
||||
"$ENV{VK_SDK_PATH}/Bin32")
|
||||
endif()
|
||||
elseif (APPLE)
|
||||
find_library(VULKAN_LIBRARY MoltenVK)
|
||||
if (VULKAN_LIBRARY)
|
||||
set(VULKAN_STATIC_LIBRARY ${VULKAN_LIBRARY})
|
||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||
"${VULKAN_LIBRARY}/Headers")
|
||||
endif()
|
||||
else()
|
||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||
"$ENV{VULKAN_SDK}/include")
|
||||
|
@ -28,6 +28,10 @@ option(GLFW_INSTALL "Generate installation target" ON)
|
||||
option(GLFW_VULKAN_STATIC "Use the Vulkan loader statically linked into application" OFF)
|
||||
option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF)
|
||||
|
||||
if (UNIX)
|
||||
option(GLFW_USE_OSMESA "Use OSMesa for offscreen context creation" OFF)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF)
|
||||
endif()
|
||||
@ -129,26 +133,36 @@ if (MINGW)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
# Dependencies required by the MoltenVK static library
|
||||
set(GLFW_VULKAN_DEPS
|
||||
"-lc++"
|
||||
"-framework Cocoa"
|
||||
"-framework Metal"
|
||||
"-framework QuartzCore")
|
||||
endif()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Detect and select backend APIs
|
||||
#--------------------------------------------------------------------
|
||||
if (WIN32)
|
||||
if (GLFW_USE_WAYLAND)
|
||||
set(_GLFW_WAYLAND 1)
|
||||
message(STATUS "Using Wayland for window creation")
|
||||
elseif (GLFW_USE_MIR)
|
||||
set(_GLFW_MIR 1)
|
||||
message(STATUS "Using Mir for window creation")
|
||||
elseif (GLFW_USE_OSMESA)
|
||||
set(_GLFW_OSMESA 1)
|
||||
message(STATUS "Using OSMesa for headless context creation")
|
||||
elseif (WIN32)
|
||||
set(_GLFW_WIN32 1)
|
||||
message(STATUS "Using Win32 for window creation")
|
||||
elseif (APPLE)
|
||||
set(_GLFW_COCOA 1)
|
||||
message(STATUS "Using Cocoa for window creation")
|
||||
elseif (UNIX)
|
||||
if (GLFW_USE_WAYLAND)
|
||||
set(_GLFW_WAYLAND 1)
|
||||
message(STATUS "Using Wayland for window creation")
|
||||
elseif (GLFW_USE_MIR)
|
||||
set(_GLFW_MIR 1)
|
||||
message(STATUS "Using Mir for window creation")
|
||||
else()
|
||||
set(_GLFW_X11 1)
|
||||
message(STATUS "Using X11 for window creation")
|
||||
endif()
|
||||
set(_GLFW_X11 1)
|
||||
message(STATUS "Using X11 for window creation")
|
||||
else()
|
||||
message(FATAL_ERROR "No supported platform was detected")
|
||||
endif()
|
||||
@ -158,7 +172,10 @@ endif()
|
||||
#--------------------------------------------------------------------
|
||||
if (GLFW_VULKAN_STATIC)
|
||||
if (VULKAN_FOUND AND VULKAN_STATIC_LIBRARY)
|
||||
list(APPEND glfw_LIBRARIES ${VULKAN_STATIC_LIBRARY})
|
||||
list(APPEND glfw_LIBRARIES ${VULKAN_STATIC_LIBRARY} ${GLFW_VULKAN_DEPS})
|
||||
if (BUILD_SHARED_LIBS)
|
||||
message(WARNING "Linking Vulkan loader static library into GLFW")
|
||||
endif()
|
||||
else()
|
||||
if (BUILD_SHARED_LIBS OR GLFW_BUILD_EXAMPLES OR GLFW_BUILD_TESTS)
|
||||
message(FATAL_ERROR "Vulkan loader static library not found")
|
||||
@ -306,6 +323,14 @@ if (_GLFW_MIR)
|
||||
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
|
||||
endif()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Use OSMesa for offscreen context creation
|
||||
#--------------------------------------------------------------------
|
||||
if (_GLFW_OSMESA)
|
||||
find_package(OSMesa REQUIRED)
|
||||
list(APPEND glfw_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}")
|
||||
endif()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Use Cocoa for window creation and NSOpenGL for context creation
|
||||
#--------------------------------------------------------------------
|
||||
@ -323,19 +348,11 @@ if (_GLFW_COCOA)
|
||||
set(_GLFW_USE_RETINA 1)
|
||||
endif()
|
||||
|
||||
# Set up library and include paths
|
||||
find_library(COCOA_FRAMEWORK Cocoa)
|
||||
find_library(IOKIT_FRAMEWORK IOKit)
|
||||
find_library(CORE_FOUNDATION_FRAMEWORK CoreFoundation)
|
||||
find_library(CORE_VIDEO_FRAMEWORK CoreVideo)
|
||||
mark_as_advanced(COCOA_FRAMEWORK
|
||||
IOKIT_FRAMEWORK
|
||||
CORE_FOUNDATION_FRAMEWORK
|
||||
CORE_VIDEO_FRAMEWORK)
|
||||
list(APPEND glfw_LIBRARIES "${COCOA_FRAMEWORK}"
|
||||
"${IOKIT_FRAMEWORK}"
|
||||
"${CORE_FOUNDATION_FRAMEWORK}"
|
||||
"${CORE_VIDEO_FRAMEWORK}")
|
||||
list(APPEND glfw_LIBRARIES
|
||||
"-framework Cocoa"
|
||||
"-framework IOKit"
|
||||
"-framework CoreFoundation"
|
||||
"-framework CoreVideo")
|
||||
|
||||
set(glfw_PKG_DEPS "")
|
||||
set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation -framework CoreVideo")
|
||||
|
12
README.md
12
README.md
@ -36,7 +36,7 @@ does not need the headers for any context creation API (WGL, GLX, EGL, NSGL) or
|
||||
rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them.
|
||||
|
||||
GLFW supports compilation on Windows with Visual C++ 2010 and later, MinGW and
|
||||
MinGW-w64, on OS X with Clang and on Linux and other Unix-like systems with GCC
|
||||
MinGW-w64, on macOS with Clang and on Linux and other Unix-like systems with GCC
|
||||
and Clang. It will likely compile in other environments as well, but this is
|
||||
not regularly tested.
|
||||
|
||||
@ -81,6 +81,7 @@ located in the `deps/` directory.
|
||||
- [linmath.h](https://github.com/datenwolf/linmath.h) for linear algebra in
|
||||
examples
|
||||
- [Nuklear](https://github.com/vurtun/nuklear) for test and example UI
|
||||
- [stb\_image\_write](https://github.com/nothings/stb) for writing images to disk
|
||||
- [Vulkan headers](https://www.khronos.org/registry/vulkan/) for Vulkan tests
|
||||
|
||||
The Vulkan example additionally requires the Vulkan SDK to be installed, or it
|
||||
@ -104,10 +105,17 @@ information on what to include when reporting a bug.
|
||||
scancodes for keys (#830)
|
||||
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
|
||||
receiving window maximization events (#778)
|
||||
- Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#281,#850)
|
||||
- Added definition of `GLAPIENTRY` to public header
|
||||
- Bugfix: Calling `glfwMaximizeWindow` on a full screen window was not ignored
|
||||
- Bugfix: `GLFW_INCLUDE_VULKAN` could not be combined with the corresponding
|
||||
OpenGL and OpenGL ES header macros
|
||||
- Bugfix: `glfwGetInstanceProcAddress` returned `NULL` for
|
||||
`vkGetInstanceProcAddr` when `_GLFW_VULKAN_STATIC` was enabled
|
||||
- [Win32] Bugfix: Undecorated windows could not be iconified by the user (#861)
|
||||
- [Cocoa] Added support for Vulkan window surface creation via MoltenVK (#870)
|
||||
- [Cocoa] Bugfix: Disabling window aspect ratio would assert (#852)
|
||||
- [Cocoa] Bugfix: Window creation failed to set first responder (#876,#883)
|
||||
- [EGL] Added support for `EGL_KHR_get_all_proc_addresses` (#871)
|
||||
|
||||
|
||||
@ -149,6 +157,7 @@ skills.
|
||||
- Lambert Clara
|
||||
- Andrew Corrigan
|
||||
- Noel Cower
|
||||
- Jason Daly
|
||||
- Jarrod Davis
|
||||
- Olivier Delannoy
|
||||
- Paul R. Deppe
|
||||
@ -160,6 +169,7 @@ skills.
|
||||
- Siavash Eliasi
|
||||
- Michael Fogleman
|
||||
- Gerald Franz
|
||||
- Mário Freitas
|
||||
- GeO4d
|
||||
- Marcus Geelnard
|
||||
- Eloi Marín Gratacós
|
||||
|
1048
deps/stb_image_write.h
vendored
Normal file
1048
deps/stb_image_write.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4
deps/tinycthread.h
vendored
4
deps/tinycthread.h
vendored
@ -123,7 +123,9 @@ typedef int _tthread_clockid_t;
|
||||
/* Emulate clock_gettime */
|
||||
int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts);
|
||||
#define clock_gettime _tthread_clock_gettime
|
||||
#define CLOCK_REALTIME 0
|
||||
#ifndef CLOCK_REALTIME
|
||||
#define CLOCK_REALTIME 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -202,8 +202,9 @@ ALIASES = "thread_safety=@par Thread safety\n" \
|
||||
"errors=@par Errors\n" \
|
||||
"glfw3=@par\n__GLFW 3:__" \
|
||||
"x11=__X11:__" \
|
||||
"wayland=__Wayland:__" \
|
||||
"win32=__Windows:__" \
|
||||
"osx=__OS X:__"
|
||||
"macos=__macOS:__"
|
||||
|
||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
||||
# A mapping has the form "name=value". For example adding
|
||||
@ -1576,6 +1577,7 @@ PREDEFINED = GLFWAPI= \
|
||||
GLFW_EXPOSE_NATIVE_COCOA \
|
||||
GLFW_EXPOSE_NATIVE_NSGL \
|
||||
GLFW_EXPOSE_NATIVE_EGL \
|
||||
GLFW_EXPOSE_NATIVE_OSMESA \
|
||||
VK_VERSION_1_0
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
||||
|
@ -65,7 +65,7 @@ The following macros control which OpenGL or OpenGL ES API header is included.
|
||||
Only one of these may be defined at a time.
|
||||
|
||||
`GLFW_INCLUDE_GLCOREARB` makes the GLFW header include the modern
|
||||
`GL/glcorearb.h` header (`OpenGL/gl3.h` on OS X) instead of the regular OpenGL
|
||||
`GL/glcorearb.h` header (`OpenGL/gl3.h` on macOS) instead of the regular OpenGL
|
||||
header.
|
||||
|
||||
`GLFW_INCLUDE_ES1` makes the GLFW header include the OpenGL ES 1.x `GLES/gl.h`
|
||||
@ -84,7 +84,7 @@ header instead of the regular OpenGL header.
|
||||
header. This is useful in combination with an extension loading library.
|
||||
|
||||
If none of the above inclusion macros are defined, the standard OpenGL `GL/gl.h`
|
||||
header (`OpenGL/gl.h` on OS X) is included.
|
||||
header (`OpenGL/gl.h` on macOS) is included.
|
||||
|
||||
The following macros control the inclusion of additional API headers. Any
|
||||
number of these may be defined simultaneously, and/or together with one of the
|
||||
@ -119,7 +119,7 @@ a shared library / dynamic library / DLL then it takes care of these links.
|
||||
However, if you are using GLFW as a static library then your executable will
|
||||
need to link against these libraries.
|
||||
|
||||
On Windows and OS X, the list of system libraries is static and can be
|
||||
On Windows and macOS, the list of system libraries is static and can be
|
||||
hard-coded into your build environment. See the section for your development
|
||||
environment below. On Linux and other Unix-like operating systems, the list
|
||||
varies but can be retrieved in various ways as described below.
|
||||
@ -289,7 +289,7 @@ env PKG_CONFIG_PATH=path/to/glfw/src cc `pkg-config --cflags glfw3` -o myprog my
|
||||
@endcode
|
||||
|
||||
The dependencies do not include OpenGL or GLU, as GLFW loads any OpenGL, OpenGL
|
||||
ES or Vulkan libraries it needs at runtime and does not use GLU. On OS X, GLU
|
||||
ES or Vulkan libraries it needs at runtime and does not use GLU. On macOS, GLU
|
||||
is built into the OpenGL framework, so if you need GLU you don't need to do
|
||||
anything extra. If you need GLU and are using Linux or BSD, you should add the
|
||||
`glu` pkg-config package.
|
||||
@ -309,7 +309,7 @@ cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --static --lib
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection build_link_xcode With Xcode on OS X
|
||||
@subsection build_link_xcode With Xcode on macOS
|
||||
|
||||
If you are using the dynamic library version of GLFW, simply add it to the
|
||||
project dependencies.
|
||||
@ -319,10 +319,10 @@ OpenGL, IOKit and CoreVideo frameworks to the project as dependencies. They can
|
||||
all be found in `/System/Library/Frameworks`.
|
||||
|
||||
|
||||
@subsection build_link_osx With command-line on OS X
|
||||
@subsection build_link_osx With command-line on macOS
|
||||
|
||||
It is recommended that you use [pkg-config](@ref build_link_pkgconfig) when
|
||||
building from the command line on OS X. That way you will get any new
|
||||
building from the command line on macOS. That way you will get any new
|
||||
dependencies added automatically. If you still wish to build manually, you need
|
||||
to add the required frameworks and libraries to your command-line yourself using
|
||||
the `-l` and `-framework` switches.
|
||||
@ -342,6 +342,6 @@ against it from the command-line.
|
||||
The OpenGL framework contains both the OpenGL and GLU APIs, so there is nothing
|
||||
special to do when using GLU. Also note that even though your machine may have
|
||||
`libGL`-style OpenGL libraries, they are for use with the X Window System and
|
||||
will _not_ work with the OS X native version of GLFW.
|
||||
will _not_ work with the macOS native version of GLFW.
|
||||
|
||||
*/
|
||||
|
@ -160,7 +160,7 @@ extensions to provide support for sRGB framebuffers. Where both of these
|
||||
extension are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect.
|
||||
|
||||
|
||||
@section compat_osx OpenGL 3.2 and later on OS X
|
||||
@section compat_osx OpenGL 3.2 and later on macOS
|
||||
|
||||
Support for OpenGL 3.2 and above was introduced with OS X 10.7 and even then
|
||||
only forward-compatible, core profile contexts are supported. Support for
|
||||
@ -185,10 +185,11 @@ a non-default value will cause @ref glfwCreateWindow to fail and the
|
||||
|
||||
@section compat_vulkan Vulkan loader and API
|
||||
|
||||
GLFW uses the standard system-wide Vulkan loader to access the Vulkan API.
|
||||
This should be installed by graphics drivers and Vulkan SDKs. If this is not
|
||||
available, @ref glfwVulkanSupported will return `GLFW_FALSE` and all other
|
||||
Vulkan-related functions will fail with an @ref GLFW_API_UNAVAILABLE error.
|
||||
By default, GLFW uses the standard system-wide Vulkan loader to access the
|
||||
Vulkan API on all platforms except macOS. This is installed by both graphics
|
||||
drivers and Vulkan SDKs. If the loader is not found, @ref glfwVulkanSupported
|
||||
will return `GLFW_FALSE` and all other Vulkan-related functions will fail with
|
||||
an @ref GLFW_API_UNAVAILABLE error.
|
||||
|
||||
|
||||
@section compat_wsi Vulkan WSI extensions
|
||||
@ -201,6 +202,11 @@ surfaces on Microsoft Windows. If any of these extensions are not available,
|
||||
@ref glfwGetRequiredInstanceExtensions will return an empty list and window
|
||||
surface creation will fail.
|
||||
|
||||
GLFW uses the `VK_KHR_surface` and `VK_MVK_macos_surface` extensions to create
|
||||
surfaces on macOS. If any of these extensions are not available, @ref
|
||||
glfwGetRequiredInstanceExtensions will return an empty list and window surface
|
||||
creation will fail.
|
||||
|
||||
GLFW uses the `VK_KHR_surface` and either the `VK_KHR_xlib_surface` or
|
||||
`VK_KHR_xcb_surface` extensions to create surfaces on X11. If `VK_KHR_surface`
|
||||
or both `VK_KHR_xlib_surface` and `VK_KHR_xcb_surface` are not available, @ref
|
||||
@ -217,8 +223,4 @@ surfaces on Mir. If any of these extensions are not available, @ref
|
||||
glfwGetRequiredInstanceExtensions will return an empty list and window surface
|
||||
creation will fail.
|
||||
|
||||
GLFW does not support any extensions for window surface creation on OS X,
|
||||
meaning@ref glfwGetRequiredInstanceExtensions will return an empty list and
|
||||
window surface creation will fail.
|
||||
|
||||
*/
|
||||
|
@ -14,7 +14,8 @@ GLFW uses [CMake](http://www.cmake.org/) to generate project files or makefiles
|
||||
for a particular development environment. If you are on a Unix-like system such
|
||||
as Linux or FreeBSD or have a package system like Fink, MacPorts, Cygwin or
|
||||
Homebrew, you can simply install its CMake package. If not, you can download
|
||||
installers for Windows and OS X from the [CMake website](http://www.cmake.org/).
|
||||
installers for Windows and macOS from the
|
||||
[CMake website](http://www.cmake.org/).
|
||||
|
||||
@note CMake only generates project files or makefiles. It does not compile the
|
||||
actual GLFW library. To compile GLFW, first generate these files for your
|
||||
@ -76,11 +77,11 @@ the CMake wiki.
|
||||
Once you have this set up, move on to @ref compile_generate.
|
||||
|
||||
|
||||
@subsubsection compile_deps_xcode Dependencies for Xcode on OS X
|
||||
@subsubsection compile_deps_xcode Dependencies for Xcode on macOS
|
||||
|
||||
Xcode comes with all necessary tools except for CMake. The required headers
|
||||
and libraries are included in the core OS X frameworks. Xcode can be downloaded
|
||||
from the Mac App Store or from the ADC Member Center.
|
||||
and libraries are included in the core macOS frameworks. Xcode can be
|
||||
downloaded from the Mac App Store or from the ADC Member Center.
|
||||
|
||||
Once you have Xcode installed, move on to @ref compile_generate.
|
||||
|
||||
@ -96,6 +97,17 @@ Once you have installed the necessary packages, move on to @ref
|
||||
compile_generate.
|
||||
|
||||
|
||||
@subsection compile_deps_osmesa Dependencies for Linux and OSMesa
|
||||
|
||||
To compile GLFW for OSMesa, you need to install the OSMesa library and header
|
||||
packages. For example, on Ubuntu and other distributions based on Debian
|
||||
GNU/Linux, you need to install the `libosmesa6-dev` package. The OSMesa library
|
||||
is required at runtime for context creation and is loaded on demand.
|
||||
|
||||
Once you have installed the necessary packages, move on to @ref
|
||||
compile_generate.
|
||||
|
||||
|
||||
@subsection compile_generate Generating build files with CMake
|
||||
|
||||
Once you have all necessary dependencies it is time to generate the project
|
||||
@ -201,7 +213,7 @@ the library.
|
||||
statically into the application.
|
||||
|
||||
|
||||
@subsubsection compile_options_osx OS X specific CMake options
|
||||
@subsubsection compile_options_osx macOS specific CMake options
|
||||
|
||||
`GLFW_USE_CHDIR` determines whether `glfwInit` changes the current
|
||||
directory of bundled applications to the `Contents/Resources` directory.
|
||||
@ -248,6 +260,7 @@ ramps and clipboard. The options are:
|
||||
- `_GLFW_X11` to use the X Window System
|
||||
- `_GLFW_WAYLAND` to use the Wayland API (experimental and incomplete)
|
||||
- `_GLFW_MIR` to use the Mir API (experimental and incomplete)
|
||||
- `_GLFW_OSMESA` to use the OSMesa API (headless and non-interactive)
|
||||
|
||||
If you are building GLFW as a shared library / dynamic library / DLL then you
|
||||
must also define `_GLFW_BUILD_DLL`. Otherwise, you must not define it.
|
||||
|
@ -84,7 +84,7 @@ objects are recommended for rendering with such contexts.
|
||||
You should still [process events](@ref events) as long as you have at least one
|
||||
window, even if none of them are visible.
|
||||
|
||||
__OS X:__ The first time a window is created the menu bar is populated with
|
||||
@macos The first time a window is created the menu bar is populated with
|
||||
common commands like Hide, Quit and About. This is not desirable for example
|
||||
when writing a command-line only application. The menu bar setup can be
|
||||
disabled with a [compile-time option](@ref compile_options_osx).
|
||||
|
@ -572,7 +572,7 @@ The callback function receives the ID of the joystick that has been connected
|
||||
and disconnected and the event that occurred.
|
||||
|
||||
@code
|
||||
void joystick_callback(int joy, int event)
|
||||
void joystick_callback(int jid, int event)
|
||||
{
|
||||
if (event == GLFW_CONNECTED)
|
||||
{
|
||||
|
@ -16,6 +16,18 @@ GLFW now supports querying the platform dependent scancode of any key with
|
||||
@ref glfwGetKeyScancode.
|
||||
|
||||
|
||||
@subsection news_33_moltenvk Support for Vulkan on macOS via MoltenVK
|
||||
|
||||
GLFW now supports the `VK_MVK_macos_surface` window surface creation extension
|
||||
provided by MoltenVK.
|
||||
|
||||
|
||||
@subsection news_33_osmesa OSMesa backend for headless software rendering
|
||||
|
||||
GLFW now supports headless context creation and software rendering via OSMesa,
|
||||
intended for automated testing. This backend does not provide input.
|
||||
|
||||
|
||||
@section news_32 New features in 3.2
|
||||
|
||||
|
||||
@ -293,11 +305,12 @@ through CMake options.
|
||||
|
||||
@subsection news_30_hidpi High-DPI support
|
||||
|
||||
GLFW now supports high-DPI monitors on both Windows and OS X, giving windows full
|
||||
resolution framebuffers where other UI elements are scaled up. To achieve this,
|
||||
@ref glfwGetFramebufferSize and @ref glfwSetFramebufferSizeCallback have been
|
||||
added. These work with pixels, while the rest of the GLFW API works with screen
|
||||
coordinates. This is important as OpenGL uses pixels, not screen coordinates.
|
||||
GLFW now supports high-DPI monitors on both Windows and macOS, giving windows
|
||||
full resolution framebuffers where other UI elements are scaled up. To achieve
|
||||
this, @ref glfwGetFramebufferSize and @ref glfwSetFramebufferSizeCallback have
|
||||
been added. These work with pixels, while the rest of the GLFW API works with
|
||||
screen coordinates. This is important as OpenGL uses pixels, not screen
|
||||
coordinates.
|
||||
|
||||
|
||||
@subsection news_30_error Error callback
|
||||
|
@ -340,7 +340,7 @@ The program above can be found in the
|
||||
[source package](http://www.glfw.org/download.html) as `examples/simple.c`
|
||||
and is compiled along with all other examples when you build GLFW. If you
|
||||
built GLFW from the source package then already have this as `simple.exe` on
|
||||
Windows, `simple` on Linux or `simple.app` on OS X.
|
||||
Windows, `simple` on Linux or `simple.app` on macOS.
|
||||
|
||||
This tutorial used only a few of the many functions GLFW provides. There are
|
||||
guides for each of the areas covered by GLFW. Each guide will introduce all the
|
||||
|
@ -11,8 +11,10 @@ with Vulkan concepts like loaders, devices, queues and surfaces and leaves it to
|
||||
the Vulkan documentation to explain the details of Vulkan functions.
|
||||
|
||||
To develop for Vulkan you should install an SDK for your platform, for example
|
||||
the [LunarG Vulkan SDK](https://vulkan.lunarg.com/). Apart from the headers and
|
||||
libraries, it also provides the validation layers necessary for development.
|
||||
the [LunarG Vulkan SDK](https://vulkan.lunarg.com/) for Windows and Linux or
|
||||
[MoltenVK](https://moltengl.com/moltenvk/) for macOS. Apart from headers and
|
||||
link libraries, they should also provide the validation layers necessary for
|
||||
development.
|
||||
|
||||
The GLFW library does not need the Vulkan SDK to enable support for Vulkan.
|
||||
However, any Vulkan-specific test and example programs are built only if the
|
||||
@ -28,6 +30,26 @@ are also guides for the other areas of the GLFW API.
|
||||
- @ref input_guide
|
||||
|
||||
|
||||
@section vulkan_loader Linking against the Vulkan loader
|
||||
|
||||
By default, GLFW will look for the Vulkan loader on demand at runtime via its
|
||||
standard name (`vulkan-1.dll` on Windows, `libvulkan.so.1` on Linux and other
|
||||
Unix-like systems). This means that GLFW does not need to be linked against the
|
||||
loader. However, it also means that if you are using the static library form of
|
||||
the Vulkan loader GLFW will either fail to find it or (worse) use the wrong one.
|
||||
|
||||
The [GLFW_VULKAN_STATIC](@ref compile_options_shared) CMake option makes GLFW
|
||||
link directly against the static form. Not linking against the Vulkan loader
|
||||
will then be a compile-time error.
|
||||
|
||||
@macos MoltenVK only provides the static library form of the Vulkan loader, but
|
||||
GLFW is able to find it without
|
||||
[GLFW_VULKAN_STATIC](@ref compile_options_shared) as long as it is linked into
|
||||
any of the binaries already loaded into the process. As it is a static library,
|
||||
you must also link against its dependencies: the `Cocoa`, `Metal` and
|
||||
`QuartzCore` frameworks and the `libc++` library.
|
||||
|
||||
|
||||
@section vulkan_include Including the Vulkan and GLFW header files
|
||||
|
||||
To include the Vulkan header, define [GLFW_INCLUDE_VULKAN](@ref build_macros)
|
||||
|
@ -258,7 +258,7 @@ create the context. Possible values are `GLFW_NATIVE_CONTEXT_API` and
|
||||
requested, this hint is ignored.
|
||||
|
||||
@par
|
||||
__OS X:__ The EGL API is not available on this platform and requests to use it
|
||||
@macos The EGL API is not available on this platform and requests to use it
|
||||
will fail.
|
||||
|
||||
@par
|
||||
|
@ -11,6 +11,10 @@ if (MSVC)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
if (GLFW_USE_OSMESA)
|
||||
add_definitions(-DUSE_NATIVE_OSMESA)
|
||||
endif()
|
||||
|
||||
include_directories("${GLFW_SOURCE_DIR}/deps")
|
||||
|
||||
if (WIN32)
|
||||
@ -31,6 +35,7 @@ set(TINYCTHREAD "${GLFW_SOURCE_DIR}/deps/tinycthread.h"
|
||||
add_executable(boing WIN32 MACOSX_BUNDLE boing.c ${ICON} ${GLAD})
|
||||
add_executable(gears WIN32 MACOSX_BUNDLE gears.c ${ICON} ${GLAD})
|
||||
add_executable(heightmap WIN32 MACOSX_BUNDLE heightmap.c ${ICON} ${GLAD})
|
||||
add_executable(offscreen offscreen.c ${ICON} ${GLAD})
|
||||
add_executable(particles WIN32 MACOSX_BUNDLE particles.c ${ICON} ${TINYCTHREAD} ${GETOPT} ${GLAD})
|
||||
add_executable(simple WIN32 MACOSX_BUNDLE simple.c ${ICON} ${GLAD})
|
||||
add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c ${ICON} ${GLAD})
|
||||
|
171
examples/offscreen.c
Normal file
171
examples/offscreen.c
Normal file
@ -0,0 +1,171 @@
|
||||
//========================================================================
|
||||
// Offscreen rendering example
|
||||
// Copyright (c) Camilla Berglund <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#if USE_NATIVE_OSMESA
|
||||
#define GLFW_EXPOSE_NATIVE_OSMESA
|
||||
#include <GLFW/glfw3native.h>
|
||||
#endif
|
||||
|
||||
#include "linmath.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include <stb_image_write.h>
|
||||
|
||||
static const struct
|
||||
{
|
||||
float x, y;
|
||||
float r, g, b;
|
||||
} vertices[3] =
|
||||
{
|
||||
{ -0.6f, -0.4f, 1.f, 0.f, 0.f },
|
||||
{ 0.6f, -0.4f, 0.f, 1.f, 0.f },
|
||||
{ 0.f, 0.6f, 0.f, 0.f, 1.f }
|
||||
};
|
||||
|
||||
static const char* vertex_shader_text =
|
||||
"uniform mat4 MVP;\n"
|
||||
"attribute vec3 vCol;\n"
|
||||
"attribute vec2 vPos;\n"
|
||||
"varying vec3 color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
|
||||
" color = vCol;\n"
|
||||
"}\n";
|
||||
|
||||
static const char* fragment_shader_text =
|
||||
"varying vec3 color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_FragColor = vec4(color, 1.0);\n"
|
||||
"}\n";
|
||||
|
||||
static void error_callback(int error, const char* description)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", description);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
GLFWwindow* window;
|
||||
GLuint vertex_buffer, vertex_shader, fragment_shader, program;
|
||||
GLint mvp_location, vpos_location, vcol_location;
|
||||
float ratio;
|
||||
int width, height;
|
||||
mat4x4 mvp;
|
||||
char* buffer;
|
||||
|
||||
glfwSetErrorCallback(error_callback);
|
||||
|
||||
if (!glfwInit())
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||
|
||||
window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
|
||||
if (!window)
|
||||
{
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
|
||||
|
||||
// NOTE: OpenGL error checks have been omitted for brevity
|
||||
|
||||
glGenBuffers(1, &vertex_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
|
||||
glCompileShader(vertex_shader);
|
||||
|
||||
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
|
||||
glCompileShader(fragment_shader);
|
||||
|
||||
program = glCreateProgram();
|
||||
glAttachShader(program, vertex_shader);
|
||||
glAttachShader(program, fragment_shader);
|
||||
glLinkProgram(program);
|
||||
|
||||
mvp_location = glGetUniformLocation(program, "MVP");
|
||||
vpos_location = glGetAttribLocation(program, "vPos");
|
||||
vcol_location = glGetAttribLocation(program, "vCol");
|
||||
|
||||
glEnableVertexAttribArray(vpos_location);
|
||||
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
|
||||
sizeof(vertices[0]), (void*) 0);
|
||||
glEnableVertexAttribArray(vcol_location);
|
||||
glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,
|
||||
sizeof(vertices[0]), (void*) (sizeof(float) * 2));
|
||||
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
ratio = width / (float) height;
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
mat4x4_ortho(mvp, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);
|
||||
|
||||
glUseProgram(program);
|
||||
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
#if USE_NATIVE_OSMESA
|
||||
glfwGetOSMesaColorBuffer(window, &width, &height, NULL, (void**) &buffer);
|
||||
#else
|
||||
buffer = calloc(4, width * height);
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
||||
#endif
|
||||
|
||||
// Write image Y-flipped because OpenGL
|
||||
stbi_write_png("offscreen.png",
|
||||
width, height, 4,
|
||||
buffer + (width * 4 * (height - 1)),
|
||||
-width * 4);
|
||||
|
||||
#if USE_NATIVE_OSMESA
|
||||
// Here is where there's nothing
|
||||
#else
|
||||
free(buffer);
|
||||
#endif
|
||||
|
||||
glfwDestroyWindow(window);
|
||||
|
||||
glfwTerminate();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
@ -101,6 +101,12 @@ extern "C" {
|
||||
#endif
|
||||
#endif /* APIENTRY */
|
||||
|
||||
/* Some OpenGL related headers use GLAPIENTRY instead.
|
||||
*/
|
||||
#ifndef GLAPIENTRY
|
||||
#define GLAPIENTRY APIENTRY
|
||||
#endif /* GLAPIENTRY */
|
||||
|
||||
/* Some Windows OpenGL headers need this.
|
||||
*/
|
||||
#if !defined(WINGDIAPI) && defined(_WIN32)
|
||||
@ -116,7 +122,7 @@ extern "C" {
|
||||
#endif /* CALLBACK */
|
||||
|
||||
/* Include because most Windows GLU headers need wchar_t and
|
||||
* the OS X OpenGL header blocks the definition of ptrdiff_t by glext.h.
|
||||
* the macOS OpenGL header blocks the definition of ptrdiff_t by glext.h.
|
||||
* Include it unconditionally to avoid surprising side-effects.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
@ -176,7 +182,11 @@ extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
#if defined(GLFW_INCLUDE_VULKAN)
|
||||
#include <vulkan/vulkan.h>
|
||||
#if defined(__APPLE__)
|
||||
#include <MoltenVK/vulkan/vulkan.h>
|
||||
#else
|
||||
#include <vulkan/vulkan.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL)
|
||||
@ -561,7 +571,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 support it via
|
||||
* a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa
|
||||
* a WGL or GLX extension. macOS does not provide OpenGL ES at all. The Mesa
|
||||
* EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary
|
||||
* driver. Older graphics drivers do not support Vulkan.
|
||||
*/
|
||||
@ -1128,7 +1138,7 @@ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int);
|
||||
* This is the function signature for joystick configuration callback
|
||||
* functions.
|
||||
*
|
||||
* @param[in] joy The joystick that was connected or disconnected.
|
||||
* @param[in] jid The joystick that was connected or disconnected.
|
||||
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
|
||||
*
|
||||
* @sa @ref joystick_event
|
||||
@ -1247,7 +1257,7 @@ typedef struct GLFWimage
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @osx This function will change the current directory of the
|
||||
* @remark @macos This function will change the current directory of the
|
||||
* application to the `Contents/Resources` subdirectory of the application's
|
||||
* bundle, if present. This can be disabled with a
|
||||
* [compile-time option](@ref compile_options_osx).
|
||||
@ -1621,6 +1631,9 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @wayland Gamma handling is currently unavailable, this function will
|
||||
* always emit @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref monitor_gamma
|
||||
@ -1642,6 +1655,9 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma);
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @wayland Gamma handling is currently unavailable, this function will
|
||||
* always return `NULL` and emit @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @pointer_lifetime The returned structure and its arrays are allocated and
|
||||
* freed by GLFW. You should not free them yourself. They are valid until the
|
||||
* specified monitor is disconnected, this function is called again for that
|
||||
@ -1674,6 +1690,9 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
|
||||
*
|
||||
* @remark @win32 The gamma ramp size must be 256.
|
||||
*
|
||||
* @remark @wayland Gamma handling is currently unavailable, this function will
|
||||
* always emit @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @pointer_lifetime The specified gamma ramp is copied before this function
|
||||
* returns.
|
||||
*
|
||||
@ -1765,8 +1784,8 @@ GLFWAPI void glfwWindowHint(int hint, int value);
|
||||
* or _borderless full screen_ windows, see @ref window_windowed_full_screen.
|
||||
*
|
||||
* Once you have created the window, you can switch it between windowed and
|
||||
* full screen mode with @ref glfwSetWindowMonitor. If the window has an
|
||||
* OpenGL or OpenGL ES context, it will be unaffected.
|
||||
* full screen mode with @ref glfwSetWindowMonitor. This will not affect its
|
||||
* OpenGL or OpenGL ES context.
|
||||
*
|
||||
* By default, newly created windows use the placement recommended by the
|
||||
* window system. To create the window at a specific position, make it
|
||||
@ -1812,19 +1831,19 @@ GLFWAPI void glfwWindowHint(int hint, int value);
|
||||
* @remark @win32 The context to share resources with must not be current on
|
||||
* any other thread.
|
||||
*
|
||||
* @remark @osx The GLFW window has no icon, as it is not a document
|
||||
* @remark @macos The GLFW window has no icon, as it is not a document
|
||||
* window, but the dock icon will be the same as the application bundle's icon.
|
||||
* For more information on bundles, see the
|
||||
* [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
|
||||
* in the Mac Developer Library.
|
||||
*
|
||||
* @remark @osx The first time a window is created the menu bar is populated
|
||||
* @remark @macos The first time a window is created the menu bar is populated
|
||||
* with common commands like Hide, Quit and About. The About entry opens
|
||||
* a minimal about dialog with information from the application's bundle. The
|
||||
* menu bar can be disabled with a
|
||||
* [compile-time option](@ref compile_options_osx).
|
||||
*
|
||||
* @remark @osx On OS X 10.10 and later the window frame will not be rendered
|
||||
* @remark @macos On OS X 10.10 and later the window frame will not be rendered
|
||||
* at full resolution on Retina displays unless the `NSHighResolutionCapable`
|
||||
* key is enabled in the application bundle's `Info.plist`. For more
|
||||
* information, see
|
||||
@ -1841,6 +1860,20 @@ GLFWAPI void glfwWindowHint(int hint, int value);
|
||||
* query the final size, position or other attributes directly after window
|
||||
* creation.
|
||||
*
|
||||
* @remark @wayland The window frame is currently unimplemented, as if
|
||||
* `GLFW_DECORATED` was always set to `GLFW_FALSE`. A compositor can still
|
||||
* emit close, resize or maximize events, using for example a keybind
|
||||
* mechanism.
|
||||
*
|
||||
* @remark @wayland A full screen window will not attempt to change the mode,
|
||||
* no matter what the requested size or refresh rate.
|
||||
*
|
||||
* @remark @wayland The wl_shell protocol does not support window
|
||||
* icons, the window will inherit the one defined in the application's
|
||||
* desktop file, so this function emits @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @wayland Screensaver inhibition is currently unimplemented.
|
||||
*
|
||||
* @reentrancy This function must not be called from a callback.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
@ -1936,7 +1969,7 @@ GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value);
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @osx The window title will not be updated until the next time you
|
||||
* @remark @macos The window title will not be updated until the next time you
|
||||
* process events.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
@ -1973,12 +2006,16 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
|
||||
* @pointer_lifetime The specified image data is copied before this function
|
||||
* returns.
|
||||
*
|
||||
* @remark @osx The GLFW window has no icon, as it is not a document
|
||||
* @remark @macos The GLFW window has no icon, as it is not a document
|
||||
* window, so this function does nothing. The dock icon will be the same as
|
||||
* the application bundle's icon. For more information on bundles, see the
|
||||
* [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
|
||||
* in the Mac Developer Library.
|
||||
*
|
||||
* @remark @wayland The wl_shell protocol does not support icons, the window
|
||||
* will inherit the one defined in the application's desktop file, so this
|
||||
* function emits @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref window_icon
|
||||
@ -2006,6 +2043,10 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* i
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @wayland There is no way for an application to retrieve the global
|
||||
* position of its windows, this function will always emit @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref window_pos
|
||||
@ -2036,6 +2077,10 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @wayland There is no way for an application to set the global
|
||||
* position of its windows, this function will always emit @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref window_pos
|
||||
@ -2107,6 +2152,9 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
|
||||
* @remark If you set size limits and an aspect ratio that conflict, the
|
||||
* results are undefined.
|
||||
*
|
||||
* @remark @wayland The size limits will not be applied until the window is
|
||||
* actually resized, either by the user or by the compositor.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref window_sizelimits
|
||||
@ -2147,6 +2195,9 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minhe
|
||||
* @remark If you set size limits and an aspect ratio that conflict, the
|
||||
* results are undefined.
|
||||
*
|
||||
* @remark @wayland The aspect ratio will not be applied until the window is
|
||||
* actually resized, either by the user or by the compositor.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref window_sizelimits
|
||||
@ -2183,6 +2234,9 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @wayland A full screen window will not attempt to change the mode,
|
||||
* no matter what the requested size.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref window_size
|
||||
@ -2252,6 +2306,10 @@ GLFWAPI void glfwGetFramebufferSize(GLFWwindow* window, int* width, int* height)
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @wayland The window frame is currently unimplemented, as if
|
||||
* `GLFW_DECORATED` was always set to `GLFW_FALSE`, so the returned values
|
||||
* will always be zero.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref window_size
|
||||
@ -2276,6 +2334,9 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @wayland There is no concept of iconification in wl_shell, this
|
||||
* function will always emit @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref window_iconify
|
||||
@ -2403,6 +2464,9 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window);
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @wayland It is not possible for an application to bring its windows
|
||||
* to front, this function will always emit @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref window_focus
|
||||
@ -2453,7 +2517,7 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
|
||||
*
|
||||
* When a window transitions from full screen to windowed mode, this function
|
||||
* restores any previous window settings such as whether it is decorated,
|
||||
* floating, resizable, has size or aspect ratio limits, etc..
|
||||
* floating, resizable, has size or aspect ratio limits, etc.
|
||||
*
|
||||
* @param[in] window The window whose monitor, size or video mode to set.
|
||||
* @param[in] monitor The desired monitor, or `NULL` to set windowed mode.
|
||||
@ -2471,6 +2535,16 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark The OpenGL or OpenGL ES context will not be destroyed or otherwise
|
||||
* affected by any resizing or mode switching, although you may need to update
|
||||
* your viewport if the framebuffer size has changed.
|
||||
*
|
||||
* @remark @wayland The desired window position is ignored, as there is no way
|
||||
* for an application to set this property.
|
||||
*
|
||||
* @remark @wayland Setting the window to full screen will not attempt to
|
||||
* change the mode, no matter what the requested size or refresh rate.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref window_monitor
|
||||
@ -2575,6 +2649,9 @@ GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window);
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
||||
*
|
||||
* @remark @wayland This callback will never be called, as there is no way for
|
||||
* an application to know its global position.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref window_pos
|
||||
@ -2629,8 +2706,8 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwind
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
||||
*
|
||||
* @remark @osx Selecting Quit from the application menu will trigger the close
|
||||
* callback for all windows.
|
||||
* @remark @macos Selecting Quit from the application menu will trigger the
|
||||
* close callback for all windows.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
@ -2649,9 +2726,9 @@ GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwi
|
||||
* called when the client area of the window needs to be redrawn, for example
|
||||
* if the window has been exposed after having been covered by another window.
|
||||
*
|
||||
* On compositing window systems such as Aero, Compiz or Aqua, where the window
|
||||
* contents are saved off-screen, this callback may be called only very
|
||||
* infrequently or never at all.
|
||||
* On compositing window systems such as Aero, Compiz, Aqua or Wayland, where
|
||||
* the window contents are saved off-screen, this callback may be called only
|
||||
* very infrequently or never at all.
|
||||
*
|
||||
* @param[in] window The window whose callback to set.
|
||||
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
|
||||
@ -2713,6 +2790,9 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwi
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
||||
*
|
||||
* @remark @wayland The wl_shell protocol has no concept of iconification,
|
||||
* this callback will never be called.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref window_iconify
|
||||
@ -3205,6 +3285,9 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @wayland This function will only work when the cursor mode is
|
||||
* `GLFW_CURSOR_DISABLED`, otherwise it will do nothing.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref cursor_pos
|
||||
@ -3389,7 +3472,7 @@ GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun cbfun);
|
||||
*
|
||||
* The character callback behaves as system text input normally does and will
|
||||
* not be called if modifier keys are held down that would prevent normal text
|
||||
* input on that platform, for example a Super (Command) key on OS X or Alt key
|
||||
* input on that platform, for example a Super (Command) key on macOS or Alt key
|
||||
* on Windows. There is a
|
||||
* [character with modifiers callback](@ref glfwSetCharModsCallback) that
|
||||
* receives these events.
|
||||
@ -3570,6 +3653,8 @@ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun cb
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
||||
*
|
||||
* @remark @wayland File drop is currently unimplemented.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref path_drop
|
||||
@ -3584,7 +3669,7 @@ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun);
|
||||
*
|
||||
* This function returns whether the specified joystick is present.
|
||||
*
|
||||
* @param[in] joy The [joystick](@ref joysticks) to query.
|
||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||
* @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
@ -3598,7 +3683,7 @@ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun);
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
GLFWAPI int glfwJoystickPresent(int joy);
|
||||
GLFWAPI int glfwJoystickPresent(int jid);
|
||||
|
||||
/*! @brief Returns the values of all axes of the specified joystick.
|
||||
*
|
||||
@ -3609,7 +3694,7 @@ GLFWAPI int glfwJoystickPresent(int joy);
|
||||
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||
* check device presence.
|
||||
*
|
||||
* @param[in] joy The [joystick](@ref joysticks) to query.
|
||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||
* @param[out] count Where to store the number of axis values in the returned
|
||||
* array. This is set to zero if the joystick is not present or an error
|
||||
* occurred.
|
||||
@ -3632,7 +3717,7 @@ GLFWAPI int glfwJoystickPresent(int joy);
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count);
|
||||
GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count);
|
||||
|
||||
/*! @brief Returns the state of all buttons of the specified joystick.
|
||||
*
|
||||
@ -3643,7 +3728,7 @@ GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count);
|
||||
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||
* check device presence.
|
||||
*
|
||||
* @param[in] joy The [joystick](@ref joysticks) to query.
|
||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||
* @param[out] count Where to store the number of button states in the returned
|
||||
* array. This is set to zero if the joystick is not present or an error
|
||||
* occurred.
|
||||
@ -3667,7 +3752,7 @@ GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count);
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count);
|
||||
GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count);
|
||||
|
||||
/*! @brief Returns the name of the specified joystick.
|
||||
*
|
||||
@ -3679,7 +3764,7 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count);
|
||||
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||
* check device presence.
|
||||
*
|
||||
* @param[in] joy The [joystick](@ref joysticks) to query.
|
||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||
* @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick
|
||||
* is not present or an [error](@ref error_handling) occurred.
|
||||
*
|
||||
@ -3699,7 +3784,7 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count);
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
GLFWAPI const char* glfwGetJoystickName(int joy);
|
||||
GLFWAPI const char* glfwGetJoystickName(int jid);
|
||||
|
||||
/*! @brief Sets the joystick configuration callback.
|
||||
*
|
||||
@ -3735,6 +3820,8 @@ GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun);
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @wayland Clipboard is currently unimplemented.
|
||||
*
|
||||
* @pointer_lifetime The specified string is copied before this function
|
||||
* returns.
|
||||
*
|
||||
@ -3763,6 +3850,8 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @wayland Clipboard is currently unimplemented.
|
||||
*
|
||||
* @pointer_lifetime The returned string is allocated and freed by GLFW. You
|
||||
* should not free it yourself. It is valid until the next call to @ref
|
||||
* glfwGetClipboardString or @ref glfwSetClipboardString, or until the library
|
||||
@ -4141,11 +4230,14 @@ GLFWAPI int glfwVulkanSupported(void);
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_API_UNAVAILABLE.
|
||||
*
|
||||
* @remarks Additional extensions may be required by future versions of GLFW.
|
||||
* @remark Additional extensions may be required by future versions of GLFW.
|
||||
* You should check if any extensions you wish to enable are already in the
|
||||
* returned array, as it is an error to specify an extension more than once in
|
||||
* the `VkInstanceCreateInfo` struct.
|
||||
*
|
||||
* @remark @macos This function currently only supports the
|
||||
* `VK_MVK_macos_surface` extension from MoltenVK.
|
||||
*
|
||||
* @pointer_lifetime The returned array is allocated and freed by GLFW. You
|
||||
* should not free it yourself. It is guaranteed to be valid only until the
|
||||
* library is terminated.
|
||||
@ -4226,6 +4318,10 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* p
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @macos This function currently always returns `GLFW_TRUE`, as the
|
||||
* `VK_MVK_macos_surface` extension does not provide
|
||||
* a `vkGetPhysicalDevice*PresentationSupport` type function.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. For
|
||||
* synchronization details of Vulkan objects, see the Vulkan specification.
|
||||
*
|
||||
@ -4270,11 +4366,17 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhys
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remarks If an error occurs before the creation call is made, GLFW returns
|
||||
* @remark If an error occurs before the creation call is made, GLFW returns
|
||||
* the Vulkan error code most appropriate for the error. Appropriate use of
|
||||
* @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should
|
||||
* eliminate almost all occurrences of these errors.
|
||||
*
|
||||
* @remark @macos This function currently only supports the
|
||||
* `VK_MVK_macos_surface` extension from MoltenVK.
|
||||
*
|
||||
* @remark @macos This function creates and sets a `CAMetalLayer` instance for
|
||||
* the window content view, which is required for MoltenVK to function.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. For
|
||||
* synchronization details of Vulkan objects, see the Vulkan specification.
|
||||
*
|
||||
|
@ -50,7 +50,7 @@ extern "C" {
|
||||
* doing and how to fix problems caused by using them. If you don't, you
|
||||
* shouldn't be using them.**
|
||||
*
|
||||
* Before the inclusion of @ref glfw3native.h, you may define exactly one
|
||||
* Before the inclusion of @ref glfw3native.h, you may define zero or more
|
||||
* window system API macro and zero or more context creation API macros.
|
||||
*
|
||||
* The chosen backends must match those the library was compiled for. Failure
|
||||
@ -68,6 +68,7 @@ extern "C" {
|
||||
* * `GLFW_EXPOSE_NATIVE_NSGL`
|
||||
* * `GLFW_EXPOSE_NATIVE_GLX`
|
||||
* * `GLFW_EXPOSE_NATIVE_EGL`
|
||||
* * `GLFW_EXPOSE_NATIVE_OSMESA`
|
||||
*
|
||||
* These macros select which of the native access functions that are declared
|
||||
* and which platform-specific headers to include. It is then up your (by
|
||||
@ -114,6 +115,9 @@ extern "C" {
|
||||
#if defined(GLFW_EXPOSE_NATIVE_EGL)
|
||||
#include <EGL/egl.h>
|
||||
#endif
|
||||
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
|
||||
#include <GL/osmesa.h>
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
@ -448,6 +452,62 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
|
||||
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
|
||||
/*! @brief Retrieves the color buffer associated with the specified window.
|
||||
*
|
||||
* @param[out] width Where to store the width of the color buffer, or `NULL`.
|
||||
* @param[out] height Where to store the height of the color buffer, or `NULL`.
|
||||
* @param[out] format Where to store the OSMesa pixel format of the color
|
||||
* buffer, or `NULL`.
|
||||
* @param[out] buffer Where to store the address of the color buffer, or
|
||||
* `NULL`.
|
||||
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width, int* height, int* format, void** buffer);
|
||||
|
||||
/*! @brief Retrieves the depth buffer associated with the specified window.
|
||||
*
|
||||
* @param[out] width Where to store the width of the depth buffer, or `NULL`.
|
||||
* @param[out] height Where to store the height of the depth buffer, or `NULL`.
|
||||
* @param[out] bytesPerValue Where to store the number of bytes per depth
|
||||
* buffer element, or `NULL`.
|
||||
* @param[out] buffer Where to store the address of the depth buffer, or
|
||||
* `NULL`.
|
||||
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width, int* height, int* bytesPerValue, void** buffer);
|
||||
|
||||
/*! @brief Returns the `OSMesaContext` of the specified window.
|
||||
*
|
||||
* @return The `OSMesaContext` of the specified window, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -45,6 +45,12 @@ elseif (_GLFW_MIR)
|
||||
set(glfw_SOURCES ${common_SOURCES} mir_init.c mir_monitor.c mir_window.c
|
||||
linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c
|
||||
egl_context.c)
|
||||
elseif (_GLFW_OSMESA)
|
||||
set(glfw_HEADERS ${common_HEADERS} osmesa_platform.h
|
||||
posix_time.h posix_tls.h osmesa_context.h)
|
||||
set(glfw_SOURCES ${common_SOURCES} osmesa_init.c osmesa_monitor.c
|
||||
osmesa_window.c posix_time.c posix_tls.c
|
||||
osmesa_context.c)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
|
@ -1,5 +1,5 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OS X - www.glfw.org
|
||||
// GLFW 3.3 macOS - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
//
|
||||
|
@ -272,24 +272,24 @@ static void matchCallback(void* context,
|
||||
IOHIDDeviceRef deviceRef)
|
||||
{
|
||||
_GLFWjoystickNS* js;
|
||||
int joy;
|
||||
int jid;
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (_glfw.ns_js[joy].present && _glfw.ns_js[joy].deviceRef == deviceRef)
|
||||
if (_glfw.ns_js[jid].present && _glfw.ns_js[jid].deviceRef == deviceRef)
|
||||
return;
|
||||
}
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (!_glfw.ns_js[joy].present)
|
||||
if (!_glfw.ns_js[jid].present)
|
||||
break;
|
||||
}
|
||||
|
||||
if (joy > GLFW_JOYSTICK_LAST)
|
||||
if (jid > GLFW_JOYSTICK_LAST)
|
||||
return;
|
||||
|
||||
js = _glfw.ns_js + joy;
|
||||
js = _glfw.ns_js + jid;
|
||||
js->present = GLFW_TRUE;
|
||||
js->deviceRef = deviceRef;
|
||||
|
||||
@ -324,7 +324,7 @@ static void matchCallback(void* context,
|
||||
js->buttons = calloc(CFArrayGetCount(js->buttonElements) +
|
||||
CFArrayGetCount(js->hatElements) * 4, 1);
|
||||
|
||||
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
||||
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
||||
}
|
||||
|
||||
// Callback for user-initiated joystick removal
|
||||
@ -334,13 +334,13 @@ static void removeCallback(void* context,
|
||||
void* sender,
|
||||
IOHIDDeviceRef deviceRef)
|
||||
{
|
||||
int joy;
|
||||
int jid;
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (_glfw.ns_js[joy].deviceRef == deviceRef)
|
||||
if (_glfw.ns_js[jid].deviceRef == deviceRef)
|
||||
{
|
||||
removeJoystick(_glfw.ns_js + joy);
|
||||
removeJoystick(_glfw.ns_js + jid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -456,11 +456,11 @@ void _glfwInitJoysticksNS(void)
|
||||
//
|
||||
void _glfwTerminateJoysticksNS(void)
|
||||
{
|
||||
int joy;
|
||||
int jid;
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
_GLFWjoystickNS* js = _glfw.ns_js + joy;
|
||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
||||
removeJoystick(js);
|
||||
}
|
||||
|
||||
@ -473,15 +473,15 @@ void _glfwTerminateJoysticksNS(void)
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformJoystickPresent(int joy)
|
||||
int _glfwPlatformJoystickPresent(int jid)
|
||||
{
|
||||
_GLFWjoystickNS* js = _glfw.ns_js + joy;
|
||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
||||
return js->present;
|
||||
}
|
||||
|
||||
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||
const float* _glfwPlatformGetJoystickAxes(int jid, int* count)
|
||||
{
|
||||
_GLFWjoystickNS* js = _glfw.ns_js + joy;
|
||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
||||
if (!pollJoystickAxisEvents(js))
|
||||
return NULL;
|
||||
|
||||
@ -489,9 +489,9 @@ const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||
return js->axes;
|
||||
}
|
||||
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int jid, int* count)
|
||||
{
|
||||
_GLFWjoystickNS* js = _glfw.ns_js + joy;
|
||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
||||
if (!pollJoystickButtonEvents(js))
|
||||
return NULL;
|
||||
|
||||
@ -500,9 +500,9 @@ const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||
return js->buttons;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetJoystickName(int joy)
|
||||
const char* _glfwPlatformGetJoystickName(int jid)
|
||||
{
|
||||
_GLFWjoystickNS* js = _glfw.ns_js + joy;
|
||||
_GLFWjoystickNS* js = _glfw.ns_js + jid;
|
||||
if (!js->present)
|
||||
return NULL;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OS X - www.glfw.org
|
||||
// GLFW 3.3 macOS - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
|
@ -1,5 +1,5 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OS X - www.glfw.org
|
||||
// GLFW 3.3 macOS - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
//
|
||||
@ -39,6 +39,18 @@
|
||||
typedef void* id;
|
||||
#endif
|
||||
|
||||
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
|
||||
|
||||
typedef struct VkMacOSSurfaceCreateInfoMVK
|
||||
{
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkMacOSSurfaceCreateFlagsMVK flags;
|
||||
const void* pView;
|
||||
} VkMacOSSurfaceCreateInfoMVK;
|
||||
|
||||
typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
|
||||
#include "posix_tls.h"
|
||||
#include "cocoa_joystick.h"
|
||||
#include "nsgl_context.h"
|
||||
@ -74,6 +86,7 @@ typedef struct _GLFWwindowNS
|
||||
id object;
|
||||
id delegate;
|
||||
id view;
|
||||
id layer;
|
||||
|
||||
GLFWbool maximized;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OS X - www.glfw.org
|
||||
// GLFW 3.3 macOS - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
//
|
||||
|
@ -1,5 +1,5 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OS X - www.glfw.org
|
||||
// GLFW 3.3 macOS - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
//
|
||||
@ -32,6 +32,23 @@
|
||||
// Needed for _NSGetProgname
|
||||
#include <crt_externs.h>
|
||||
|
||||
// HACK: The 10.12 SDK adds new symbols and immediately deprecates the old ones
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
||||
#define NSWindowStyleMaskBorderless NSBorderlessWindowMask
|
||||
#define NSWindowStyleMaskClosable NSClosableWindowMask
|
||||
#define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask
|
||||
#define NSWindowStyleMaskResizable NSResizableWindowMask
|
||||
#define NSWindowStyleMaskTitled NSTitledWindowMask
|
||||
#define NSEventModifierFlagCommand NSCommandKeyMask
|
||||
#define NSEventModifierFlagControl NSControlKeyMask
|
||||
#define NSEventModifierFlagOption NSAlternateKeyMask
|
||||
#define NSEventModifierFlagShift NSShiftKeyMask
|
||||
#define NSEventModifierFlagDeviceIndependentFlagsMask NSDeviceIndependentModifierFlagsMask
|
||||
#define NSEventMaskAny NSAnyEventMask
|
||||
#define NSEventTypeApplicationDefined NSApplicationDefined
|
||||
#define NSEventTypeKeyUp NSKeyUp
|
||||
#endif
|
||||
|
||||
|
||||
// Returns the specified standard cursor
|
||||
//
|
||||
@ -63,14 +80,15 @@ static NSUInteger getStyleMask(_GLFWwindow* window)
|
||||
NSUInteger styleMask = 0;
|
||||
|
||||
if (window->monitor || !window->decorated)
|
||||
styleMask |= NSBorderlessWindowMask;
|
||||
styleMask |= NSWindowStyleMaskBorderless;
|
||||
else
|
||||
{
|
||||
styleMask |= NSTitledWindowMask | NSClosableWindowMask |
|
||||
NSMiniaturizableWindowMask;
|
||||
styleMask |= NSWindowStyleMaskTitled |
|
||||
NSWindowStyleMaskClosable |
|
||||
NSWindowStyleMaskMiniaturizable;
|
||||
|
||||
if (window->resizable)
|
||||
styleMask |= NSResizableWindowMask;
|
||||
styleMask |= NSWindowStyleMaskResizable;
|
||||
}
|
||||
|
||||
return styleMask;
|
||||
@ -144,25 +162,25 @@ static void releaseMonitor(_GLFWwindow* window)
|
||||
_glfwRestoreVideoModeNS(window->monitor);
|
||||
}
|
||||
|
||||
// Translates OS X key modifiers into GLFW ones
|
||||
// Translates macOS key modifiers into GLFW ones
|
||||
//
|
||||
static int translateFlags(NSUInteger flags)
|
||||
{
|
||||
int mods = 0;
|
||||
|
||||
if (flags & NSShiftKeyMask)
|
||||
if (flags & NSEventModifierFlagShift)
|
||||
mods |= GLFW_MOD_SHIFT;
|
||||
if (flags & NSControlKeyMask)
|
||||
if (flags & NSEventModifierFlagControl)
|
||||
mods |= GLFW_MOD_CONTROL;
|
||||
if (flags & NSAlternateKeyMask)
|
||||
if (flags & NSEventModifierFlagOption)
|
||||
mods |= GLFW_MOD_ALT;
|
||||
if (flags & NSCommandKeyMask)
|
||||
if (flags & NSEventModifierFlagCommand)
|
||||
mods |= GLFW_MOD_SUPER;
|
||||
|
||||
return mods;
|
||||
}
|
||||
|
||||
// Translates a OS X keycode to a GLFW keycode
|
||||
// Translates a macOS keycode to a GLFW keycode
|
||||
//
|
||||
static int translateKey(unsigned int key)
|
||||
{
|
||||
@ -180,16 +198,16 @@ static NSUInteger translateKeyToModifierFlag(int key)
|
||||
{
|
||||
case GLFW_KEY_LEFT_SHIFT:
|
||||
case GLFW_KEY_RIGHT_SHIFT:
|
||||
return NSShiftKeyMask;
|
||||
return NSEventModifierFlagShift;
|
||||
case GLFW_KEY_LEFT_CONTROL:
|
||||
case GLFW_KEY_RIGHT_CONTROL:
|
||||
return NSControlKeyMask;
|
||||
return NSEventModifierFlagControl;
|
||||
case GLFW_KEY_LEFT_ALT:
|
||||
case GLFW_KEY_RIGHT_ALT:
|
||||
return NSAlternateKeyMask;
|
||||
return NSEventModifierFlagOption;
|
||||
case GLFW_KEY_LEFT_SUPER:
|
||||
case GLFW_KEY_RIGHT_SUPER:
|
||||
return NSCommandKeyMask;
|
||||
return NSEventModifierFlagCommand;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -413,6 +431,16 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)wantsUpdateLayer
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (id)makeBackingLayer
|
||||
{
|
||||
return window->ns.layer;
|
||||
}
|
||||
|
||||
- (void)cursorUpdate:(NSEvent *)event
|
||||
{
|
||||
updateCursorImage(window);
|
||||
@ -565,7 +593,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
{
|
||||
int action;
|
||||
const unsigned int modifierFlags =
|
||||
[event modifierFlags] & NSDeviceIndependentModifierFlagsMask;
|
||||
[event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
|
||||
const int key = translateKey([event keyCode]);
|
||||
const int mods = translateFlags(modifierFlags);
|
||||
const NSUInteger keyFlag = translateKeyToModifierFlag(key);
|
||||
@ -760,7 +788,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
|
||||
- (BOOL)canBecomeKeyWindow
|
||||
{
|
||||
// Required for NSBorderlessWindowMask windows
|
||||
// Required for NSWindowStyleMaskBorderless windows
|
||||
return YES;
|
||||
}
|
||||
|
||||
@ -781,8 +809,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
// down the command key don't get sent to the key window.
|
||||
- (void)sendEvent:(NSEvent *)event
|
||||
{
|
||||
if ([event type] == NSKeyUp && ([event modifierFlags] & NSCommandKeyMask))
|
||||
if ([event type] == NSEventTypeKeyUp &&
|
||||
([event modifierFlags] & NSEventModifierFlagCommand))
|
||||
{
|
||||
[[self keyWindow] sendEvent:event];
|
||||
}
|
||||
else
|
||||
[super sendEvent:event];
|
||||
}
|
||||
@ -866,7 +897,7 @@ static void createMenuBar(void)
|
||||
[[appMenu addItemWithTitle:@"Hide Others"
|
||||
action:@selector(hideOtherApplications:)
|
||||
keyEquivalent:@"h"]
|
||||
setKeyEquivalentModifierMask:NSAlternateKeyMask | NSCommandKeyMask];
|
||||
setKeyEquivalentModifierMask:NSEventModifierFlagOption | NSEventModifierFlagCommand];
|
||||
[appMenu addItemWithTitle:@"Show All"
|
||||
action:@selector(unhideAllApplications:)
|
||||
keyEquivalent:@""];
|
||||
@ -898,7 +929,7 @@ static void createMenuBar(void)
|
||||
[[windowMenu addItemWithTitle:@"Enter Full Screen"
|
||||
action:@selector(toggleFullScreen:)
|
||||
keyEquivalent:@"f"]
|
||||
setKeyEquivalentModifierMask:NSControlKeyMask | NSCommandKeyMask];
|
||||
setKeyEquivalentModifierMask:NSEventModifierFlagControl | NSEventModifierFlagCommand];
|
||||
|
||||
// Prior to Snow Leopard, we need to use this oddly-named semi-private API
|
||||
// to get the application menu working properly.
|
||||
@ -1011,11 +1042,11 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
|
||||
#endif /*_GLFW_USE_RETINA*/
|
||||
|
||||
[window->ns.object setContentView:window->ns.view];
|
||||
[window->ns.object makeFirstResponder:window->ns.view];
|
||||
[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];
|
||||
[window->ns.object setRestorable:NO];
|
||||
|
||||
return GLFW_TRUE;
|
||||
@ -1162,7 +1193,7 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
|
||||
{
|
||||
if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
|
||||
[window->ns.object setContentAspectRatio:NSMakeSize(0, 0)];
|
||||
[window->ns.object setResizeIncrements:NSMakeSize(1.0, 1.0)];
|
||||
else
|
||||
[window->ns.object setContentAspectRatio:NSMakeSize(numer, denom)];
|
||||
}
|
||||
@ -1358,7 +1389,7 @@ void _glfwPlatformPollEvents(void)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
||||
untilDate:[NSDate distantPast]
|
||||
inMode:NSDefaultRunLoopMode
|
||||
dequeue:YES];
|
||||
@ -1377,7 +1408,7 @@ void _glfwPlatformWaitEvents(void)
|
||||
// I wanted to pass NO to dequeue:, and rely on PollEvents to
|
||||
// dequeue and send. For reasons not at all clear to me, passing
|
||||
// NO to dequeue: causes this method never to return.
|
||||
NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||
NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
||||
untilDate:[NSDate distantFuture]
|
||||
inMode:NSDefaultRunLoopMode
|
||||
dequeue:YES];
|
||||
@ -1389,7 +1420,7 @@ void _glfwPlatformWaitEvents(void)
|
||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||
{
|
||||
NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout];
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
||||
untilDate:date
|
||||
inMode:NSDefaultRunLoopMode
|
||||
dequeue:YES];
|
||||
@ -1402,7 +1433,7 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||
void _glfwPlatformPostEmptyEvent(void)
|
||||
{
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
NSEvent* event = [NSEvent otherEventWithType:NSApplicationDefined
|
||||
NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
|
||||
location:NSMakePoint(0, 0)
|
||||
modifierFlags:0
|
||||
timestamp:0
|
||||
@ -1632,13 +1663,18 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
{
|
||||
if (!_glfw.vk.KHR_surface || !_glfw.vk.MVK_macos_surface)
|
||||
return;
|
||||
|
||||
extensions[0] = "VK_KHR_surface";
|
||||
extensions[1] = "VK_MVK_macos_surface";
|
||||
}
|
||||
|
||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
@ -1646,7 +1682,57 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
const VkAllocationCallbacks* allocator,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
|
||||
VkResult err;
|
||||
VkMacOSSurfaceCreateInfoMVK sci;
|
||||
PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK;
|
||||
|
||||
vkCreateMacOSSurfaceMVK = (PFN_vkCreateMacOSSurfaceMVK)
|
||||
vkGetInstanceProcAddr(instance, "vkCreateMacOSSurfaceMVK");
|
||||
if (!vkCreateMacOSSurfaceMVK)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Cocoa: Vulkan instance missing VK_MVK_macos_surface extension");
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
}
|
||||
|
||||
// HACK: Dynamically load Core Animation to avoid adding an extra
|
||||
// dependency for the majority who don't use MoltenVK
|
||||
NSBundle* bundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/QuartzCore.framework"];
|
||||
if (!bundle)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to find QuartzCore.framework");
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
}
|
||||
|
||||
// NOTE: Create the layer here as makeBackingLayer should not return nil
|
||||
window->ns.layer = [[bundle classNamed:@"CAMetalLayer"] layer];
|
||||
if (!window->ns.layer)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to create layer for view");
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
}
|
||||
|
||||
[window->ns.view setWantsLayer:YES];
|
||||
|
||||
memset(&sci, 0, sizeof(sci));
|
||||
sci.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
|
||||
sci.pView = window->ns.view;
|
||||
|
||||
err = vkCreateMacOSSurfaceMVK(instance, &sci, allocator, surface);
|
||||
if (err)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to create Vulkan surface: %s",
|
||||
_glfwGetVulkanResultString(err));
|
||||
}
|
||||
|
||||
return err;
|
||||
#else
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -44,6 +44,8 @@
|
||||
#cmakedefine _GLFW_WAYLAND
|
||||
// Define this to 1 if building GLFW for Mir
|
||||
#cmakedefine _GLFW_MIR
|
||||
// Define this to 1 if building GLFW for OSMesa
|
||||
#cmakedefine _GLFW_OSMESA
|
||||
|
||||
// Define this to 1 if building as a shared library / dynamic library / DLL
|
||||
#cmakedefine _GLFW_BUILD_DLL
|
||||
|
36
src/input.c
36
src/input.c
@ -124,10 +124,10 @@ void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
|
||||
window->callbacks.drop((GLFWwindow*) window, count, paths);
|
||||
}
|
||||
|
||||
void _glfwInputJoystickChange(int joy, int event)
|
||||
void _glfwInputJoystickChange(int jid, int event)
|
||||
{
|
||||
if (_glfw.callbacks.joystick)
|
||||
_glfw.callbacks.joystick(joy, event);
|
||||
_glfw.callbacks.joystick(jid, event);
|
||||
}
|
||||
|
||||
|
||||
@ -553,62 +553,62 @@ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun)
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI int glfwJoystickPresent(int joy)
|
||||
GLFWAPI int glfwJoystickPresent(int jid)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||
|
||||
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", jid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _glfwPlatformJoystickPresent(joy);
|
||||
return _glfwPlatformJoystickPresent(jid);
|
||||
}
|
||||
|
||||
GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count)
|
||||
GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
|
||||
{
|
||||
assert(count != NULL);
|
||||
*count = 0;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", jid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _glfwPlatformGetJoystickAxes(joy, count);
|
||||
return _glfwPlatformGetJoystickAxes(jid, count);
|
||||
}
|
||||
|
||||
GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count)
|
||||
GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
|
||||
{
|
||||
assert(count != NULL);
|
||||
*count = 0;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", jid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _glfwPlatformGetJoystickButtons(joy, count);
|
||||
return _glfwPlatformGetJoystickButtons(jid, count);
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetJoystickName(int joy)
|
||||
GLFWAPI const char* glfwGetJoystickName(int jid)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", jid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _glfwPlatformGetJoystickName(joy);
|
||||
return _glfwPlatformGetJoystickName(jid);
|
||||
}
|
||||
|
||||
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
|
||||
|
@ -69,6 +69,7 @@ typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
|
||||
#define GL_VERSION 0x1f02
|
||||
#define GL_NONE 0
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_EXTENSIONS 0x1f03
|
||||
#define GL_NUM_EXTENSIONS 0x821d
|
||||
#define GL_CONTEXT_FLAGS 0x821e
|
||||
@ -110,6 +111,7 @@ typedef enum VkStructureType
|
||||
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
|
||||
VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
|
||||
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
|
||||
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000053000,
|
||||
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
|
||||
} VkStructureType;
|
||||
|
||||
@ -171,6 +173,8 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
||||
#include "wl_platform.h"
|
||||
#elif defined(_GLFW_MIR)
|
||||
#include "mir_platform.h"
|
||||
#elif defined(_GLFW_OSMESA)
|
||||
#include "osmesa_platform.h"
|
||||
#else
|
||||
#error "No supported window creation API selected"
|
||||
#endif
|
||||
@ -458,6 +462,8 @@ struct _GLFWlibrary
|
||||
GLFWbool KHR_surface;
|
||||
#if defined(_GLFW_WIN32)
|
||||
GLFWbool KHR_win32_surface;
|
||||
#elif defined(_GLFW_COCOA)
|
||||
GLFWbool MVK_macos_surface;
|
||||
#elif defined(_GLFW_X11)
|
||||
GLFWbool KHR_xlib_surface;
|
||||
GLFWbool KHR_xcb_surface;
|
||||
@ -608,22 +614,22 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window);
|
||||
/*! @copydoc glfwJoystickPresent
|
||||
* @ingroup platform
|
||||
*/
|
||||
int _glfwPlatformJoystickPresent(int joy);
|
||||
int _glfwPlatformJoystickPresent(int jid);
|
||||
|
||||
/*! @copydoc glfwGetJoystickAxes
|
||||
* @ingroup platform
|
||||
*/
|
||||
const float* _glfwPlatformGetJoystickAxes(int joy, int* count);
|
||||
const float* _glfwPlatformGetJoystickAxes(int jid, int* count);
|
||||
|
||||
/*! @copydoc glfwGetJoystickButtons
|
||||
* @ingroup platform
|
||||
*/
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count);
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int jid, int* count);
|
||||
|
||||
/*! @copydoc glfwGetJoystickName
|
||||
* @ingroup platform
|
||||
*/
|
||||
const char* _glfwPlatformGetJoystickName(int joy);
|
||||
const char* _glfwPlatformGetJoystickName(int jid);
|
||||
|
||||
/*! @copydoc glfwGetTimerValue
|
||||
* @ingroup platform
|
||||
@ -961,11 +967,11 @@ void _glfwInputError(int error, const char* format, ...);
|
||||
void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
|
||||
|
||||
/*! @brief Notifies shared code of a joystick connection/disconnection event.
|
||||
* @param[in] joy The joystick that was connected or disconnected.
|
||||
* @param[in] jid The joystick that was connected or disconnected.
|
||||
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputJoystickChange(int joy, int event);
|
||||
void _glfwInputJoystickChange(int jid, int event);
|
||||
|
||||
|
||||
//========================================================================
|
||||
@ -1060,7 +1066,7 @@ GLFWbool _glfwIsPrintable(int key);
|
||||
|
||||
/*! @ingroup utility
|
||||
*/
|
||||
GLFWbool _glfwInitVulkan(void);
|
||||
GLFWbool _glfwInitVulkan(int mode);
|
||||
|
||||
/*! @ingroup utility
|
||||
*/
|
||||
|
@ -50,25 +50,25 @@ static GLFWbool openJoystickDevice(const char* path)
|
||||
{
|
||||
char axisCount, buttonCount;
|
||||
char name[256] = "";
|
||||
int joy, fd, version;
|
||||
int jid, fd, version;
|
||||
_GLFWjoystickLinux* js;
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (!_glfw.linux_js.js[joy].present)
|
||||
if (!_glfw.linux_js.js[jid].present)
|
||||
continue;
|
||||
|
||||
if (strcmp(_glfw.linux_js.js[joy].path, path) == 0)
|
||||
if (strcmp(_glfw.linux_js.js[jid].path, path) == 0)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (!_glfw.linux_js.js[joy].present)
|
||||
if (!_glfw.linux_js.js[jid].present)
|
||||
break;
|
||||
}
|
||||
|
||||
if (joy > GLFW_JOYSTICK_LAST)
|
||||
if (jid > GLFW_JOYSTICK_LAST)
|
||||
return GLFW_FALSE;
|
||||
|
||||
fd = open(path, O_RDONLY | O_NONBLOCK);
|
||||
@ -87,7 +87,7 @@ static GLFWbool openJoystickDevice(const char* path)
|
||||
if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
|
||||
strncpy(name, "Unknown", sizeof(name));
|
||||
|
||||
js = _glfw.linux_js.js + joy;
|
||||
js = _glfw.linux_js.js + jid;
|
||||
js->present = GLFW_TRUE;
|
||||
js->name = strdup(name);
|
||||
js->path = strdup(path);
|
||||
@ -101,7 +101,7 @@ static GLFWbool openJoystickDevice(const char* path)
|
||||
js->buttonCount = (int) buttonCount;
|
||||
js->buttons = calloc(buttonCount, 1);
|
||||
|
||||
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
||||
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
#endif // __linux__
|
||||
@ -304,15 +304,15 @@ void _glfwPollJoystickEvents(void)
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformJoystickPresent(int joy)
|
||||
int _glfwPlatformJoystickPresent(int jid)
|
||||
{
|
||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + joy;
|
||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + jid;
|
||||
return pollJoystickEvents(js);
|
||||
}
|
||||
|
||||
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||
const float* _glfwPlatformGetJoystickAxes(int jid, int* count)
|
||||
{
|
||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + joy;
|
||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + jid;
|
||||
if (!pollJoystickEvents(js))
|
||||
return NULL;
|
||||
|
||||
@ -320,9 +320,9 @@ const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||
return js->axes;
|
||||
}
|
||||
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int jid, int* count)
|
||||
{
|
||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + joy;
|
||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + jid;
|
||||
if (!pollJoystickEvents(js))
|
||||
return NULL;
|
||||
|
||||
@ -330,9 +330,9 @@ const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||
return js->buttons;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetJoystickName(int joy)
|
||||
const char* _glfwPlatformGetJoystickName(int jid)
|
||||
{
|
||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + joy;
|
||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + jid;
|
||||
if (!pollJoystickEvents(js))
|
||||
return NULL;
|
||||
|
||||
|
@ -175,10 +175,12 @@ void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window)
|
||||
_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
|
||||
{
|
||||
_GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
|
||||
monitor->name = strdup(name);
|
||||
monitor->widthMM = widthMM;
|
||||
monitor->heightMM = heightMM;
|
||||
|
||||
if (name)
|
||||
monitor->name = strdup(name);
|
||||
|
||||
return monitor;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OS X - www.glfw.org
|
||||
// GLFW 3.3 macOS - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
//
|
||||
|
@ -1,5 +1,5 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OS X - www.glfw.org
|
||||
// GLFW 3.3 macOS - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
//
|
||||
@ -124,14 +124,14 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"NSGL: OpenGL ES is not available on OS X");
|
||||
"NSGL: OpenGL ES is not available on macOS");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (ctxconfig->major == 3 && ctxconfig->minor < 2)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"NSGL: The targeted version of OS X does not support OpenGL 3.0 or 3.1");
|
||||
"NSGL: The targeted version of macOS does not support OpenGL 3.0 or 3.1");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
@ -140,23 +140,23 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
if (!ctxconfig->forward)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"NSGL: The targeted version of OS X only supports forward-compatible contexts for OpenGL 3.2 and above");
|
||||
"NSGL: The targeted version of macOS only supports forward-compatible contexts for OpenGL 3.2 and above");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"NSGL: The targeted version of OS X only supports core profile contexts for OpenGL 3.2 and above");
|
||||
"NSGL: The targeted version of macOS only supports core profile contexts for OpenGL 3.2 and above");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Context robustness modes (GL_KHR_robustness) are not yet supported on
|
||||
// OS X but are not a hard constraint, so ignore and continue
|
||||
// macOS but are not a hard constraint, so ignore and continue
|
||||
|
||||
// Context release behaviors (GL_KHR_context_flush_control) are not yet
|
||||
// supported on OS X but are not a hard constraint, so ignore and continue
|
||||
// supported on macOS but are not a hard constraint, so ignore and continue
|
||||
|
||||
#define ADD_ATTR(x) { attributes[attributeCount++] = x; }
|
||||
#define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); }
|
||||
@ -206,7 +206,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
fbconfig->greenBits +
|
||||
fbconfig->blueBits;
|
||||
|
||||
// OS X needs non-zero color size, so set reasonable values
|
||||
// macOS needs non-zero color size, so set reasonable values
|
||||
if (colorBits == 0)
|
||||
colorBits = 24;
|
||||
else if (colorBits < 15)
|
||||
@ -225,7 +225,15 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
ADD_ATTR2(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
|
||||
|
||||
if (fbconfig->stereo)
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"NSGL: Stereo rendering is deprecated");
|
||||
return GLFW_FALSE;
|
||||
#else
|
||||
ADD_ATTR(NSOpenGLPFAStereo);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (fbconfig->doublebuffer)
|
||||
ADD_ATTR(NSOpenGLPFADoubleBuffer);
|
||||
|
367
src/osmesa_context.c
Normal file
367
src/osmesa_context.c
Normal file
@ -0,0 +1,367 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OSMesa - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
static void makeContextCurrentOSMesa(_GLFWwindow* window)
|
||||
{
|
||||
if (window)
|
||||
{
|
||||
// Check to see if we need to allocate a new buffer
|
||||
if ((window->context.osmesa.buffer == NULL) ||
|
||||
(window->osmesa.width != window->context.osmesa.width) ||
|
||||
(window->osmesa.height != window->context.osmesa.height))
|
||||
{
|
||||
free(window->context.osmesa.buffer);
|
||||
|
||||
// Allocate the new buffer (width * height * 8-bit RGBA)
|
||||
window->context.osmesa.buffer =
|
||||
calloc(4, window->osmesa.width * window->osmesa.height);
|
||||
|
||||
window->context.osmesa.width = window->osmesa.width;
|
||||
window->context.osmesa.height = window->osmesa.height;
|
||||
}
|
||||
|
||||
if (!OSMesaMakeCurrent(window->context.osmesa.handle,
|
||||
window->context.osmesa.buffer,
|
||||
GL_UNSIGNED_BYTE,
|
||||
window->osmesa.width, window->osmesa.height))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"OSMesa: Failed to make context current");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_glfwPlatformSetCurrentContext(window);
|
||||
}
|
||||
|
||||
static GLFWglproc getProcAddressOSMesa(const char* procname)
|
||||
{
|
||||
return (GLFWglproc) OSMesaGetProcAddress(procname);
|
||||
}
|
||||
|
||||
static void destroyContextOSMesa(_GLFWwindow* window)
|
||||
{
|
||||
if (window->context.osmesa.handle)
|
||||
{
|
||||
OSMesaDestroyContext(window->context.osmesa.handle);
|
||||
window->context.osmesa.handle = NULL;
|
||||
}
|
||||
|
||||
if (window->context.osmesa.buffer)
|
||||
{
|
||||
free(window->context.osmesa.buffer);
|
||||
window->context.osmesa.width = 0;
|
||||
window->context.osmesa.height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void swapBuffersOSMesa(_GLFWwindow* window)
|
||||
{
|
||||
// No double buffering on OSMesa
|
||||
}
|
||||
|
||||
static void swapIntervalOSMesa(int interval)
|
||||
{
|
||||
// No swap interval on OSMesa
|
||||
}
|
||||
|
||||
static int extensionSupportedOSMesa(const char* extension)
|
||||
{
|
||||
// OSMesa does not have extensions
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwInitOSMesa(void)
|
||||
{
|
||||
int i;
|
||||
const char* sonames[] =
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
"libOSMesa.dll",
|
||||
"OSMesa.dll",
|
||||
#elif defined(__APPLE__)
|
||||
"libOSMesa.8.dylib",
|
||||
#elif defined(__CYGWIN__)
|
||||
"libOSMesa-8.so",
|
||||
#else
|
||||
"libOSMesa.so.8",
|
||||
"libOSMesa.so.6",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
if (_glfw.osmesa.handle)
|
||||
return GLFW_TRUE;
|
||||
|
||||
for (i = 0; sonames[i]; i++)
|
||||
{
|
||||
_glfw.osmesa.handle = _glfw_dlopen(sonames[i]);
|
||||
if (_glfw.osmesa.handle)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_glfw.osmesa.handle)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.osmesa.CreateContextExt = (PFNOSMESACREATECONTEXTEXTPROC)
|
||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextExt");
|
||||
_glfw.osmesa.CreateContextAttribs = (PFNOSMESACREATECONTEXTATTRIBSPROC)
|
||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextAttribs");
|
||||
_glfw.osmesa.DestroyContext = (PFNOSMESADESTROYCONTEXTPROC)
|
||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaDestroyContext");
|
||||
_glfw.osmesa.MakeCurrent = (PFNOSMESAMAKECURRENTPROC)
|
||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaMakeCurrent");
|
||||
_glfw.osmesa.GetColorBuffer = (PFNOSMESAGETCOLORBUFFERPROC)
|
||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetColorBuffer");
|
||||
_glfw.osmesa.GetDepthBuffer = (PFNOSMESAGETDEPTHBUFFERPROC)
|
||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetDepthBuffer");
|
||||
_glfw.osmesa.GetProcAddress = (PFNOSMESAGETPROCADDRESSPROC)
|
||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetProcAddress");
|
||||
|
||||
if (!_glfw.osmesa.CreateContextExt ||
|
||||
!_glfw.osmesa.DestroyContext ||
|
||||
!_glfw.osmesa.MakeCurrent ||
|
||||
!_glfw.osmesa.GetColorBuffer ||
|
||||
!_glfw.osmesa.GetDepthBuffer ||
|
||||
!_glfw.osmesa.GetProcAddress)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"OSMesa: Failed to load required entry points");
|
||||
|
||||
_glfwTerminateOSMesa();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwTerminateOSMesa(void)
|
||||
{
|
||||
if (_glfw.osmesa.handle)
|
||||
{
|
||||
_glfw_dlclose(_glfw.osmesa.handle);
|
||||
_glfw.osmesa.handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define setAttrib(attribName, attribValue) \
|
||||
{ \
|
||||
attribs[index++] = attribName; \
|
||||
attribs[index++] = attribValue; \
|
||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
}
|
||||
|
||||
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
OSMesaContext share = NULL;
|
||||
const int accumBits = fbconfig->accumRedBits +
|
||||
fbconfig->accumGreenBits +
|
||||
fbconfig->accumBlueBits +
|
||||
fbconfig->accumAlphaBits;
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"OSMesa: OpenGL ES is not available on OSMesa");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (ctxconfig->share)
|
||||
share = ctxconfig->share->context.osmesa.handle;
|
||||
|
||||
if (OSMesaCreateContextAttribs)
|
||||
{
|
||||
int index = 0, attribs[40];
|
||||
|
||||
setAttrib(OSMESA_FORMAT, OSMESA_RGBA);
|
||||
setAttrib(OSMESA_DEPTH_BITS, fbconfig->depthBits);
|
||||
setAttrib(OSMESA_STENCIL_BITS, fbconfig->stencilBits);
|
||||
setAttrib(OSMESA_ACCUM_BITS, accumBits);
|
||||
|
||||
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
||||
{
|
||||
setAttrib(OSMESA_PROFILE, OSMESA_CORE_PROFILE);
|
||||
}
|
||||
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
||||
{
|
||||
setAttrib(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE);
|
||||
}
|
||||
|
||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||
{
|
||||
setAttrib(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major);
|
||||
setAttrib(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor);
|
||||
}
|
||||
|
||||
if (ctxconfig->forward)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"OSMesa: Foward-compatible contexts not supported");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
setAttrib(0, 0);
|
||||
|
||||
window->context.osmesa.handle =
|
||||
OSMesaCreateContextAttribs(attribs, share);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ctxconfig->profile)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"OSMesa: OpenGL profiles unavailable");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
window->context.osmesa.handle =
|
||||
OSMesaCreateContextExt(OSMESA_RGBA,
|
||||
fbconfig->depthBits,
|
||||
fbconfig->stencilBits,
|
||||
accumBits,
|
||||
share);
|
||||
}
|
||||
|
||||
if (window->context.osmesa.handle == NULL)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"OSMesa: Failed to create context");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
window->context.makeCurrent = makeContextCurrentOSMesa;
|
||||
window->context.swapBuffers = swapBuffersOSMesa;
|
||||
window->context.swapInterval = swapIntervalOSMesa;
|
||||
window->context.extensionSupported = extensionSupportedOSMesa;
|
||||
window->context.getProcAddress = getProcAddressOSMesa;
|
||||
window->context.destroy = destroyContextOSMesa;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
#undef setAttrib
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW native API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
|
||||
int* height, int* format, void** buffer)
|
||||
{
|
||||
void* mesaBuffer;
|
||||
GLint mesaWidth, mesaHeight, mesaFormat;
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
|
||||
if (!OSMesaGetColorBuffer(window->context.osmesa.handle,
|
||||
&mesaWidth, &mesaHeight,
|
||||
&mesaFormat, &mesaBuffer))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"OSMesa: Failed to retrieve color buffer");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (width)
|
||||
*width = mesaWidth;
|
||||
if (height)
|
||||
*height = mesaHeight;
|
||||
if (format)
|
||||
*format = mesaFormat;
|
||||
if (buffer)
|
||||
*buffer = mesaBuffer;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
|
||||
int* width, int* height,
|
||||
int* bytesPerValue,
|
||||
void** buffer)
|
||||
{
|
||||
void* mesaBuffer;
|
||||
GLint mesaWidth, mesaHeight, mesaBytes;
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
|
||||
if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,
|
||||
&mesaWidth, &mesaHeight,
|
||||
&mesaBytes, &mesaBuffer))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"OSMesa: Failed to retrieve depth buffer");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (width)
|
||||
*width = mesaWidth;
|
||||
if (height)
|
||||
*height = mesaHeight;
|
||||
if (bytesPerValue)
|
||||
*bytesPerValue = mesaBytes;
|
||||
if (buffer)
|
||||
*buffer = mesaBuffer;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (window->context.client == GLFW_NO_API)
|
||||
{
|
||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return window->context.osmesa.handle;
|
||||
}
|
||||
|
98
src/osmesa_context.h
Normal file
98
src/osmesa_context.h
Normal file
@ -0,0 +1,98 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OSMesa - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_osmesa_context_h_
|
||||
#define _glfw3_osmesa_context_h_
|
||||
|
||||
#define OSMESA_RGBA 0x1908
|
||||
#define OSMESA_FORMAT 0x22
|
||||
#define OSMESA_DEPTH_BITS 0x30
|
||||
#define OSMESA_STENCIL_BITS 0x31
|
||||
#define OSMESA_ACCUM_BITS 0x32
|
||||
#define OSMESA_PROFILE 0x33
|
||||
#define OSMESA_CORE_PROFILE 0x34
|
||||
#define OSMESA_COMPAT_PROFILE 0x35
|
||||
#define OSMESA_CONTEXT_MAJOR_VERSION 0x36
|
||||
#define OSMESA_CONTEXT_MINOR_VERSION 0x37
|
||||
|
||||
typedef void* OSMesaContext;
|
||||
typedef void (*OSMESAproc)();
|
||||
|
||||
typedef OSMesaContext (* PFNOSMESACREATECONTEXTATTRIBSPROC)(const int*,OSMesaContext);
|
||||
typedef OSMesaContext (* PFNOSMESACREATECONTEXTEXTPROC)(GLenum,GLint,GLint,GLint,OSMesaContext);
|
||||
typedef void (* PFNOSMESADESTROYCONTEXTPROC)(OSMesaContext);
|
||||
typedef int (* PFNOSMESAMAKECURRENTPROC)(OSMesaContext,void*,int,int,int);
|
||||
typedef int (* PFNOSMESAGETCOLORBUFFERPROC)(OSMesaContext,int*,int*,int*,void**);
|
||||
typedef int (* PFNOSMESAGETDEPTHBUFFERPROC)(OSMesaContext,int*,int*,int*,void**);
|
||||
typedef GLFWglproc (* PFNOSMESAGETPROCADDRESSPROC)(const char*);
|
||||
#define OSMesaCreateContextExt _glfw.osmesa.CreateContextExt
|
||||
#define OSMesaCreateContextAttribs _glfw.osmesa.CreateContextAttribs
|
||||
#define OSMesaDestroyContext _glfw.osmesa.DestroyContext
|
||||
#define OSMesaMakeCurrent _glfw.osmesa.MakeCurrent
|
||||
#define OSMesaGetColorBuffer _glfw.osmesa.GetColorBuffer
|
||||
#define OSMesaGetDepthBuffer _glfw.osmesa.GetDepthBuffer
|
||||
#define OSMesaGetProcAddress _glfw.osmesa.GetProcAddress
|
||||
|
||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextOSMesa osmesa
|
||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryOSMesa osmesa
|
||||
|
||||
|
||||
// OSMesa-specific per-context data
|
||||
//
|
||||
typedef struct _GLFWcontextOSMesa
|
||||
{
|
||||
OSMesaContext handle;
|
||||
int width;
|
||||
int height;
|
||||
void* buffer;
|
||||
|
||||
} _GLFWcontextOSMesa;
|
||||
|
||||
// OSMesa-specific global data
|
||||
//
|
||||
typedef struct _GLFWlibraryOSMesa
|
||||
{
|
||||
void* handle;
|
||||
|
||||
PFNOSMESACREATECONTEXTEXTPROC CreateContextExt;
|
||||
PFNOSMESACREATECONTEXTATTRIBSPROC CreateContextAttribs;
|
||||
PFNOSMESADESTROYCONTEXTPROC DestroyContext;
|
||||
PFNOSMESAMAKECURRENTPROC MakeCurrent;
|
||||
PFNOSMESAGETCOLORBUFFERPROC GetColorBuffer;
|
||||
PFNOSMESAGETDEPTHBUFFERPROC GetDepthBuffer;
|
||||
PFNOSMESAGETPROCADDRESSPROC GetProcAddress;
|
||||
|
||||
} _GLFWlibraryOSMesa;
|
||||
|
||||
|
||||
GLFWbool _glfwInitOSMesa(void);
|
||||
void _glfwTerminateOSMesa(void);
|
||||
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig);
|
||||
|
||||
#endif // _glfw3_osmesa_context_h_
|
54
src/osmesa_init.c
Normal file
54
src/osmesa_init.c
Normal file
@ -0,0 +1,54 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OSMesa - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformInit(void)
|
||||
{
|
||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfwInitTimerPOSIX();
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformTerminate(void)
|
||||
{
|
||||
_glfwTerminateOSMesa();
|
||||
_glfwTerminateThreadLocalStoragePOSIX();
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetVersionString(void)
|
||||
{
|
||||
return _GLFW_VERSION_NUMBER " none OSMesa";
|
||||
}
|
||||
|
67
src/osmesa_monitor.c
Normal file
67
src/osmesa_monitor.c
Normal file
@ -0,0 +1,67 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OSMesa - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
||||
{
|
||||
// OSMesa is headless, so no monitors
|
||||
*count = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||
{
|
||||
}
|
||||
|
65
src/osmesa_platform.h
Normal file
65
src/osmesa_platform.h
Normal file
@ -0,0 +1,65 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OSMesa - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_osmesa_platform_h_
|
||||
#define _glfw3_osmesa_platform_h_
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowOSMesa osmesa
|
||||
|
||||
#define _GLFW_PLATFORM_MONITOR_STATE
|
||||
#define _GLFW_PLATFORM_CURSOR_STATE
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE
|
||||
#define _GLFW_EGL_CONTEXT_STATE
|
||||
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
|
||||
|
||||
#include "osmesa_context.h"
|
||||
#include "posix_time.h"
|
||||
#include "posix_tls.h"
|
||||
|
||||
#if defined(_GLFW_WIN32)
|
||||
#define _glfw_dlopen(name) LoadLibraryA(name)
|
||||
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
|
||||
#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
|
||||
#else
|
||||
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||
#endif
|
||||
|
||||
// OSMesa-specific per-window data
|
||||
//
|
||||
typedef struct _GLFWwindowOSMesa
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
} _GLFWwindowOSMesa;
|
||||
|
||||
|
||||
#endif // _glfw3_osmesa_platform_h_
|
303
src/osmesa_window.c
Normal file
303
src/osmesa_window.c
Normal file
@ -0,0 +1,303 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OSMesa - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
static int createNativeWindow(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig)
|
||||
{
|
||||
window->osmesa.width = wndconfig->width;
|
||||
window->osmesa.height = wndconfig->height;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
if (!createNativeWindow(window, wndconfig))
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (ctxconfig->client != GLFW_NO_API)
|
||||
{
|
||||
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwInitOSMesa())
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: EGL not available");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (window->context.destroy)
|
||||
window->context.destroy(window);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count,
|
||||
const GLFWimage* images)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
_GLFWmonitor* monitor,
|
||||
int xpos, int ypos,
|
||||
int width, int height,
|
||||
int refreshRate)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
||||
{
|
||||
if (width)
|
||||
*width = window->osmesa.width;
|
||||
if (height)
|
||||
*height = window->osmesa.height;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||
{
|
||||
window->osmesa.width = width;
|
||||
window->osmesa.height = height;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||
int minwidth, int minheight,
|
||||
int maxwidth, int maxheight)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int n, int d)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
|
||||
{
|
||||
if (width)
|
||||
*width = window->osmesa.width;
|
||||
if (height)
|
||||
*height = window->osmesa.height;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||
int* left, int* top,
|
||||
int* right, int* bottom)
|
||||
{
|
||||
if (right)
|
||||
*right = window->osmesa.width;
|
||||
if (bottom)
|
||||
*top = window->osmesa.height;
|
||||
}
|
||||
|
||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
void _glfwPlatformPollEvents(void)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformWaitEvents(void)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformPostEmptyEvent(void)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformApplyCursorMode(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
{
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||
{
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
||||
{
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetKeyName(int key, int scancode)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int _glfwPlatformGetKeyScancode(int key)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _glfwPlatformJoystickPresent(int joy)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetJoystickName(int joy)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
{
|
||||
}
|
||||
|
||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
_GLFWwindow* window,
|
||||
const VkAllocationCallbacks* allocator,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
// This seems like the most appropriate error to return here
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
73
src/vulkan.c
73
src/vulkan.c
@ -31,37 +31,54 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define _GLFW_FIND_LOADER 1
|
||||
#define _GLFW_REQUIRE_LOADER 2
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwInitVulkan(void)
|
||||
GLFWbool _glfwInitVulkan(int mode)
|
||||
{
|
||||
VkResult err;
|
||||
VkExtensionProperties* ep;
|
||||
uint32_t i, count;
|
||||
|
||||
#if !defined(_GLFW_VULKAN_STATIC)
|
||||
#if defined(_GLFW_WIN32)
|
||||
const char* name = "vulkan-1.dll";
|
||||
#else
|
||||
const char* name = "libvulkan.so.1";
|
||||
#endif
|
||||
|
||||
if (_glfw.vk.available)
|
||||
return GLFW_TRUE;
|
||||
|
||||
_glfw.vk.handle = _glfw_dlopen(name);
|
||||
#if !defined(_GLFW_VULKAN_STATIC)
|
||||
#if defined(_GLFW_WIN32)
|
||||
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
|
||||
#elif defined(_GLFW_COCOA)
|
||||
// NULL maps to RTLD_DEFAULT, which searches all loaded binaries
|
||||
_glfw.vk.handle = _glfw_dlopen(NULL);
|
||||
#else
|
||||
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
|
||||
#endif
|
||||
if (!_glfw.vk.handle)
|
||||
{
|
||||
if (mode == _GLFW_REQUIRE_LOADER)
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
|
||||
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
|
||||
_glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
|
||||
if (!_glfw.vk.GetInstanceProcAddr)
|
||||
{
|
||||
#if defined(_GLFW_COCOA)
|
||||
if (mode == _GLFW_REQUIRE_LOADER)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: vkGetInstanceProcAddr not found in process");
|
||||
}
|
||||
#else
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: Loader does not export vkGetInstanceProcAddr");
|
||||
#endif
|
||||
|
||||
_glfwTerminateVulkan();
|
||||
return GLFW_FALSE;
|
||||
@ -111,6 +128,9 @@ GLFWbool _glfwInitVulkan(void)
|
||||
#if defined(_GLFW_WIN32)
|
||||
else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
|
||||
_glfw.vk.KHR_win32_surface = GLFW_TRUE;
|
||||
#elif defined(_GLFW_COCOA)
|
||||
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
|
||||
_glfw.vk.MVK_macos_surface = GLFW_TRUE;
|
||||
#elif defined(_GLFW_X11)
|
||||
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
|
||||
_glfw.vk.KHR_xlib_surface = GLFW_TRUE;
|
||||
@ -136,8 +156,10 @@ GLFWbool _glfwInitVulkan(void)
|
||||
|
||||
void _glfwTerminateVulkan(void)
|
||||
{
|
||||
#if !defined(_GLFW_VULKAN_STATIC)
|
||||
if (_glfw.vk.handle)
|
||||
_glfw_dlclose(_glfw.vk.handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* _glfwGetVulkanResultString(VkResult result)
|
||||
@ -203,7 +225,7 @@ const char* _glfwGetVulkanResultString(VkResult result)
|
||||
GLFWAPI int glfwVulkanSupported(void)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
return _glfwInitVulkan();
|
||||
return _glfwInitVulkan(_GLFW_FIND_LOADER);
|
||||
}
|
||||
|
||||
GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
|
||||
@ -212,11 +234,11 @@ GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (!_glfwInitVulkan())
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
|
||||
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||
return NULL;
|
||||
|
||||
if (!_glfw.vk.extensions[0])
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*count = 2;
|
||||
return (const char**) _glfw.vk.extensions;
|
||||
@ -229,15 +251,20 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (!_glfwInitVulkan())
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
|
||||
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
|
||||
#if defined(_GLFW_VULKAN_STATIC)
|
||||
if (!proc)
|
||||
{
|
||||
if (strcmp(procname, "vkGetInstanceProcAddr") == 0)
|
||||
return (GLFWvkproc) vkGetInstanceProcAddr;
|
||||
}
|
||||
#else
|
||||
if (!proc)
|
||||
proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
|
||||
#endif
|
||||
|
||||
return proc;
|
||||
}
|
||||
@ -248,11 +275,8 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
|
||||
if (!_glfwInitVulkan())
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
|
||||
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!_glfw.vk.extensions[0])
|
||||
{
|
||||
@ -279,11 +303,8 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
|
||||
|
||||
if (!_glfwInitVulkan())
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
|
||||
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
if (!_glfw.vk.extensions[0])
|
||||
{
|
||||
|
@ -304,6 +304,7 @@ static void createKeyTables(void)
|
||||
//
|
||||
static HWND createHelperWindow(void)
|
||||
{
|
||||
MSG msg;
|
||||
HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
|
||||
_GLFW_WNDCLASSNAME,
|
||||
L"GLFW helper window",
|
||||
@ -336,6 +337,12 @@ static HWND createHelperWindow(void)
|
||||
DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||
}
|
||||
|
||||
while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
@ -423,8 +430,6 @@ int _glfwPlatformInit(void)
|
||||
if (!_glfw.win32.helperWindowHandle)
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfwPlatformPollEvents();
|
||||
|
||||
_glfwInitTimerWin32();
|
||||
_glfwInitJoysticksWin32();
|
||||
|
||||
|
@ -332,26 +332,26 @@ static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
|
||||
//
|
||||
static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
{
|
||||
int joy = 0;
|
||||
int jid = 0;
|
||||
DIDEVCAPS dc;
|
||||
DIPROPDWORD dipd;
|
||||
IDirectInputDevice8* device;
|
||||
_GLFWobjenumWin32 data;
|
||||
_GLFWjoystickWin32* js;
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (memcmp(&_glfw.win32_js[joy].guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||
if (memcmp(&_glfw.win32_js[jid].guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (!_glfw.win32_js[joy].present)
|
||||
if (!_glfw.win32_js[jid].present)
|
||||
break;
|
||||
}
|
||||
|
||||
if (joy > GLFW_JOYSTICK_LAST)
|
||||
if (jid > GLFW_JOYSTICK_LAST)
|
||||
return DIENUM_STOP;
|
||||
|
||||
if (supportsXInput(&di->guidProduct))
|
||||
@ -362,14 +362,14 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
&device,
|
||||
NULL)))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "DI: Failed to create device");
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create device");
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"DI: Failed to set device data format");
|
||||
"Win32: Failed to set device data format");
|
||||
|
||||
IDirectInputDevice8_Release(device);
|
||||
return DIENUM_CONTINUE;
|
||||
@ -381,7 +381,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
if (FAILED(IDirectInputDevice8_GetCapabilities(device, &dc)))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"DI: Failed to query device capabilities");
|
||||
"Win32: Failed to query device capabilities");
|
||||
|
||||
IDirectInputDevice8_Release(device);
|
||||
return DIENUM_CONTINUE;
|
||||
@ -398,7 +398,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
&dipd.diph)))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"DI: Failed to set device axis mode");
|
||||
"Win32: Failed to set device axis mode");
|
||||
|
||||
IDirectInputDevice8_Release(device);
|
||||
return DIENUM_CONTINUE;
|
||||
@ -415,7 +415,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"DI: Failed to enumerate device objects");
|
||||
"Win32: Failed to enumerate device objects");
|
||||
|
||||
IDirectInputDevice8_Release(device);
|
||||
free(data.objects);
|
||||
@ -426,7 +426,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
sizeof(_GLFWjoyobjectWin32),
|
||||
compareJoystickObjects);
|
||||
|
||||
js = _glfw.win32_js + joy;
|
||||
js = _glfw.win32_js + jid;
|
||||
js->device = device;
|
||||
js->guid = di->guidInstance;
|
||||
js->axisCount = data.axisCount + data.sliderCount;
|
||||
@ -438,7 +438,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
js->name = _glfwCreateUTF8FromWideStringWin32(di->tszInstanceName);
|
||||
js->present = GLFW_TRUE;
|
||||
|
||||
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
||||
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
@ -447,33 +447,33 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
//
|
||||
static GLFWbool openXinputDevice(DWORD index)
|
||||
{
|
||||
int joy;
|
||||
int jid;
|
||||
XINPUT_CAPABILITIES xic;
|
||||
_GLFWjoystickWin32* js;
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (_glfw.win32_js[joy].present &&
|
||||
_glfw.win32_js[joy].device == NULL &&
|
||||
_glfw.win32_js[joy].index == index)
|
||||
if (_glfw.win32_js[jid].present &&
|
||||
_glfw.win32_js[jid].device == NULL &&
|
||||
_glfw.win32_js[jid].index == index)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (!_glfw.win32_js[joy].present)
|
||||
if (!_glfw.win32_js[jid].present)
|
||||
break;
|
||||
}
|
||||
|
||||
if (joy > GLFW_JOYSTICK_LAST)
|
||||
if (jid > GLFW_JOYSTICK_LAST)
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (_glfw_XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
||||
return GLFW_FALSE;
|
||||
|
||||
js = _glfw.win32_js + joy;
|
||||
js = _glfw.win32_js + jid;
|
||||
js->axisCount = 6;
|
||||
js->axes = calloc(js->axisCount, sizeof(float));
|
||||
js->buttonCount = 14;
|
||||
@ -482,7 +482,7 @@ static GLFWbool openXinputDevice(DWORD index)
|
||||
js->name = strdup(getDeviceDescription(&xic));
|
||||
js->index = index;
|
||||
|
||||
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
||||
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
@ -664,7 +664,7 @@ void _glfwInitJoysticksWin32(void)
|
||||
NULL)))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"DI: Failed to create interface");
|
||||
"Win32: Failed to create interface");
|
||||
}
|
||||
}
|
||||
|
||||
@ -675,10 +675,10 @@ void _glfwInitJoysticksWin32(void)
|
||||
//
|
||||
void _glfwTerminateJoysticksWin32(void)
|
||||
{
|
||||
int joy;
|
||||
int jid;
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
closeJoystick(_glfw.win32_js + joy);
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
closeJoystick(_glfw.win32_js + jid);
|
||||
|
||||
if (_glfw.win32.dinput8.api)
|
||||
IDirectInput8_Release(_glfw.win32.dinput8.api);
|
||||
@ -715,10 +715,10 @@ void _glfwDetectJoystickConnectionWin32(void)
|
||||
//
|
||||
void _glfwDetectJoystickDisconnectionWin32(void)
|
||||
{
|
||||
int joy;
|
||||
int jid;
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
pollJoystickState(_glfw.win32_js + joy, _GLFW_PRESENCE_ONLY);
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
pollJoystickState(_glfw.win32_js + jid, _GLFW_PRESENCE_ONLY);
|
||||
}
|
||||
|
||||
|
||||
@ -726,15 +726,15 @@ void _glfwDetectJoystickDisconnectionWin32(void)
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformJoystickPresent(int joy)
|
||||
int _glfwPlatformJoystickPresent(int jid)
|
||||
{
|
||||
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||
_GLFWjoystickWin32* js = _glfw.win32_js + jid;
|
||||
return pollJoystickState(js, _GLFW_PRESENCE_ONLY);
|
||||
}
|
||||
|
||||
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||
const float* _glfwPlatformGetJoystickAxes(int jid, int* count)
|
||||
{
|
||||
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||
_GLFWjoystickWin32* js = _glfw.win32_js + jid;
|
||||
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
|
||||
return NULL;
|
||||
|
||||
@ -742,9 +742,9 @@ const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||
return js->axes;
|
||||
}
|
||||
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int jid, int* count)
|
||||
{
|
||||
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||
_GLFWjoystickWin32* js = _glfw.win32_js + jid;
|
||||
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
|
||||
return NULL;
|
||||
|
||||
@ -752,9 +752,9 @@ const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||
return js->buttons;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetJoystickName(int joy)
|
||||
const char* _glfwPlatformGetJoystickName(int jid)
|
||||
{
|
||||
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||
_GLFWjoystickWin32* js = _glfw.win32_js + jid;
|
||||
if (!pollJoystickState(js, _GLFW_PRESENCE_ONLY))
|
||||
return NULL;
|
||||
|
||||
|
@ -668,7 +668,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
case WM_MOUSEHWHEEL:
|
||||
{
|
||||
// This message is only sent on Windows Vista and later
|
||||
// NOTE: The X-axis is inverted for consistency with OS X and X11.
|
||||
// NOTE: The X-axis is inverted for consistency with macOS and X11
|
||||
_glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);
|
||||
return 0;
|
||||
}
|
||||
|
138
src/wl_init.c
138
src/wl_init.c
@ -128,7 +128,7 @@ static void pointerHandleAxis(void* data,
|
||||
wl_fixed_t value)
|
||||
{
|
||||
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
||||
double scroll_factor;
|
||||
double scrollFactor;
|
||||
double x, y;
|
||||
|
||||
if (!window)
|
||||
@ -137,17 +137,17 @@ static void pointerHandleAxis(void* data,
|
||||
/* Wayland scroll events are in pointer motion coordinate space (think
|
||||
* two finger scroll). The factor 10 is commonly used to convert to
|
||||
* "scroll step means 1.0. */
|
||||
scroll_factor = 1.0/10.0;
|
||||
scrollFactor = 1.0/10.0;
|
||||
|
||||
switch (axis)
|
||||
{
|
||||
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
|
||||
x = wl_fixed_to_double(value) * scroll_factor;
|
||||
x = wl_fixed_to_double(value) * scrollFactor;
|
||||
y = 0.0;
|
||||
break;
|
||||
case WL_POINTER_AXIS_VERTICAL_SCROLL:
|
||||
x = 0.0;
|
||||
y = wl_fixed_to_double(value) * scroll_factor;
|
||||
y = wl_fixed_to_double(value) * scrollFactor;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -172,7 +172,10 @@ static void keyboardHandleKeymap(void* data,
|
||||
{
|
||||
struct xkb_keymap* keymap;
|
||||
struct xkb_state* state;
|
||||
struct xkb_compose_table* composeTable;
|
||||
struct xkb_compose_state* composeState;
|
||||
char* mapStr;
|
||||
const char* locale;
|
||||
|
||||
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
|
||||
{
|
||||
@ -186,10 +189,10 @@ static void keyboardHandleKeymap(void* data,
|
||||
return;
|
||||
}
|
||||
|
||||
keymap = xkb_map_new_from_string(_glfw.wl.xkb.context,
|
||||
mapStr,
|
||||
XKB_KEYMAP_FORMAT_TEXT_V1,
|
||||
0);
|
||||
keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context,
|
||||
mapStr,
|
||||
XKB_KEYMAP_FORMAT_TEXT_V1,
|
||||
0);
|
||||
munmap(mapStr, size);
|
||||
close(fd);
|
||||
|
||||
@ -205,23 +208,52 @@ static void keyboardHandleKeymap(void* data,
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Failed to create XKB state");
|
||||
xkb_map_unref(keymap);
|
||||
xkb_keymap_unref(keymap);
|
||||
return;
|
||||
}
|
||||
|
||||
// Look up the preferred locale, falling back to "C" as default.
|
||||
locale = getenv("LC_ALL");
|
||||
if (!locale)
|
||||
locale = getenv("LC_CTYPE");
|
||||
if (!locale)
|
||||
locale = getenv("LANG");
|
||||
if (!locale)
|
||||
locale = "C";
|
||||
|
||||
composeTable =
|
||||
xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
|
||||
XKB_COMPOSE_COMPILE_NO_FLAGS);
|
||||
if (composeTable)
|
||||
{
|
||||
composeState =
|
||||
xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
|
||||
xkb_compose_table_unref(composeTable);
|
||||
if (composeState)
|
||||
_glfw.wl.xkb.composeState = composeState;
|
||||
else
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Failed to create XKB compose state");
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Failed to create XKB compose table");
|
||||
}
|
||||
|
||||
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
||||
xkb_state_unref(_glfw.wl.xkb.state);
|
||||
_glfw.wl.xkb.keymap = keymap;
|
||||
_glfw.wl.xkb.state = state;
|
||||
|
||||
_glfw.wl.xkb.control_mask =
|
||||
1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Control");
|
||||
_glfw.wl.xkb.alt_mask =
|
||||
1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
|
||||
_glfw.wl.xkb.shift_mask =
|
||||
1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
|
||||
_glfw.wl.xkb.super_mask =
|
||||
1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
|
||||
_glfw.wl.xkb.controlMask =
|
||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control");
|
||||
_glfw.wl.xkb.altMask =
|
||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
|
||||
_glfw.wl.xkb.shiftMask =
|
||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
|
||||
_glfw.wl.xkb.superMask =
|
||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
|
||||
}
|
||||
|
||||
static void keyboardHandleEnter(void* data,
|
||||
@ -258,18 +290,40 @@ static int toGLFWKeyCode(uint32_t key)
|
||||
return GLFW_KEY_UNKNOWN;
|
||||
}
|
||||
|
||||
static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
||||
{
|
||||
if (sym == XKB_KEY_NoSymbol)
|
||||
return sym;
|
||||
if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)
|
||||
!= XKB_COMPOSE_FEED_ACCEPTED)
|
||||
return sym;
|
||||
switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState))
|
||||
{
|
||||
case XKB_COMPOSE_COMPOSED:
|
||||
return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState);
|
||||
case XKB_COMPOSE_COMPOSING:
|
||||
case XKB_COMPOSE_CANCELLED:
|
||||
return XKB_KEY_NoSymbol;
|
||||
case XKB_COMPOSE_NOTHING:
|
||||
default:
|
||||
return sym;
|
||||
}
|
||||
}
|
||||
|
||||
static void inputChar(_GLFWwindow* window, uint32_t key)
|
||||
{
|
||||
uint32_t code, num_syms;
|
||||
uint32_t code, numSyms;
|
||||
long cp;
|
||||
const xkb_keysym_t *syms;
|
||||
xkb_keysym_t sym;
|
||||
|
||||
code = key + 8;
|
||||
num_syms = xkb_key_get_syms(_glfw.wl.xkb.state, code, &syms);
|
||||
numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms);
|
||||
|
||||
if (num_syms == 1)
|
||||
if (numSyms == 1)
|
||||
{
|
||||
cp = _glfwKeySym2Unicode(syms[0]);
|
||||
sym = composeSymbol(syms[0]);
|
||||
cp = _glfwKeySym2Unicode(sym);
|
||||
if (cp != -1)
|
||||
{
|
||||
const int mods = _glfw.wl.xkb.modifiers;
|
||||
@ -327,15 +381,17 @@ static void keyboardHandleModifiers(void* data,
|
||||
group);
|
||||
|
||||
mask = xkb_state_serialize_mods(_glfw.wl.xkb.state,
|
||||
XKB_STATE_DEPRESSED |
|
||||
XKB_STATE_LATCHED);
|
||||
if (mask & _glfw.wl.xkb.control_mask)
|
||||
XKB_STATE_MODS_DEPRESSED |
|
||||
XKB_STATE_LAYOUT_DEPRESSED |
|
||||
XKB_STATE_MODS_LATCHED |
|
||||
XKB_STATE_LAYOUT_LATCHED);
|
||||
if (mask & _glfw.wl.xkb.controlMask)
|
||||
modifiers |= GLFW_MOD_CONTROL;
|
||||
if (mask & _glfw.wl.xkb.alt_mask)
|
||||
if (mask & _glfw.wl.xkb.altMask)
|
||||
modifiers |= GLFW_MOD_ALT;
|
||||
if (mask & _glfw.wl.xkb.shift_mask)
|
||||
if (mask & _glfw.wl.xkb.shiftMask)
|
||||
modifiers |= GLFW_MOD_SHIFT;
|
||||
if (mask & _glfw.wl.xkb.super_mask)
|
||||
if (mask & _glfw.wl.xkb.superMask)
|
||||
modifiers |= GLFW_MOD_SUPER;
|
||||
_glfw.wl.xkb.modifiers = modifiers;
|
||||
}
|
||||
@ -387,10 +443,10 @@ static void registryHandleGlobal(void* data,
|
||||
{
|
||||
if (strcmp(interface, "wl_compositor") == 0)
|
||||
{
|
||||
_glfw.wl.wl_compositor_version = min(3, version);
|
||||
_glfw.wl.compositorVersion = min(3, version);
|
||||
_glfw.wl.compositor =
|
||||
wl_registry_bind(registry, name, &wl_compositor_interface,
|
||||
_glfw.wl.wl_compositor_version);
|
||||
_glfw.wl.compositorVersion);
|
||||
}
|
||||
else if (strcmp(interface, "wl_shm") == 0)
|
||||
{
|
||||
@ -643,16 +699,38 @@ void _glfwPlatformTerminate(void)
|
||||
_glfwTerminateJoysticksLinux();
|
||||
_glfwTerminateThreadLocalStoragePOSIX();
|
||||
|
||||
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
|
||||
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
||||
xkb_state_unref(_glfw.wl.xkb.state);
|
||||
xkb_context_unref(_glfw.wl.xkb.context);
|
||||
|
||||
if (_glfw.wl.cursorTheme)
|
||||
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
|
||||
if (_glfw.wl.cursorSurface)
|
||||
wl_surface_destroy(_glfw.wl.cursorSurface);
|
||||
if (_glfw.wl.compositor)
|
||||
wl_compositor_destroy(_glfw.wl.compositor);
|
||||
if (_glfw.wl.shm)
|
||||
wl_shm_destroy(_glfw.wl.shm);
|
||||
if (_glfw.wl.shell)
|
||||
wl_shell_destroy(_glfw.wl.shell);
|
||||
if (_glfw.wl.pointer)
|
||||
wl_pointer_destroy(_glfw.wl.pointer);
|
||||
if (_glfw.wl.keyboard)
|
||||
wl_keyboard_destroy(_glfw.wl.keyboard);
|
||||
if (_glfw.wl.seat)
|
||||
wl_seat_destroy(_glfw.wl.seat);
|
||||
if (_glfw.wl.relativePointerManager)
|
||||
zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager);
|
||||
if (_glfw.wl.pointerConstraints)
|
||||
zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints);
|
||||
if (_glfw.wl.registry)
|
||||
wl_registry_destroy(_glfw.wl.registry);
|
||||
if (_glfw.wl.display)
|
||||
{
|
||||
wl_display_flush(_glfw.wl.display);
|
||||
if (_glfw.wl.display)
|
||||
wl_display_disconnect(_glfw.wl.display);
|
||||
}
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetVersionString(void)
|
||||
|
@ -50,11 +50,21 @@ static void geometry(void* data,
|
||||
int32_t transform)
|
||||
{
|
||||
struct _GLFWmonitor *monitor = data;
|
||||
char* name;
|
||||
size_t nameLength;
|
||||
|
||||
monitor->wl.x = x;
|
||||
monitor->wl.y = y;
|
||||
monitor->widthMM = physicalWidth;
|
||||
monitor->heightMM = physicalHeight;
|
||||
|
||||
nameLength = strlen(make) + 1 + strlen(model) + 1;
|
||||
name = realloc(monitor->name, nameLength);
|
||||
if (name)
|
||||
{
|
||||
sprintf(name, "%s %s", make, model);
|
||||
monitor->name = name;
|
||||
}
|
||||
}
|
||||
|
||||
static void mode(void* data,
|
||||
@ -102,7 +112,7 @@ static void scale(void* data,
|
||||
monitor->wl.scale = factor;
|
||||
}
|
||||
|
||||
static const struct wl_output_listener output_listener = {
|
||||
static const struct wl_output_listener outputListener = {
|
||||
geometry,
|
||||
mode,
|
||||
done,
|
||||
@ -118,10 +128,6 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
|
||||
{
|
||||
_GLFWmonitor *monitor;
|
||||
struct wl_output *output;
|
||||
char name_str[80];
|
||||
|
||||
memset(name_str, 0, sizeof(name_str));
|
||||
snprintf(name_str, 79, "wl_output@%u", name);
|
||||
|
||||
if (version < 2)
|
||||
{
|
||||
@ -130,7 +136,8 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
|
||||
return;
|
||||
}
|
||||
|
||||
monitor = _glfwAllocMonitor(name_str, 0, 0);
|
||||
// The actual name of this output will be set in the geometry handler.
|
||||
monitor = _glfwAllocMonitor(NULL, 0, 0);
|
||||
|
||||
output = wl_registry_bind(_glfw.wl.registry,
|
||||
name,
|
||||
@ -148,7 +155,7 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
|
||||
monitor->wl.scale = 1;
|
||||
|
||||
monitor->wl.output = output;
|
||||
wl_output_add_listener(output, &output_listener, monitor);
|
||||
wl_output_add_listener(output, &outputListener, monitor);
|
||||
|
||||
if (_glfw.wl.monitorsCount + 1 >= _glfw.wl.monitorsSize)
|
||||
{
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-compose.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
|
||||
@ -83,7 +84,7 @@ typedef struct _GLFWwindowWayland
|
||||
GLFWbool maximized;
|
||||
struct wl_surface* surface;
|
||||
struct wl_egl_window* native;
|
||||
struct wl_shell_surface* shell_surface;
|
||||
struct wl_shell_surface* shellSurface;
|
||||
struct wl_callback* callback;
|
||||
|
||||
_GLFWcursor* currentCursor;
|
||||
@ -119,7 +120,7 @@ typedef struct _GLFWlibraryWayland
|
||||
struct zwp_relative_pointer_manager_v1* relativePointerManager;
|
||||
struct zwp_pointer_constraints_v1* pointerConstraints;
|
||||
|
||||
int wl_compositor_version;
|
||||
int compositorVersion;
|
||||
|
||||
struct wl_cursor_theme* cursorTheme;
|
||||
struct wl_surface* cursorSurface;
|
||||
@ -136,10 +137,11 @@ typedef struct _GLFWlibraryWayland
|
||||
struct xkb_context* context;
|
||||
struct xkb_keymap* keymap;
|
||||
struct xkb_state* state;
|
||||
xkb_mod_mask_t control_mask;
|
||||
xkb_mod_mask_t alt_mask;
|
||||
xkb_mod_mask_t shift_mask;
|
||||
xkb_mod_mask_t super_mask;
|
||||
struct xkb_compose_state* composeState;
|
||||
xkb_mod_mask_t controlMask;
|
||||
xkb_mod_mask_t altMask;
|
||||
xkb_mod_mask_t shiftMask;
|
||||
xkb_mod_mask_t superMask;
|
||||
unsigned int modifiers;
|
||||
} xkb;
|
||||
|
||||
|
@ -105,7 +105,7 @@ static void checkScaleChange(_GLFWwindow* window)
|
||||
int monitorScale;
|
||||
|
||||
// Check if we will be able to set the buffer scale or not.
|
||||
if (_glfw.wl.wl_compositor_version < 3)
|
||||
if (_glfw.wl.compositorVersion < 3)
|
||||
return;
|
||||
|
||||
// Get the scale factor from the highest scale monitor.
|
||||
@ -220,33 +220,33 @@ static GLFWbool createSurface(_GLFWwindow* window,
|
||||
|
||||
static GLFWbool createShellSurface(_GLFWwindow* window)
|
||||
{
|
||||
window->wl.shell_surface = wl_shell_get_shell_surface(_glfw.wl.shell,
|
||||
window->wl.surface);
|
||||
if (!window->wl.shell_surface)
|
||||
window->wl.shellSurface = wl_shell_get_shell_surface(_glfw.wl.shell,
|
||||
window->wl.surface);
|
||||
if (!window->wl.shellSurface)
|
||||
return GLFW_FALSE;
|
||||
|
||||
wl_shell_surface_add_listener(window->wl.shell_surface,
|
||||
wl_shell_surface_add_listener(window->wl.shellSurface,
|
||||
&shellSurfaceListener,
|
||||
window);
|
||||
|
||||
if (window->wl.title)
|
||||
wl_shell_surface_set_title(window->wl.shell_surface, window->wl.title);
|
||||
wl_shell_surface_set_title(window->wl.shellSurface, window->wl.title);
|
||||
|
||||
if (window->monitor)
|
||||
{
|
||||
wl_shell_surface_set_fullscreen(
|
||||
window->wl.shell_surface,
|
||||
window->wl.shellSurface,
|
||||
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
|
||||
0,
|
||||
window->monitor->wl.output);
|
||||
}
|
||||
else if (window->wl.maximized)
|
||||
{
|
||||
wl_shell_surface_set_maximized(window->wl.shell_surface, NULL);
|
||||
wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_shell_surface_set_toplevel(window->wl.shell_surface);
|
||||
wl_shell_surface_set_toplevel(window->wl.shellSurface);
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
@ -411,7 +411,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
}
|
||||
else
|
||||
{
|
||||
window->wl.shell_surface = NULL;
|
||||
window->wl.shellSurface = NULL;
|
||||
window->wl.visible = GLFW_FALSE;
|
||||
}
|
||||
|
||||
@ -443,8 +443,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
if (window->wl.native)
|
||||
wl_egl_window_destroy(window->wl.native);
|
||||
|
||||
if (window->wl.shell_surface)
|
||||
wl_shell_surface_destroy(window->wl.shell_surface);
|
||||
if (window->wl.shellSurface)
|
||||
wl_shell_surface_destroy(window->wl.shellSurface);
|
||||
|
||||
if (window->wl.surface)
|
||||
wl_surface_destroy(window->wl.surface);
|
||||
@ -458,8 +458,8 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||
if (window->wl.title)
|
||||
free(window->wl.title);
|
||||
window->wl.title = strdup(title);
|
||||
if (window->wl.shell_surface)
|
||||
wl_shell_surface_set_title(window->wl.shell_surface, title);
|
||||
if (window->wl.shellSurface)
|
||||
wl_shell_surface_set_title(window->wl.shellSurface, title);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
||||
@ -546,8 +546,8 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
||||
// TODO: also do the same for iconified.
|
||||
if (window->monitor || window->wl.maximized)
|
||||
{
|
||||
if (window->wl.shell_surface)
|
||||
wl_shell_surface_set_toplevel(window->wl.shell_surface);
|
||||
if (window->wl.shellSurface)
|
||||
wl_shell_surface_set_toplevel(window->wl.shellSurface);
|
||||
|
||||
window->wl.maximized = GLFW_FALSE;
|
||||
}
|
||||
@ -557,10 +557,10 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (!window->monitor && !window->wl.maximized)
|
||||
{
|
||||
if (window->wl.shell_surface)
|
||||
if (window->wl.shellSurface)
|
||||
{
|
||||
// Let the compositor select the best output.
|
||||
wl_shell_surface_set_maximized(window->wl.shell_surface, NULL);
|
||||
wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
|
||||
}
|
||||
window->wl.maximized = GLFW_TRUE;
|
||||
}
|
||||
@ -570,7 +570,7 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (!window->monitor)
|
||||
{
|
||||
if (!window->wl.shell_surface)
|
||||
if (!window->wl.shellSurface)
|
||||
createShellSurface(window);
|
||||
window->wl.visible = GLFW_TRUE;
|
||||
}
|
||||
@ -580,8 +580,8 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (!window->monitor)
|
||||
{
|
||||
if (window->wl.shell_surface)
|
||||
wl_shell_surface_destroy(window->wl.shell_surface);
|
||||
if (window->wl.shellSurface)
|
||||
wl_shell_surface_destroy(window->wl.shellSurface);
|
||||
window->wl.visible = GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
@ -601,14 +601,14 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
if (monitor)
|
||||
{
|
||||
wl_shell_surface_set_fullscreen(
|
||||
window->wl.shell_surface,
|
||||
window->wl.shellSurface,
|
||||
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
|
||||
refreshRate * 1000, // Convert Hz to mHz.
|
||||
monitor->wl.output);
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_shell_surface_set_toplevel(window->wl.shell_surface);
|
||||
wl_shell_surface_set_toplevel(window->wl.shellSurface);
|
||||
}
|
||||
_glfwInputWindowMonitorChange(window, monitor);
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ if (VULKAN_FOUND)
|
||||
add_executable(vulkan WIN32 vulkan.c ${ICON})
|
||||
target_include_directories(vulkan PRIVATE "${VULKAN_INCLUDE_DIR}")
|
||||
if (NOT GLFW_VULKAN_STATIC)
|
||||
target_link_libraries(vulkan "${VULKAN_LIBRARY}")
|
||||
target_link_libraries(vulkan "${VULKAN_LIBRARY}" ${GLFW_VULKAN_DEPS})
|
||||
endif()
|
||||
list(APPEND WINDOWS_BINARIES vulkan)
|
||||
endif()
|
||||
|
@ -459,26 +459,26 @@ static void monitor_callback(GLFWmonitor* monitor, int event)
|
||||
}
|
||||
}
|
||||
|
||||
static void joystick_callback(int joy, int event)
|
||||
static void joystick_callback(int jid, int event)
|
||||
{
|
||||
if (event == GLFW_CONNECTED)
|
||||
{
|
||||
int axisCount, buttonCount;
|
||||
|
||||
glfwGetJoystickAxes(joy, &axisCount);
|
||||
glfwGetJoystickButtons(joy, &buttonCount);
|
||||
glfwGetJoystickAxes(jid, &axisCount);
|
||||
glfwGetJoystickButtons(jid, &buttonCount);
|
||||
|
||||
printf("%08x at %0.3f: Joystick %i (%s) was connected with %i axes and %i buttons\n",
|
||||
counter++, glfwGetTime(),
|
||||
joy,
|
||||
glfwGetJoystickName(joy),
|
||||
jid,
|
||||
glfwGetJoystickName(jid),
|
||||
axisCount,
|
||||
buttonCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%08x at %0.3f: Joystick %i was disconnected\n",
|
||||
counter++, glfwGetTime(), joy);
|
||||
counter++, glfwGetTime(), jid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,8 +46,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int windowed_xpos, windowed_ypos, windowed_width, windowed_height;
|
||||
|
||||
static void error_callback(int error, const char* description)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", description);
|
||||
|
@ -820,9 +820,14 @@ int main(int argc, char** argv)
|
||||
re = glfwGetRequiredInstanceExtensions(&re_count);
|
||||
|
||||
printf("Vulkan required instance extensions:");
|
||||
for (i = 0; i < re_count; i++)
|
||||
printf(" %s", re[i]);
|
||||
putchar('\n');
|
||||
if (re)
|
||||
{
|
||||
for (i = 0; i < re_count; i++)
|
||||
printf(" %s", re[i]);
|
||||
putchar('\n');
|
||||
}
|
||||
else
|
||||
printf(" missing\n");
|
||||
|
||||
if (list_extensions)
|
||||
list_vulkan_instance_extensions();
|
||||
|
@ -60,17 +60,17 @@ static void error_callback(int error, const char* description)
|
||||
fprintf(stderr, "Error: %s\n", description);
|
||||
}
|
||||
|
||||
static void joystick_callback(int joy, int event)
|
||||
static void joystick_callback(int jid, int event)
|
||||
{
|
||||
if (event == GLFW_CONNECTED)
|
||||
joysticks[joystick_count++] = joy;
|
||||
joysticks[joystick_count++] = jid;
|
||||
else if (event == GLFW_DISCONNECTED)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < joystick_count; i++)
|
||||
{
|
||||
if (joysticks[i] == joy)
|
||||
if (joysticks[i] == jid)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ static const char* joystick_label(int jid)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int joy;
|
||||
int jid;
|
||||
GLFWwindow* window;
|
||||
struct nk_context* nk;
|
||||
struct nk_font_atlas* atlas;
|
||||
@ -102,10 +102,10 @@ int main(void)
|
||||
if (!glfwInit())
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (glfwJoystickPresent(joy))
|
||||
joystick_callback(joy, GLFW_CONNECTED);
|
||||
if (glfwJoystickPresent(jid))
|
||||
joystick_callback(jid, GLFW_CONNECTED);
|
||||
}
|
||||
|
||||
glfwSetJoystickCallback(joystick_callback);
|
||||
|
@ -52,6 +52,12 @@ static void error_callback(int error, const char* description)
|
||||
fprintf(stderr, "Error: %s\n", description);
|
||||
}
|
||||
|
||||
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
{
|
||||
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||
}
|
||||
|
||||
static int thread_main(void* data)
|
||||
{
|
||||
const Thread* thread = data;
|
||||
@ -101,6 +107,8 @@ int main(void)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
glfwSetKeyCallback(threads[i].window, key_callback);
|
||||
|
||||
glfwSetWindowPos(threads[i].window, 200 + 250 * i, 200);
|
||||
glfwShowWindow(threads[i].window);
|
||||
}
|
||||
|
531
tests/vulkan.c
531
tests/vulkan.c
@ -3,24 +3,17 @@
|
||||
* Copyright (c) 2015-2016 Valve Corporation
|
||||
* Copyright (c) 2015-2016 LunarG, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and/or associated documentation files (the "Materials"), to
|
||||
* deal in the Materials without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Materials, and to permit persons to whom the Materials are
|
||||
* furnished to do so, subject to the following conditions:
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* The above copyright notice(s) and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Materials.
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
*
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
|
||||
* USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Author: Chia-I Wu <olvaffe@gmail.com>
|
||||
* Author: Cody Northrop <cody@lunarg.com>
|
||||
@ -28,6 +21,8 @@
|
||||
* Author: Ian Elliott <ian@LunarG.com>
|
||||
* Author: Jon Ashburn <jon@lunarg.com>
|
||||
* Author: Piers Daniell <pdaniell@nvidia.com>
|
||||
* Author: Gwan-gyeong Mun <elongbug@gmail.com>
|
||||
* Porter: Camilla Berglund <elmindreda@glfw.org>
|
||||
*/
|
||||
/*
|
||||
* Draw a textured triangle with depth testing. This is written against Intel
|
||||
@ -35,22 +30,24 @@
|
||||
* should. It also does no error checking.
|
||||
*/
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#define _ISOC11_SOURCE /* for aligned_alloc() */
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#define DEMO_TEXTURE_COUNT 1
|
||||
#define VERTEX_BUFFER_BIND_ID 0
|
||||
#define APP_SHORT_NAME "vulkan"
|
||||
#define APP_SHORT_NAME "tri"
|
||||
#define APP_LONG_NAME "The Vulkan Triangle Demo Program"
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
@ -245,39 +242,23 @@ struct texture_object {
|
||||
int32_t tex_width, tex_height;
|
||||
};
|
||||
|
||||
static int validation_error = 0;
|
||||
|
||||
VKAPI_ATTR VkBool32 VKAPI_CALL
|
||||
dbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
|
||||
uint64_t srcObject, size_t location, int32_t msgCode,
|
||||
const char *pLayerPrefix, const char *pMsg, void *pUserData) {
|
||||
char *message = (char *)malloc(strlen(pMsg) + 100);
|
||||
BreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
|
||||
uint64_t srcObject, size_t location, int32_t msgCode,
|
||||
const char *pLayerPrefix, const char *pMsg,
|
||||
void *pUserData) {
|
||||
#ifdef _WIN32
|
||||
DebugBreak();
|
||||
#else
|
||||
raise(SIGTRAP);
|
||||
#endif
|
||||
|
||||
assert(message);
|
||||
|
||||
if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
|
||||
sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode,
|
||||
pMsg);
|
||||
} else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
|
||||
sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode,
|
||||
pMsg);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("%s\n", message);
|
||||
fflush(stdout);
|
||||
free(message);
|
||||
|
||||
/*
|
||||
* false indicates that layer should not bail-out of an
|
||||
* API call that had validation failures. This may mean that the
|
||||
* app dies inside the driver due to invalid parameter(s).
|
||||
* That's what would happen without validation layers, so we'll
|
||||
* keep that behavior here.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef struct _SwapchainBuffers {
|
||||
typedef struct {
|
||||
VkImage image;
|
||||
VkCommandBuffer cmd;
|
||||
VkImageView view;
|
||||
@ -288,20 +269,19 @@ struct demo {
|
||||
VkSurfaceKHR surface;
|
||||
bool use_staging_buffer;
|
||||
|
||||
VkAllocationCallbacks allocator;
|
||||
|
||||
VkInstance inst;
|
||||
VkPhysicalDevice gpu;
|
||||
VkDevice device;
|
||||
VkQueue queue;
|
||||
VkPhysicalDeviceProperties gpu_props;
|
||||
VkPhysicalDeviceFeatures gpu_features;
|
||||
VkQueueFamilyProperties *queue_props;
|
||||
uint32_t graphics_queue_node_index;
|
||||
|
||||
uint32_t enabled_extension_count;
|
||||
uint32_t enabled_layer_count;
|
||||
const char *extension_names[64];
|
||||
char *device_validation_layers[64];
|
||||
const char *enabled_layers[64];
|
||||
|
||||
int width, height;
|
||||
VkFormat format;
|
||||
@ -363,10 +343,14 @@ struct demo {
|
||||
|
||||
VkPhysicalDeviceMemoryProperties memory_properties;
|
||||
|
||||
int32_t curFrame;
|
||||
int32_t frameCount;
|
||||
bool validate;
|
||||
bool use_break;
|
||||
PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallback;
|
||||
PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallback;
|
||||
VkDebugReportCallbackEXT msg_callback;
|
||||
PFN_vkDebugReportMessageEXT DebugReportMessage;
|
||||
|
||||
float depthStencil;
|
||||
float depthIncrement;
|
||||
@ -375,6 +359,40 @@ struct demo {
|
||||
uint32_t queue_count;
|
||||
};
|
||||
|
||||
VKAPI_ATTR VkBool32 VKAPI_CALL
|
||||
dbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
|
||||
uint64_t srcObject, size_t location, int32_t msgCode,
|
||||
const char *pLayerPrefix, const char *pMsg, void *pUserData) {
|
||||
char *message = (char *)malloc(strlen(pMsg) + 100);
|
||||
|
||||
assert(message);
|
||||
|
||||
validation_error = 1;
|
||||
|
||||
if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
|
||||
sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode,
|
||||
pMsg);
|
||||
} else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
|
||||
sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode,
|
||||
pMsg);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("%s\n", message);
|
||||
fflush(stdout);
|
||||
free(message);
|
||||
|
||||
/*
|
||||
* false indicates that layer should not bail-out of an
|
||||
* API call that had validation failures. This may mean that the
|
||||
* app dies inside the driver due to invalid parameter(s).
|
||||
* That's what would happen without validation layers, so we'll
|
||||
* keep that behavior here.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
// Forward declaration:
|
||||
static void demo_resize(struct demo *demo);
|
||||
|
||||
@ -382,9 +400,8 @@ static bool memory_type_from_properties(struct demo *demo, uint32_t typeBits,
|
||||
VkFlags requirements_mask,
|
||||
uint32_t *typeIndex) {
|
||||
uint32_t i;
|
||||
|
||||
// Search memtypes to find first index with those properties
|
||||
for (i = 0; i < 32; i++) {
|
||||
for (i = 0; i < VK_MAX_MEMORY_TYPES; i++) {
|
||||
if ((typeBits & 1) == 1) {
|
||||
// Type is available, does it match user properties?
|
||||
if ((demo->memory_properties.memoryTypes[i].propertyFlags &
|
||||
@ -433,7 +450,9 @@ static void demo_flush_init_cmd(struct demo *demo) {
|
||||
static void demo_set_image_layout(struct demo *demo, VkImage image,
|
||||
VkImageAspectFlags aspectMask,
|
||||
VkImageLayout old_image_layout,
|
||||
VkImageLayout new_image_layout) {
|
||||
VkImageLayout new_image_layout,
|
||||
VkAccessFlagBits srcAccessMask) {
|
||||
|
||||
VkResult U_ASSERT_ONLY err;
|
||||
|
||||
if (demo->setup_cmd == VK_NULL_HANDLE) {
|
||||
@ -448,21 +467,11 @@ static void demo_set_image_layout(struct demo *demo, VkImage image,
|
||||
err = vkAllocateCommandBuffers(demo->device, &cmd, &demo->setup_cmd);
|
||||
assert(!err);
|
||||
|
||||
VkCommandBufferInheritanceInfo cmd_buf_hinfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
|
||||
.pNext = NULL,
|
||||
.renderPass = VK_NULL_HANDLE,
|
||||
.subpass = 0,
|
||||
.framebuffer = VK_NULL_HANDLE,
|
||||
.occlusionQueryEnable = VK_FALSE,
|
||||
.queryFlags = 0,
|
||||
.pipelineStatistics = 0,
|
||||
};
|
||||
VkCommandBufferBeginInfo cmd_buf_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
.pNext = NULL,
|
||||
.flags = 0,
|
||||
.pInheritanceInfo = &cmd_buf_hinfo,
|
||||
.pInheritanceInfo = NULL,
|
||||
};
|
||||
err = vkBeginCommandBuffer(demo->setup_cmd, &cmd_buf_info);
|
||||
assert(!err);
|
||||
@ -471,7 +480,7 @@ static void demo_set_image_layout(struct demo *demo, VkImage image,
|
||||
VkImageMemoryBarrier image_memory_barrier = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = NULL,
|
||||
.srcAccessMask = 0,
|
||||
.srcAccessMask = srcAccessMask,
|
||||
.dstAccessMask = 0,
|
||||
.oldLayout = old_image_layout,
|
||||
.newLayout = new_image_layout,
|
||||
@ -509,21 +518,11 @@ static void demo_set_image_layout(struct demo *demo, VkImage image,
|
||||
}
|
||||
|
||||
static void demo_draw_build_cmd(struct demo *demo) {
|
||||
const VkCommandBufferInheritanceInfo cmd_buf_hinfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
|
||||
.pNext = NULL,
|
||||
.renderPass = VK_NULL_HANDLE,
|
||||
.subpass = 0,
|
||||
.framebuffer = VK_NULL_HANDLE,
|
||||
.occlusionQueryEnable = VK_FALSE,
|
||||
.queryFlags = 0,
|
||||
.pipelineStatistics = 0,
|
||||
};
|
||||
const VkCommandBufferBeginInfo cmd_buf_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
.pNext = NULL,
|
||||
.flags = 0,
|
||||
.pInheritanceInfo = &cmd_buf_hinfo,
|
||||
.pInheritanceInfo = NULL,
|
||||
};
|
||||
const VkClearValue clear_values[2] = {
|
||||
[0] = {.color.float32 = {0.2f, 0.2f, 0.2f, 0.2f}},
|
||||
@ -546,6 +545,23 @@ static void demo_draw_build_cmd(struct demo *demo) {
|
||||
err = vkBeginCommandBuffer(demo->draw_cmd, &cmd_buf_info);
|
||||
assert(!err);
|
||||
|
||||
// We can use LAYOUT_UNDEFINED as a wildcard here because we don't care what
|
||||
// happens to the previous contents of the image
|
||||
VkImageMemoryBarrier image_memory_barrier = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = NULL,
|
||||
.srcAccessMask = 0,
|
||||
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = demo->buffers[demo->current_buffer].image,
|
||||
.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}};
|
||||
|
||||
vkCmdPipelineBarrier(demo->draw_cmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, NULL, 0,
|
||||
NULL, 1, &image_memory_barrier);
|
||||
vkCmdBeginRenderPass(demo->draw_cmd, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdBindPipeline(demo->draw_cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
demo->pipeline);
|
||||
@ -599,20 +615,24 @@ static void demo_draw_build_cmd(struct demo *demo) {
|
||||
|
||||
static void demo_draw(struct demo *demo) {
|
||||
VkResult U_ASSERT_ONLY err;
|
||||
VkSemaphore presentCompleteSemaphore;
|
||||
VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {
|
||||
VkSemaphore imageAcquiredSemaphore, drawCompleteSemaphore;
|
||||
VkSemaphoreCreateInfo semaphoreCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
err = vkCreateSemaphore(demo->device, &presentCompleteSemaphoreCreateInfo,
|
||||
NULL, &presentCompleteSemaphore);
|
||||
err = vkCreateSemaphore(demo->device, &semaphoreCreateInfo,
|
||||
NULL, &imageAcquiredSemaphore);
|
||||
assert(!err);
|
||||
|
||||
err = vkCreateSemaphore(demo->device, &semaphoreCreateInfo,
|
||||
NULL, &drawCompleteSemaphore);
|
||||
assert(!err);
|
||||
|
||||
// Get the index of the next available swapchain image:
|
||||
err = demo->fpAcquireNextImageKHR(demo->device, demo->swapchain, UINT64_MAX,
|
||||
presentCompleteSemaphore,
|
||||
imageAcquiredSemaphore,
|
||||
(VkFence)0, // TODO: Show use of fence
|
||||
&demo->current_buffer);
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||
@ -620,7 +640,8 @@ static void demo_draw(struct demo *demo) {
|
||||
// must be recreated:
|
||||
demo_resize(demo);
|
||||
demo_draw(demo);
|
||||
vkDestroySemaphore(demo->device, presentCompleteSemaphore, NULL);
|
||||
vkDestroySemaphore(demo->device, imageAcquiredSemaphore, NULL);
|
||||
vkDestroySemaphore(demo->device, drawCompleteSemaphore, NULL);
|
||||
return;
|
||||
} else if (err == VK_SUBOPTIMAL_KHR) {
|
||||
// demo->swapchain is not as optimal as it could be, but the platform's
|
||||
@ -629,12 +650,6 @@ static void demo_draw(struct demo *demo) {
|
||||
assert(!err);
|
||||
}
|
||||
|
||||
// Assume the command buffer has been run on current_buffer before so
|
||||
// we need to set the image layout back to COLOR_ATTACHMENT_OPTIMAL
|
||||
demo_set_image_layout(demo, demo->buffers[demo->current_buffer].image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
demo_flush_init_cmd(demo);
|
||||
|
||||
// Wait for the present complete semaphore to be signaled to ensure
|
||||
@ -642,7 +657,6 @@ static void demo_draw(struct demo *demo) {
|
||||
// engine has fully released ownership to the application, and it is
|
||||
// okay to render to the image.
|
||||
|
||||
// FIXME/TODO: DEAL WITH VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
|
||||
demo_draw_build_cmd(demo);
|
||||
VkFence nullFence = VK_NULL_HANDLE;
|
||||
VkPipelineStageFlags pipe_stage_flags =
|
||||
@ -650,12 +664,12 @@ static void demo_draw(struct demo *demo) {
|
||||
VkSubmitInfo submit_info = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.pNext = NULL,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &presentCompleteSemaphore,
|
||||
.pWaitSemaphores = &imageAcquiredSemaphore,
|
||||
.pWaitDstStageMask = &pipe_stage_flags,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &demo->draw_cmd,
|
||||
.signalSemaphoreCount = 0,
|
||||
.pSignalSemaphores = NULL};
|
||||
.signalSemaphoreCount = 1,
|
||||
.pSignalSemaphores = &drawCompleteSemaphore};
|
||||
|
||||
err = vkQueueSubmit(demo->queue, 1, &submit_info, nullFence);
|
||||
assert(!err);
|
||||
@ -663,12 +677,13 @@ static void demo_draw(struct demo *demo) {
|
||||
VkPresentInfoKHR present = {
|
||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||
.pNext = NULL,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &drawCompleteSemaphore,
|
||||
.swapchainCount = 1,
|
||||
.pSwapchains = &demo->swapchain,
|
||||
.pImageIndices = &demo->current_buffer,
|
||||
};
|
||||
|
||||
// TBD/TODO: SHOULD THE "present" PARAMETER BE "const" IN THE HEADER?
|
||||
err = demo->fpQueuePresentKHR(demo->queue, &present);
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||
// demo->swapchain is out of date (e.g. the window was resized) and
|
||||
@ -684,7 +699,8 @@ static void demo_draw(struct demo *demo) {
|
||||
err = vkQueueWaitIdle(demo->queue);
|
||||
assert(err == VK_SUCCESS);
|
||||
|
||||
vkDestroySemaphore(demo->device, presentCompleteSemaphore, NULL);
|
||||
vkDestroySemaphore(demo->device, imageAcquiredSemaphore, NULL);
|
||||
vkDestroySemaphore(demo->device, drawCompleteSemaphore, NULL);
|
||||
}
|
||||
|
||||
static void demo_prepare_buffers(struct demo *demo) {
|
||||
@ -709,12 +725,25 @@ static void demo_prepare_buffers(struct demo *demo) {
|
||||
assert(!err);
|
||||
|
||||
VkExtent2D swapchainExtent;
|
||||
// width and height are either both -1, or both not -1.
|
||||
if (surfCapabilities.currentExtent.width == (uint32_t)-1) {
|
||||
// If the surface size is undefined, the size is set to
|
||||
// the size of the images requested.
|
||||
// width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF.
|
||||
if (surfCapabilities.currentExtent.width == 0xFFFFFFFF) {
|
||||
// If the surface size is undefined, the size is set to the size
|
||||
// of the images requested, which must fit within the minimum and
|
||||
// maximum values.
|
||||
swapchainExtent.width = demo->width;
|
||||
swapchainExtent.height = demo->height;
|
||||
|
||||
if (swapchainExtent.width < surfCapabilities.minImageExtent.width) {
|
||||
swapchainExtent.width = surfCapabilities.minImageExtent.width;
|
||||
} else if (swapchainExtent.width > surfCapabilities.maxImageExtent.width) {
|
||||
swapchainExtent.width = surfCapabilities.maxImageExtent.width;
|
||||
}
|
||||
|
||||
if (swapchainExtent.height < surfCapabilities.minImageExtent.height) {
|
||||
swapchainExtent.height = surfCapabilities.minImageExtent.height;
|
||||
} else if (swapchainExtent.height > surfCapabilities.maxImageExtent.height) {
|
||||
swapchainExtent.height = surfCapabilities.maxImageExtent.height;
|
||||
}
|
||||
} else {
|
||||
// If the surface size is defined, the swap chain size must match
|
||||
swapchainExtent = surfCapabilities.currentExtent;
|
||||
@ -724,15 +753,16 @@ static void demo_prepare_buffers(struct demo *demo) {
|
||||
|
||||
VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
|
||||
// Determine the number of VkImage's to use in the swap chain (we desire to
|
||||
// own only 1 image at a time, besides the images being displayed and
|
||||
// queued for display):
|
||||
uint32_t desiredNumberOfSwapchainImages =
|
||||
surfCapabilities.minImageCount + 1;
|
||||
// Determine the number of VkImage's to use in the swap chain.
|
||||
// Application desires to only acquire 1 image at a time (which is
|
||||
// "surfCapabilities.minImageCount").
|
||||
uint32_t desiredNumOfSwapchainImages = surfCapabilities.minImageCount;
|
||||
// If maxImageCount is 0, we can ask for as many images as we want;
|
||||
// otherwise we're limited to maxImageCount
|
||||
if ((surfCapabilities.maxImageCount > 0) &&
|
||||
(desiredNumberOfSwapchainImages > surfCapabilities.maxImageCount)) {
|
||||
(desiredNumOfSwapchainImages > surfCapabilities.maxImageCount)) {
|
||||
// Application must settle for fewer images than desired:
|
||||
desiredNumberOfSwapchainImages = surfCapabilities.maxImageCount;
|
||||
desiredNumOfSwapchainImages = surfCapabilities.maxImageCount;
|
||||
}
|
||||
|
||||
VkSurfaceTransformFlagsKHR preTransform;
|
||||
@ -747,7 +777,7 @@ static void demo_prepare_buffers(struct demo *demo) {
|
||||
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
||||
.pNext = NULL,
|
||||
.surface = demo->surface,
|
||||
.minImageCount = desiredNumberOfSwapchainImages,
|
||||
.minImageCount = desiredNumOfSwapchainImages,
|
||||
.imageFormat = demo->format,
|
||||
.imageColorSpace = demo->color_space,
|
||||
.imageExtent =
|
||||
@ -818,14 +848,6 @@ static void demo_prepare_buffers(struct demo *demo) {
|
||||
|
||||
demo->buffers[i].image = swapchainImages[i];
|
||||
|
||||
// Render loop will expect image to have been used before and in
|
||||
// VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
|
||||
// layout and will change to COLOR_ATTACHMENT_OPTIMAL, so init the image
|
||||
// to that state
|
||||
demo_set_image_layout(
|
||||
demo, demo->buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
|
||||
color_attachment_view.image = demo->buffers[i].image;
|
||||
|
||||
err = vkCreateImageView(demo->device, &color_attachment_view, NULL,
|
||||
@ -906,7 +928,8 @@ static void demo_prepare_depth(struct demo *demo) {
|
||||
|
||||
demo_set_image_layout(demo, demo->depth.image, VK_IMAGE_ASPECT_DEPTH_BIT,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||
0);
|
||||
|
||||
/* create image view */
|
||||
view.image = demo->depth.image;
|
||||
@ -939,6 +962,7 @@ demo_prepare_texture_image(struct demo *demo, const uint32_t *tex_colors,
|
||||
.tiling = tiling,
|
||||
.usage = usage,
|
||||
.flags = 0,
|
||||
.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED
|
||||
};
|
||||
VkMemoryAllocateInfo mem_alloc = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
@ -997,7 +1021,8 @@ demo_prepare_texture_image(struct demo *demo, const uint32_t *tex_colors,
|
||||
|
||||
tex_obj->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
demo_set_image_layout(demo, tex_obj->image, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, tex_obj->imageLayout);
|
||||
VK_IMAGE_LAYOUT_PREINITIALIZED, tex_obj->imageLayout,
|
||||
VK_ACCESS_HOST_WRITE_BIT);
|
||||
/* setting the image layout does not reference the actual memory so no need
|
||||
* to add a mem ref */
|
||||
}
|
||||
@ -1025,20 +1050,22 @@ static void demo_prepare_textures(struct demo *demo) {
|
||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) &&
|
||||
!demo->use_staging_buffer) {
|
||||
/* Device can texture using linear textures */
|
||||
demo_prepare_texture_image(demo, tex_colors[i], &demo->textures[i],
|
||||
VK_IMAGE_TILING_LINEAR,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
|
||||
demo_prepare_texture_image(
|
||||
demo, tex_colors[i], &demo->textures[i], VK_IMAGE_TILING_LINEAR,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
} else if (props.optimalTilingFeatures &
|
||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
|
||||
/* Must use staging buffer to copy linear texture to optimized */
|
||||
struct texture_object staging_texture;
|
||||
|
||||
memset(&staging_texture, 0, sizeof(staging_texture));
|
||||
demo_prepare_texture_image(demo, tex_colors[i], &staging_texture,
|
||||
VK_IMAGE_TILING_LINEAR,
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
|
||||
demo_prepare_texture_image(
|
||||
demo, tex_colors[i], &staging_texture, VK_IMAGE_TILING_LINEAR,
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
|
||||
demo_prepare_texture_image(
|
||||
demo, tex_colors[i], &demo->textures[i],
|
||||
@ -1049,12 +1076,14 @@ static void demo_prepare_textures(struct demo *demo) {
|
||||
demo_set_image_layout(demo, staging_texture.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
staging_texture.imageLayout,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
0);
|
||||
|
||||
demo_set_image_layout(demo, demo->textures[i].image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
demo->textures[i].imageLayout,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
0);
|
||||
|
||||
VkImageCopy copy_region = {
|
||||
.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
|
||||
@ -1072,7 +1101,8 @@ static void demo_prepare_textures(struct demo *demo) {
|
||||
demo_set_image_layout(demo, demo->textures[i].image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
demo->textures[i].imageLayout);
|
||||
demo->textures[i].imageLayout,
|
||||
0);
|
||||
|
||||
demo_flush_init_cmd(demo);
|
||||
|
||||
@ -1165,7 +1195,8 @@ static void demo_prepare_vertices(struct demo *demo) {
|
||||
|
||||
mem_alloc.allocationSize = mem_reqs.size;
|
||||
pass = memory_type_from_properties(demo, mem_reqs.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
&mem_alloc.memoryTypeIndex);
|
||||
assert(pass);
|
||||
|
||||
@ -1376,6 +1407,7 @@ static void demo_prepare_pipeline(struct demo *demo) {
|
||||
rs.depthClampEnable = VK_FALSE;
|
||||
rs.rasterizerDiscardEnable = VK_FALSE;
|
||||
rs.depthBiasEnable = VK_FALSE;
|
||||
rs.lineWidth = 1.0f;
|
||||
|
||||
memset(&cb, 0, sizeof(cb));
|
||||
cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||
@ -1608,6 +1640,9 @@ static void demo_run(struct demo *demo) {
|
||||
|
||||
// Wait for work to finish before updating MVP.
|
||||
vkDeviceWaitIdle(demo->device);
|
||||
demo->curFrame++;
|
||||
if (demo->frameCount != INT32_MAX && demo->curFrame == demo->frameCount)
|
||||
glfwSetWindowShouldClose(demo->window, GLFW_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1636,7 +1671,7 @@ static void demo_create_window(struct demo *demo) {
|
||||
* Return 1 (true) if all layer names specified in check_names
|
||||
* can be found in given layer properties.
|
||||
*/
|
||||
static VkBool32 demo_check_layers(uint32_t check_count, char **check_names,
|
||||
static VkBool32 demo_check_layers(uint32_t check_count, const char **check_names,
|
||||
uint32_t layer_count,
|
||||
VkLayerProperties *layers) {
|
||||
uint32_t i, j;
|
||||
@ -1656,79 +1691,77 @@ static VkBool32 demo_check_layers(uint32_t check_count, char **check_names,
|
||||
return 1;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void *VKAPI_CALL myrealloc(void *pUserData, void *pOriginal,
|
||||
size_t size, size_t alignment,
|
||||
VkSystemAllocationScope allocationScope) {
|
||||
return realloc(pOriginal, size);
|
||||
}
|
||||
|
||||
VKAPI_ATTR void *VKAPI_CALL myalloc(void *pUserData, size_t size,
|
||||
size_t alignment,
|
||||
VkSystemAllocationScope allocationScope) {
|
||||
#ifdef _MSC_VER
|
||||
return _aligned_malloc(size, alignment);
|
||||
#else
|
||||
return aligned_alloc(alignment, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL myfree(void *pUserData, void *pMemory) {
|
||||
#ifdef _MSC_VER
|
||||
_aligned_free(pMemory);
|
||||
#else
|
||||
free(pMemory);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void demo_init_vk(struct demo *demo) {
|
||||
VkResult err;
|
||||
uint32_t required_extension_count;
|
||||
const char** required_extensions;
|
||||
uint32_t i;
|
||||
uint32_t i = 0;
|
||||
uint32_t required_extension_count = 0;
|
||||
uint32_t instance_extension_count = 0;
|
||||
uint32_t instance_layer_count = 0;
|
||||
uint32_t device_validation_layer_count = 0;
|
||||
uint32_t validation_layer_count = 0;
|
||||
const char **required_extensions = NULL;
|
||||
const char **instance_validation_layers = NULL;
|
||||
demo->enabled_extension_count = 0;
|
||||
demo->enabled_layer_count = 0;
|
||||
|
||||
char *instance_validation_layers[] = {
|
||||
"VK_LAYER_LUNARG_mem_tracker",
|
||||
"VK_LAYER_GOOGLE_unique_objects",
|
||||
char *instance_validation_layers_alt1[] = {
|
||||
"VK_LAYER_LUNARG_standard_validation"
|
||||
};
|
||||
|
||||
demo->device_validation_layers[0] = "VK_LAYER_LUNARG_mem_tracker";
|
||||
demo->device_validation_layers[1] = "VK_LAYER_GOOGLE_unique_objects";
|
||||
device_validation_layer_count = 2;
|
||||
char *instance_validation_layers_alt2[] = {
|
||||
"VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation",
|
||||
"VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_image",
|
||||
"VK_LAYER_LUNARG_core_validation", "VK_LAYER_LUNARG_swapchain",
|
||||
"VK_LAYER_GOOGLE_unique_objects"
|
||||
};
|
||||
|
||||
/* Look for validation layers */
|
||||
VkBool32 validation_found = 0;
|
||||
err = vkEnumerateInstanceLayerProperties(&instance_layer_count, NULL);
|
||||
assert(!err);
|
||||
if (demo->validate) {
|
||||
|
||||
if (instance_layer_count > 0) {
|
||||
VkLayerProperties *instance_layers =
|
||||
malloc(sizeof(VkLayerProperties) * instance_layer_count);
|
||||
err = vkEnumerateInstanceLayerProperties(&instance_layer_count,
|
||||
instance_layers);
|
||||
err = vkEnumerateInstanceLayerProperties(&instance_layer_count, NULL);
|
||||
assert(!err);
|
||||
|
||||
if (demo->validate) {
|
||||
instance_validation_layers = instance_validation_layers_alt1;
|
||||
if (instance_layer_count > 0) {
|
||||
VkLayerProperties *instance_layers =
|
||||
malloc(sizeof (VkLayerProperties) * instance_layer_count);
|
||||
err = vkEnumerateInstanceLayerProperties(&instance_layer_count,
|
||||
instance_layers);
|
||||
assert(!err);
|
||||
|
||||
|
||||
validation_found = demo_check_layers(
|
||||
ARRAY_SIZE(instance_validation_layers),
|
||||
instance_validation_layers, instance_layer_count,
|
||||
instance_layers);
|
||||
demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers);
|
||||
ARRAY_SIZE(instance_validation_layers_alt1),
|
||||
instance_validation_layers, instance_layer_count,
|
||||
instance_layers);
|
||||
if (validation_found) {
|
||||
demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers_alt1);
|
||||
demo->enabled_layers[0] = "VK_LAYER_LUNARG_standard_validation";
|
||||
validation_layer_count = 1;
|
||||
} else {
|
||||
// use alternative set of validation layers
|
||||
instance_validation_layers = instance_validation_layers_alt2;
|
||||
demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers_alt2);
|
||||
validation_found = demo_check_layers(
|
||||
ARRAY_SIZE(instance_validation_layers_alt2),
|
||||
instance_validation_layers, instance_layer_count,
|
||||
instance_layers);
|
||||
validation_layer_count =
|
||||
ARRAY_SIZE(instance_validation_layers_alt2);
|
||||
for (i = 0; i < validation_layer_count; i++) {
|
||||
demo->enabled_layers[i] = instance_validation_layers[i];
|
||||
}
|
||||
}
|
||||
free(instance_layers);
|
||||
}
|
||||
|
||||
free(instance_layers);
|
||||
}
|
||||
|
||||
if (demo->validate && !validation_found) {
|
||||
ERR_EXIT("vkEnumerateInstanceLayerProperties failed to find"
|
||||
"required validation layer.\n\n"
|
||||
"Please look at the Getting Started guide for additional "
|
||||
"information.\n",
|
||||
"vkCreateInstance Failure");
|
||||
if (!validation_found) {
|
||||
ERR_EXIT("vkEnumerateInstanceLayerProperties failed to find "
|
||||
"required validation layer.\n\n"
|
||||
"Please look at the Getting Started guide for additional "
|
||||
"information.\n",
|
||||
"vkCreateInstance Failure");
|
||||
}
|
||||
}
|
||||
|
||||
/* Look for instance extensions */
|
||||
@ -1792,11 +1825,7 @@ static void demo_init_vk(struct demo *demo) {
|
||||
|
||||
uint32_t gpu_count;
|
||||
|
||||
demo->allocator.pfnAllocation = myalloc;
|
||||
demo->allocator.pfnFree = myfree;
|
||||
demo->allocator.pfnReallocation = myrealloc;
|
||||
|
||||
err = vkCreateInstance(&inst_info, &demo->allocator, &demo->inst);
|
||||
err = vkCreateInstance(&inst_info, NULL, &demo->inst);
|
||||
if (err == VK_ERROR_INCOMPATIBLE_DRIVER) {
|
||||
ERR_EXIT("Cannot find a compatible Vulkan installable client driver "
|
||||
"(ICD).\n\nPlease look at the Getting Started guide for "
|
||||
@ -1834,40 +1863,6 @@ static void demo_init_vk(struct demo *demo) {
|
||||
"vkEnumeratePhysicalDevices Failure");
|
||||
}
|
||||
|
||||
/* Look for validation layers */
|
||||
validation_found = 0;
|
||||
demo->enabled_layer_count = 0;
|
||||
uint32_t device_layer_count = 0;
|
||||
err =
|
||||
vkEnumerateDeviceLayerProperties(demo->gpu, &device_layer_count, NULL);
|
||||
assert(!err);
|
||||
|
||||
if (device_layer_count > 0) {
|
||||
VkLayerProperties *device_layers =
|
||||
malloc(sizeof(VkLayerProperties) * device_layer_count);
|
||||
err = vkEnumerateDeviceLayerProperties(demo->gpu, &device_layer_count,
|
||||
device_layers);
|
||||
assert(!err);
|
||||
|
||||
if (demo->validate) {
|
||||
validation_found = demo_check_layers(device_validation_layer_count,
|
||||
demo->device_validation_layers,
|
||||
device_layer_count,
|
||||
device_layers);
|
||||
demo->enabled_layer_count = device_validation_layer_count;
|
||||
}
|
||||
|
||||
free(device_layers);
|
||||
}
|
||||
|
||||
if (demo->validate && !validation_found) {
|
||||
ERR_EXIT("vkEnumerateDeviceLayerProperties failed to find "
|
||||
"a required validation layer.\n\n"
|
||||
"Please look at the Getting Started guide for additional "
|
||||
"information.\n",
|
||||
"vkCreateDevice Failure");
|
||||
}
|
||||
|
||||
/* Look for device extensions */
|
||||
uint32_t device_extension_count = 0;
|
||||
VkBool32 swapchainExtFound = 0;
|
||||
@ -1911,17 +1906,33 @@ static void demo_init_vk(struct demo *demo) {
|
||||
demo->CreateDebugReportCallback =
|
||||
(PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(
|
||||
demo->inst, "vkCreateDebugReportCallbackEXT");
|
||||
demo->DestroyDebugReportCallback =
|
||||
(PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(
|
||||
demo->inst, "vkDestroyDebugReportCallbackEXT");
|
||||
if (!demo->CreateDebugReportCallback) {
|
||||
ERR_EXIT(
|
||||
"GetProcAddr: Unable to find vkCreateDebugReportCallbackEXT\n",
|
||||
"vkGetProcAddr Failure");
|
||||
}
|
||||
if (!demo->DestroyDebugReportCallback) {
|
||||
ERR_EXIT(
|
||||
"GetProcAddr: Unable to find vkDestroyDebugReportCallbackEXT\n",
|
||||
"vkGetProcAddr Failure");
|
||||
}
|
||||
demo->DebugReportMessage =
|
||||
(PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr(
|
||||
demo->inst, "vkDebugReportMessageEXT");
|
||||
if (!demo->DebugReportMessage) {
|
||||
ERR_EXIT("GetProcAddr: Unable to find vkDebugReportMessageEXT\n",
|
||||
"vkGetProcAddr Failure");
|
||||
}
|
||||
|
||||
VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;
|
||||
dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
|
||||
dbgCreateInfo.flags =
|
||||
VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
|
||||
dbgCreateInfo.pfnCallback = dbgFunc;
|
||||
dbgCreateInfo.pUserData = NULL;
|
||||
dbgCreateInfo.pfnCallback = demo->use_break ? BreakCallback : dbgFunc;
|
||||
dbgCreateInfo.pUserData = demo;
|
||||
dbgCreateInfo.pNext = NULL;
|
||||
err = demo->CreateDebugReportCallback(demo->inst, &dbgCreateInfo, NULL,
|
||||
&demo->msg_callback);
|
||||
@ -1945,11 +1956,6 @@ static void demo_init_vk(struct demo *demo) {
|
||||
GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceFormatsKHR);
|
||||
GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfacePresentModesKHR);
|
||||
GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceSupportKHR);
|
||||
GET_INSTANCE_PROC_ADDR(demo->inst, CreateSwapchainKHR);
|
||||
GET_INSTANCE_PROC_ADDR(demo->inst, DestroySwapchainKHR);
|
||||
GET_INSTANCE_PROC_ADDR(demo->inst, GetSwapchainImagesKHR);
|
||||
GET_INSTANCE_PROC_ADDR(demo->inst, AcquireNextImageKHR);
|
||||
GET_INSTANCE_PROC_ADDR(demo->inst, QueuePresentKHR);
|
||||
|
||||
vkGetPhysicalDeviceProperties(demo->gpu, &demo->gpu_props);
|
||||
|
||||
@ -1963,6 +1969,8 @@ static void demo_init_vk(struct demo *demo) {
|
||||
demo->queue_props);
|
||||
assert(demo->queue_count >= 1);
|
||||
|
||||
vkGetPhysicalDeviceFeatures(demo->gpu, &demo->gpu_features);
|
||||
|
||||
// Graphics queue and MemMgr queue can be separate.
|
||||
// TODO: Add support for separate queues, including synchronization,
|
||||
// and appropriate tracking for QueueSubmit
|
||||
@ -1979,18 +1987,23 @@ static void demo_init_device(struct demo *demo) {
|
||||
.queueCount = 1,
|
||||
.pQueuePriorities = queue_priorities};
|
||||
|
||||
|
||||
VkPhysicalDeviceFeatures features;
|
||||
memset(&features, 0, sizeof(features));
|
||||
if (demo->gpu_features.shaderClipDistance) {
|
||||
features.shaderClipDistance = VK_TRUE;
|
||||
}
|
||||
|
||||
VkDeviceCreateInfo device = {
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
.queueCreateInfoCount = 1,
|
||||
.pQueueCreateInfos = &queue,
|
||||
.enabledLayerCount = demo->enabled_layer_count,
|
||||
.ppEnabledLayerNames =
|
||||
(const char *const *)((demo->validate)
|
||||
? demo->device_validation_layers
|
||||
: NULL),
|
||||
.enabledLayerCount = 0,
|
||||
.ppEnabledLayerNames = NULL,
|
||||
.enabledExtensionCount = demo->enabled_extension_count,
|
||||
.ppEnabledExtensionNames = (const char *const *)demo->extension_names,
|
||||
.pEnabledFeatures = &features,
|
||||
};
|
||||
|
||||
err = vkCreateDevice(demo->gpu, &device, NULL, &demo->device);
|
||||
@ -2092,6 +2105,8 @@ static void demo_init_vk_swapchain(struct demo *demo) {
|
||||
}
|
||||
demo->color_space = surfFormats[0].colorSpace;
|
||||
|
||||
demo->curFrame = 0;
|
||||
|
||||
// Get Memory information and properties
|
||||
vkGetPhysicalDeviceMemoryProperties(demo->gpu, &demo->memory_properties);
|
||||
}
|
||||
@ -2115,12 +2130,34 @@ static void demo_init_connection(struct demo *demo) {
|
||||
static void demo_init(struct demo *demo, const int argc, const char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(demo, 0, sizeof(*demo));
|
||||
demo->frameCount = INT32_MAX;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strncmp(argv[i], "--use_staging", strlen("--use_staging")) == 0)
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--use_staging") == 0) {
|
||||
demo->use_staging_buffer = true;
|
||||
continue;
|
||||
}
|
||||
if (strcmp(argv[i], "--break") == 0) {
|
||||
demo->use_break = true;
|
||||
continue;
|
||||
}
|
||||
if (strcmp(argv[i], "--validate") == 0) {
|
||||
demo->validate = true;
|
||||
continue;
|
||||
}
|
||||
if (strcmp(argv[i], "--c") == 0 && demo->frameCount == INT32_MAX &&
|
||||
i < argc - 1 && sscanf(argv[i + 1], "%d", &demo->frameCount) == 1 &&
|
||||
demo->frameCount >= 0) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Usage:\n %s [--use_staging] [--validate] [--break] "
|
||||
"[--c <framecount>]\n",
|
||||
APP_SHORT_NAME);
|
||||
fflush(stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
demo_init_connection(demo);
|
||||
@ -2174,8 +2211,11 @@ static void demo_cleanup(struct demo *demo) {
|
||||
free(demo->buffers);
|
||||
|
||||
vkDestroyDevice(demo->device, NULL);
|
||||
if (demo->validate) {
|
||||
demo->DestroyDebugReportCallback(demo->inst, demo->msg_callback, NULL);
|
||||
}
|
||||
vkDestroySurfaceKHR(demo->inst, demo->surface, NULL);
|
||||
vkDestroyInstance(demo->inst, &demo->allocator);
|
||||
vkDestroyInstance(demo->inst, NULL);
|
||||
|
||||
free(demo->queue_props);
|
||||
|
||||
@ -2186,6 +2226,11 @@ static void demo_cleanup(struct demo *demo) {
|
||||
static void demo_resize(struct demo *demo) {
|
||||
uint32_t i;
|
||||
|
||||
// In order to properly resize the window, we must re-create the swapchain
|
||||
// AND redo the command buffers, etc.
|
||||
//
|
||||
// First, perform part of the demo_cleanup() function:
|
||||
|
||||
for (i = 0; i < demo->swapchainImageCount; i++) {
|
||||
vkDestroyFramebuffer(demo->device, demo->framebuffers[i], NULL);
|
||||
}
|
||||
@ -2240,6 +2285,6 @@ int main(const int argc, const char *argv[]) {
|
||||
|
||||
demo_cleanup(&demo);
|
||||
|
||||
return 0;
|
||||
return validation_error;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user