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{VULKAN_SDK}/Bin32"
|
||||||
"$ENV{VK_SDK_PATH}/Bin32")
|
"$ENV{VK_SDK_PATH}/Bin32")
|
||||||
endif()
|
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()
|
else()
|
||||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||||
"$ENV{VULKAN_SDK}/include")
|
"$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_VULKAN_STATIC "Use the Vulkan loader statically linked into application" OFF)
|
||||||
option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" 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)
|
if (WIN32)
|
||||||
option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF)
|
option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF)
|
||||||
endif()
|
endif()
|
||||||
@ -129,26 +133,36 @@ if (MINGW)
|
|||||||
endif()
|
endif()
|
||||||
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
|
# Detect and select backend APIs
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
if (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)
|
if (GLFW_USE_WAYLAND)
|
||||||
set(_GLFW_WAYLAND 1)
|
set(_GLFW_WAYLAND 1)
|
||||||
message(STATUS "Using Wayland for window creation")
|
message(STATUS "Using Wayland for window creation")
|
||||||
elseif (GLFW_USE_MIR)
|
elseif (GLFW_USE_MIR)
|
||||||
set(_GLFW_MIR 1)
|
set(_GLFW_MIR 1)
|
||||||
message(STATUS "Using Mir for window creation")
|
message(STATUS "Using Mir for window creation")
|
||||||
else()
|
elseif (GLFW_USE_OSMESA)
|
||||||
|
set(_GLFW_OSMESA 1)
|
||||||
|
message(STATUS "Using OSMesa for headless context creation")
|
||||||
|
elseif (WIN32)
|
||||||
|
set(_GLFW_WIN32 1)
|
||||||
|
message(STATUS "Using Win32 for window creation")
|
||||||
|
elseif (APPLE)
|
||||||
|
set(_GLFW_COCOA 1)
|
||||||
|
message(STATUS "Using Cocoa for window creation")
|
||||||
|
elseif (UNIX)
|
||||||
set(_GLFW_X11 1)
|
set(_GLFW_X11 1)
|
||||||
message(STATUS "Using X11 for window creation")
|
message(STATUS "Using X11 for window creation")
|
||||||
endif()
|
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "No supported platform was detected")
|
message(FATAL_ERROR "No supported platform was detected")
|
||||||
endif()
|
endif()
|
||||||
@ -158,7 +172,10 @@ endif()
|
|||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
if (GLFW_VULKAN_STATIC)
|
if (GLFW_VULKAN_STATIC)
|
||||||
if (VULKAN_FOUND AND VULKAN_STATIC_LIBRARY)
|
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()
|
else()
|
||||||
if (BUILD_SHARED_LIBS OR GLFW_BUILD_EXAMPLES OR GLFW_BUILD_TESTS)
|
if (BUILD_SHARED_LIBS OR GLFW_BUILD_EXAMPLES OR GLFW_BUILD_TESTS)
|
||||||
message(FATAL_ERROR "Vulkan loader static library not found")
|
message(FATAL_ERROR "Vulkan loader static library not found")
|
||||||
@ -306,6 +323,14 @@ if (_GLFW_MIR)
|
|||||||
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
|
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
|
||||||
endif()
|
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
|
# Use Cocoa for window creation and NSOpenGL for context creation
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
@ -323,19 +348,11 @@ if (_GLFW_COCOA)
|
|||||||
set(_GLFW_USE_RETINA 1)
|
set(_GLFW_USE_RETINA 1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Set up library and include paths
|
list(APPEND glfw_LIBRARIES
|
||||||
find_library(COCOA_FRAMEWORK Cocoa)
|
"-framework Cocoa"
|
||||||
find_library(IOKIT_FRAMEWORK IOKit)
|
"-framework IOKit"
|
||||||
find_library(CORE_FOUNDATION_FRAMEWORK CoreFoundation)
|
"-framework CoreFoundation"
|
||||||
find_library(CORE_VIDEO_FRAMEWORK CoreVideo)
|
"-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}")
|
|
||||||
|
|
||||||
set(glfw_PKG_DEPS "")
|
set(glfw_PKG_DEPS "")
|
||||||
set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation -framework CoreVideo")
|
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.
|
rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them.
|
||||||
|
|
||||||
GLFW supports compilation on Windows with Visual C++ 2010 and later, MinGW and
|
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
|
and Clang. It will likely compile in other environments as well, but this is
|
||||||
not regularly tested.
|
not regularly tested.
|
||||||
|
|
||||||
@ -81,6 +81,7 @@ located in the `deps/` directory.
|
|||||||
- [linmath.h](https://github.com/datenwolf/linmath.h) for linear algebra in
|
- [linmath.h](https://github.com/datenwolf/linmath.h) for linear algebra in
|
||||||
examples
|
examples
|
||||||
- [Nuklear](https://github.com/vurtun/nuklear) for test and example UI
|
- [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
|
- [Vulkan headers](https://www.khronos.org/registry/vulkan/) for Vulkan tests
|
||||||
|
|
||||||
The Vulkan example additionally requires the Vulkan SDK to be installed, or it
|
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)
|
scancodes for keys (#830)
|
||||||
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
|
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
|
||||||
receiving window maximization events (#778)
|
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: Calling `glfwMaximizeWindow` on a full screen window was not ignored
|
||||||
- Bugfix: `GLFW_INCLUDE_VULKAN` could not be combined with the corresponding
|
- Bugfix: `GLFW_INCLUDE_VULKAN` could not be combined with the corresponding
|
||||||
OpenGL and OpenGL ES header macros
|
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)
|
- [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)
|
- [EGL] Added support for `EGL_KHR_get_all_proc_addresses` (#871)
|
||||||
|
|
||||||
|
|
||||||
@ -149,6 +157,7 @@ skills.
|
|||||||
- Lambert Clara
|
- Lambert Clara
|
||||||
- Andrew Corrigan
|
- Andrew Corrigan
|
||||||
- Noel Cower
|
- Noel Cower
|
||||||
|
- Jason Daly
|
||||||
- Jarrod Davis
|
- Jarrod Davis
|
||||||
- Olivier Delannoy
|
- Olivier Delannoy
|
||||||
- Paul R. Deppe
|
- Paul R. Deppe
|
||||||
@ -160,6 +169,7 @@ skills.
|
|||||||
- Siavash Eliasi
|
- Siavash Eliasi
|
||||||
- Michael Fogleman
|
- Michael Fogleman
|
||||||
- Gerald Franz
|
- Gerald Franz
|
||||||
|
- Mário Freitas
|
||||||
- GeO4d
|
- GeO4d
|
||||||
- Marcus Geelnard
|
- Marcus Geelnard
|
||||||
- Eloi Marín Gratacós
|
- 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
2
deps/tinycthread.h
vendored
2
deps/tinycthread.h
vendored
@ -123,8 +123,10 @@ typedef int _tthread_clockid_t;
|
|||||||
/* Emulate clock_gettime */
|
/* Emulate clock_gettime */
|
||||||
int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts);
|
int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts);
|
||||||
#define clock_gettime _tthread_clock_gettime
|
#define clock_gettime _tthread_clock_gettime
|
||||||
|
#ifndef CLOCK_REALTIME
|
||||||
#define CLOCK_REALTIME 0
|
#define CLOCK_REALTIME 0
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/** TinyCThread version (major number). */
|
/** TinyCThread version (major number). */
|
||||||
|
@ -202,8 +202,9 @@ ALIASES = "thread_safety=@par Thread safety\n" \
|
|||||||
"errors=@par Errors\n" \
|
"errors=@par Errors\n" \
|
||||||
"glfw3=@par\n__GLFW 3:__" \
|
"glfw3=@par\n__GLFW 3:__" \
|
||||||
"x11=__X11:__" \
|
"x11=__X11:__" \
|
||||||
|
"wayland=__Wayland:__" \
|
||||||
"win32=__Windows:__" \
|
"win32=__Windows:__" \
|
||||||
"osx=__OS X:__"
|
"macos=__macOS:__"
|
||||||
|
|
||||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
# 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
|
# A mapping has the form "name=value". For example adding
|
||||||
@ -1576,6 +1577,7 @@ PREDEFINED = GLFWAPI= \
|
|||||||
GLFW_EXPOSE_NATIVE_COCOA \
|
GLFW_EXPOSE_NATIVE_COCOA \
|
||||||
GLFW_EXPOSE_NATIVE_NSGL \
|
GLFW_EXPOSE_NATIVE_NSGL \
|
||||||
GLFW_EXPOSE_NATIVE_EGL \
|
GLFW_EXPOSE_NATIVE_EGL \
|
||||||
|
GLFW_EXPOSE_NATIVE_OSMESA \
|
||||||
VK_VERSION_1_0
|
VK_VERSION_1_0
|
||||||
|
|
||||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
# 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.
|
Only one of these may be defined at a time.
|
||||||
|
|
||||||
`GLFW_INCLUDE_GLCOREARB` makes the GLFW header include the modern
|
`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.
|
header.
|
||||||
|
|
||||||
`GLFW_INCLUDE_ES1` makes the GLFW header include the OpenGL ES 1.x `GLES/gl.h`
|
`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.
|
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`
|
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
|
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
|
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
|
However, if you are using GLFW as a static library then your executable will
|
||||||
need to link against these libraries.
|
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
|
hard-coded into your build environment. See the section for your development
|
||||||
environment below. On Linux and other Unix-like operating systems, the list
|
environment below. On Linux and other Unix-like operating systems, the list
|
||||||
varies but can be retrieved in various ways as described below.
|
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
|
@endcode
|
||||||
|
|
||||||
The dependencies do not include OpenGL or GLU, as GLFW loads any OpenGL, OpenGL
|
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
|
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
|
anything extra. If you need GLU and are using Linux or BSD, you should add the
|
||||||
`glu` pkg-config package.
|
`glu` pkg-config package.
|
||||||
@ -309,7 +309,7 @@ cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --static --lib
|
|||||||
@endcode
|
@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
|
If you are using the dynamic library version of GLFW, simply add it to the
|
||||||
project dependencies.
|
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`.
|
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
|
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
|
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
|
to add the required frameworks and libraries to your command-line yourself using
|
||||||
the `-l` and `-framework` switches.
|
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
|
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
|
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
|
`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.
|
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
|
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
|
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
|
@section compat_vulkan Vulkan loader and API
|
||||||
|
|
||||||
GLFW uses the standard system-wide Vulkan loader to access the Vulkan API.
|
By default, GLFW uses the standard system-wide Vulkan loader to access the
|
||||||
This should be installed by graphics drivers and Vulkan SDKs. If this is not
|
Vulkan API on all platforms except macOS. This is installed by both graphics
|
||||||
available, @ref glfwVulkanSupported will return `GLFW_FALSE` and all other
|
drivers and Vulkan SDKs. If the loader is not found, @ref glfwVulkanSupported
|
||||||
Vulkan-related functions will fail with an @ref GLFW_API_UNAVAILABLE error.
|
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
|
@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
|
@ref glfwGetRequiredInstanceExtensions will return an empty list and window
|
||||||
surface creation will fail.
|
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
|
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`
|
`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
|
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
|
glfwGetRequiredInstanceExtensions will return an empty list and window surface
|
||||||
creation will fail.
|
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
|
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
|
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
|
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
|
@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
|
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.
|
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
|
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
|
and libraries are included in the core macOS frameworks. Xcode can be
|
||||||
from the Mac App Store or from the ADC Member Center.
|
downloaded from the Mac App Store or from the ADC Member Center.
|
||||||
|
|
||||||
Once you have Xcode installed, move on to @ref compile_generate.
|
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.
|
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
|
@subsection compile_generate Generating build files with CMake
|
||||||
|
|
||||||
Once you have all necessary dependencies it is time to generate the project
|
Once you have all necessary dependencies it is time to generate the project
|
||||||
@ -201,7 +213,7 @@ the library.
|
|||||||
statically into the application.
|
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
|
`GLFW_USE_CHDIR` determines whether `glfwInit` changes the current
|
||||||
directory of bundled applications to the `Contents/Resources` directory.
|
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_X11` to use the X Window System
|
||||||
- `_GLFW_WAYLAND` to use the Wayland API (experimental and incomplete)
|
- `_GLFW_WAYLAND` to use the Wayland API (experimental and incomplete)
|
||||||
- `_GLFW_MIR` to use the Mir 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
|
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.
|
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
|
You should still [process events](@ref events) as long as you have at least one
|
||||||
window, even if none of them are visible.
|
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
|
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
|
when writing a command-line only application. The menu bar setup can be
|
||||||
disabled with a [compile-time option](@ref compile_options_osx).
|
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.
|
and disconnected and the event that occurred.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
void joystick_callback(int joy, int event)
|
void joystick_callback(int jid, int event)
|
||||||
{
|
{
|
||||||
if (event == GLFW_CONNECTED)
|
if (event == GLFW_CONNECTED)
|
||||||
{
|
{
|
||||||
|
@ -16,6 +16,18 @@ GLFW now supports querying the platform dependent scancode of any key with
|
|||||||
@ref glfwGetKeyScancode.
|
@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
|
@section news_32 New features in 3.2
|
||||||
|
|
||||||
|
|
||||||
@ -293,11 +305,12 @@ through CMake options.
|
|||||||
|
|
||||||
@subsection news_30_hidpi High-DPI support
|
@subsection news_30_hidpi High-DPI support
|
||||||
|
|
||||||
GLFW now supports high-DPI monitors on both Windows and OS X, giving windows full
|
GLFW now supports high-DPI monitors on both Windows and macOS, giving windows
|
||||||
resolution framebuffers where other UI elements are scaled up. To achieve this,
|
full resolution framebuffers where other UI elements are scaled up. To achieve
|
||||||
@ref glfwGetFramebufferSize and @ref glfwSetFramebufferSizeCallback have been
|
this, @ref glfwGetFramebufferSize and @ref glfwSetFramebufferSizeCallback have
|
||||||
added. These work with pixels, while the rest of the GLFW API works with screen
|
been added. These work with pixels, while the rest of the GLFW API works with
|
||||||
coordinates. This is important as OpenGL uses pixels, not screen coordinates.
|
screen coordinates. This is important as OpenGL uses pixels, not screen
|
||||||
|
coordinates.
|
||||||
|
|
||||||
|
|
||||||
@subsection news_30_error Error callback
|
@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`
|
[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
|
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
|
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
|
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
|
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.
|
the Vulkan documentation to explain the details of Vulkan functions.
|
||||||
|
|
||||||
To develop for Vulkan you should install an SDK for your platform, for example
|
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
|
the [LunarG Vulkan SDK](https://vulkan.lunarg.com/) for Windows and Linux or
|
||||||
libraries, it also provides the validation layers necessary for development.
|
[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.
|
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
|
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
|
- @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
|
@section vulkan_include Including the Vulkan and GLFW header files
|
||||||
|
|
||||||
To include the Vulkan header, define [GLFW_INCLUDE_VULKAN](@ref build_macros)
|
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.
|
requested, this hint is ignored.
|
||||||
|
|
||||||
@par
|
@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.
|
will fail.
|
||||||
|
|
||||||
@par
|
@par
|
||||||
|
@ -11,6 +11,10 @@ if (MSVC)
|
|||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (GLFW_USE_OSMESA)
|
||||||
|
add_definitions(-DUSE_NATIVE_OSMESA)
|
||||||
|
endif()
|
||||||
|
|
||||||
include_directories("${GLFW_SOURCE_DIR}/deps")
|
include_directories("${GLFW_SOURCE_DIR}/deps")
|
||||||
|
|
||||||
if (WIN32)
|
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(boing WIN32 MACOSX_BUNDLE boing.c ${ICON} ${GLAD})
|
||||||
add_executable(gears WIN32 MACOSX_BUNDLE gears.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(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(particles WIN32 MACOSX_BUNDLE particles.c ${ICON} ${TINYCTHREAD} ${GETOPT} ${GLAD})
|
||||||
add_executable(simple WIN32 MACOSX_BUNDLE simple.c ${ICON} ${GLAD})
|
add_executable(simple WIN32 MACOSX_BUNDLE simple.c ${ICON} ${GLAD})
|
||||||
add_executable(splitview WIN32 MACOSX_BUNDLE splitview.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
|
||||||
#endif /* APIENTRY */
|
#endif /* APIENTRY */
|
||||||
|
|
||||||
|
/* Some OpenGL related headers use GLAPIENTRY instead.
|
||||||
|
*/
|
||||||
|
#ifndef GLAPIENTRY
|
||||||
|
#define GLAPIENTRY APIENTRY
|
||||||
|
#endif /* GLAPIENTRY */
|
||||||
|
|
||||||
/* Some Windows OpenGL headers need this.
|
/* Some Windows OpenGL headers need this.
|
||||||
*/
|
*/
|
||||||
#if !defined(WINGDIAPI) && defined(_WIN32)
|
#if !defined(WINGDIAPI) && defined(_WIN32)
|
||||||
@ -116,7 +122,7 @@ extern "C" {
|
|||||||
#endif /* CALLBACK */
|
#endif /* CALLBACK */
|
||||||
|
|
||||||
/* Include because most Windows GLU headers need wchar_t and
|
/* 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 it unconditionally to avoid surprising side-effects.
|
||||||
*/
|
*/
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@ -176,8 +182,12 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if defined(GLFW_INCLUDE_VULKAN)
|
#if defined(GLFW_INCLUDE_VULKAN)
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <MoltenVK/vulkan/vulkan.h>
|
||||||
|
#else
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL)
|
#if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL)
|
||||||
/* GLFW_DLL must be defined by applications that are linking against the DLL
|
/* GLFW_DLL must be defined by applications that are linking against the DLL
|
||||||
@ -561,7 +571,7 @@ extern "C" {
|
|||||||
* @par
|
* @par
|
||||||
* Some pre-installed Windows graphics drivers do not support OpenGL. AMD only
|
* Some pre-installed Windows graphics drivers do not support OpenGL. AMD only
|
||||||
* supports OpenGL ES via EGL, while Nvidia and Intel only support it via
|
* supports OpenGL ES via EGL, while Nvidia and Intel only support it via
|
||||||
* a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa
|
* a WGL or GLX extension. macOS does not provide OpenGL ES at all. The Mesa
|
||||||
* EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary
|
* EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary
|
||||||
* driver. Older graphics drivers do not support Vulkan.
|
* 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
|
* This is the function signature for joystick configuration callback
|
||||||
* functions.
|
* 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`.
|
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
|
||||||
*
|
*
|
||||||
* @sa @ref joystick_event
|
* @sa @ref joystick_event
|
||||||
@ -1247,7 +1257,7 @@ typedef struct GLFWimage
|
|||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_PLATFORM_ERROR.
|
* @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
|
* application to the `Contents/Resources` subdirectory of the application's
|
||||||
* bundle, if present. This can be disabled with a
|
* bundle, if present. This can be disabled with a
|
||||||
* [compile-time option](@ref compile_options_osx).
|
* [compile-time option](@ref compile_options_osx).
|
||||||
@ -1621,6 +1631,9 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
|
|||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
* GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
|
* 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.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref monitor_gamma
|
* @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
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* 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
|
* @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
|
* 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
|
* 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 @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
|
* @pointer_lifetime The specified gamma ramp is copied before this function
|
||||||
* returns.
|
* returns.
|
||||||
*
|
*
|
||||||
@ -1765,8 +1784,8 @@ GLFWAPI void glfwWindowHint(int hint, int value);
|
|||||||
* or _borderless full screen_ windows, see @ref window_windowed_full_screen.
|
* or _borderless full screen_ windows, see @ref window_windowed_full_screen.
|
||||||
*
|
*
|
||||||
* Once you have created the window, you can switch it between windowed and
|
* Once you have created the window, you can switch it between windowed and
|
||||||
* full screen mode with @ref glfwSetWindowMonitor. If the window has an
|
* full screen mode with @ref glfwSetWindowMonitor. This will not affect its
|
||||||
* OpenGL or OpenGL ES context, it will be unaffected.
|
* OpenGL or OpenGL ES context.
|
||||||
*
|
*
|
||||||
* By default, newly created windows use the placement recommended by the
|
* By default, newly created windows use the placement recommended by the
|
||||||
* window system. To create the window at a specific position, make it
|
* 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
|
* @remark @win32 The context to share resources with must not be current on
|
||||||
* any other thread.
|
* 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.
|
* window, but the dock icon will be the same as the application bundle's icon.
|
||||||
* For more information on bundles, see the
|
* For more information on bundles, see the
|
||||||
* [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
|
* [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
|
||||||
* in the Mac Developer Library.
|
* 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
|
* with common commands like Hide, Quit and About. The About entry opens
|
||||||
* a minimal about dialog with information from the application's bundle. The
|
* a minimal about dialog with information from the application's bundle. The
|
||||||
* menu bar can be disabled with a
|
* menu bar can be disabled with a
|
||||||
* [compile-time option](@ref compile_options_osx).
|
* [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`
|
* at full resolution on Retina displays unless the `NSHighResolutionCapable`
|
||||||
* key is enabled in the application bundle's `Info.plist`. For more
|
* key is enabled in the application bundle's `Info.plist`. For more
|
||||||
* information, see
|
* information, see
|
||||||
@ -1841,6 +1860,20 @@ GLFWAPI void glfwWindowHint(int hint, int value);
|
|||||||
* query the final size, position or other attributes directly after window
|
* query the final size, position or other attributes directly after window
|
||||||
* creation.
|
* 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.
|
* @reentrancy This function must not be called from a callback.
|
||||||
*
|
*
|
||||||
* @thread_safety This function must only be called from the main thread.
|
* @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
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* 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.
|
* process events.
|
||||||
*
|
*
|
||||||
* @thread_safety This function must only be called from the main thread.
|
* @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
|
* @pointer_lifetime The specified image data is copied before this function
|
||||||
* returns.
|
* 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
|
* 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
|
* 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/)
|
* [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
|
||||||
* in the Mac Developer Library.
|
* 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.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref window_icon
|
* @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
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* 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.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref window_pos
|
* @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
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* 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.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref window_pos
|
* @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
|
* @remark If you set size limits and an aspect ratio that conflict, the
|
||||||
* results are undefined.
|
* 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.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref window_sizelimits
|
* @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
|
* @remark If you set size limits and an aspect ratio that conflict, the
|
||||||
* results are undefined.
|
* 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.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref window_sizelimits
|
* @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
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* 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.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref window_size
|
* @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
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* 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.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref window_size
|
* @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
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* 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.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref window_iconify
|
* @sa @ref window_iconify
|
||||||
@ -2403,6 +2464,9 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window);
|
|||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* 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.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref window_focus
|
* @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
|
* When a window transitions from full screen to windowed mode, this function
|
||||||
* restores any previous window settings such as whether it is decorated,
|
* 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] window The window whose monitor, size or video mode to set.
|
||||||
* @param[in] monitor The desired monitor, or `NULL` to set windowed mode.
|
* @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
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* 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.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref window_monitor
|
* @sa @ref window_monitor
|
||||||
@ -2575,6 +2649,9 @@ GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window);
|
|||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
* @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.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref window_pos
|
* @sa @ref window_pos
|
||||||
@ -2629,8 +2706,8 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwind
|
|||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
||||||
*
|
*
|
||||||
* @remark @osx Selecting Quit from the application menu will trigger the close
|
* @remark @macos Selecting Quit from the application menu will trigger the
|
||||||
* callback for all windows.
|
* close callback for all windows.
|
||||||
*
|
*
|
||||||
* @thread_safety This function must only be called from the main thread.
|
* @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
|
* 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.
|
* 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
|
* On compositing window systems such as Aero, Compiz, Aqua or Wayland, where
|
||||||
* contents are saved off-screen, this callback may be called only very
|
* the window contents are saved off-screen, this callback may be called only
|
||||||
* infrequently or never at all.
|
* very infrequently or never at all.
|
||||||
*
|
*
|
||||||
* @param[in] window The window whose callback to set.
|
* @param[in] window The window whose callback to set.
|
||||||
* @param[in] cbfun The new callback, or `NULL` to remove the currently 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.
|
* @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.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref window_iconify
|
* @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
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* 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.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref cursor_pos
|
* @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
|
* 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
|
* 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
|
* on Windows. There is a
|
||||||
* [character with modifiers callback](@ref glfwSetCharModsCallback) that
|
* [character with modifiers callback](@ref glfwSetCharModsCallback) that
|
||||||
* receives these events.
|
* receives these events.
|
||||||
@ -3570,6 +3653,8 @@ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun cb
|
|||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
* @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.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref path_drop
|
* @sa @ref path_drop
|
||||||
@ -3584,7 +3669,7 @@ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun);
|
|||||||
*
|
*
|
||||||
* This function returns whether the specified joystick is present.
|
* 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.
|
* @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
@ -3598,7 +3683,7 @@ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun);
|
|||||||
*
|
*
|
||||||
* @ingroup input
|
* @ingroup input
|
||||||
*/
|
*/
|
||||||
GLFWAPI int glfwJoystickPresent(int joy);
|
GLFWAPI int glfwJoystickPresent(int jid);
|
||||||
|
|
||||||
/*! @brief Returns the values of all axes of the specified joystick.
|
/*! @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
|
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||||
* check device presence.
|
* 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
|
* @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
|
* array. This is set to zero if the joystick is not present or an error
|
||||||
* occurred.
|
* occurred.
|
||||||
@ -3632,7 +3717,7 @@ GLFWAPI int glfwJoystickPresent(int joy);
|
|||||||
*
|
*
|
||||||
* @ingroup input
|
* @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.
|
/*! @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
|
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||||
* check device presence.
|
* 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
|
* @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
|
* array. This is set to zero if the joystick is not present or an error
|
||||||
* occurred.
|
* occurred.
|
||||||
@ -3667,7 +3752,7 @@ GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count);
|
|||||||
*
|
*
|
||||||
* @ingroup input
|
* @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.
|
/*! @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
|
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||||
* check device presence.
|
* 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
|
* @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick
|
||||||
* is not present or an [error](@ref error_handling) occurred.
|
* 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
|
* @ingroup input
|
||||||
*/
|
*/
|
||||||
GLFWAPI const char* glfwGetJoystickName(int joy);
|
GLFWAPI const char* glfwGetJoystickName(int jid);
|
||||||
|
|
||||||
/*! @brief Sets the joystick configuration callback.
|
/*! @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
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR.
|
||||||
*
|
*
|
||||||
|
* @remark @wayland Clipboard is currently unimplemented.
|
||||||
|
*
|
||||||
* @pointer_lifetime The specified string is copied before this function
|
* @pointer_lifetime The specified string is copied before this function
|
||||||
* returns.
|
* returns.
|
||||||
*
|
*
|
||||||
@ -3763,6 +3850,8 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
|
|||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR.
|
||||||
*
|
*
|
||||||
|
* @remark @wayland Clipboard is currently unimplemented.
|
||||||
|
*
|
||||||
* @pointer_lifetime The returned string is allocated and freed by GLFW. You
|
* @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
|
* should not free it yourself. It is valid until the next call to @ref
|
||||||
* glfwGetClipboardString or @ref glfwSetClipboardString, or until the library
|
* 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
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_API_UNAVAILABLE.
|
* 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
|
* 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
|
* returned array, as it is an error to specify an extension more than once in
|
||||||
* the `VkInstanceCreateInfo` struct.
|
* 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
|
* @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
|
* should not free it yourself. It is guaranteed to be valid only until the
|
||||||
* library is terminated.
|
* library is terminated.
|
||||||
@ -4226,6 +4318,10 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* p
|
|||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
* GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
|
* 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
|
* @thread_safety This function may be called from any thread. For
|
||||||
* synchronization details of Vulkan objects, see the Vulkan specification.
|
* 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
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
* GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
|
* 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
|
* the Vulkan error code most appropriate for the error. Appropriate use of
|
||||||
* @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should
|
* @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should
|
||||||
* eliminate almost all occurrences of these errors.
|
* 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
|
* @thread_safety This function may be called from any thread. For
|
||||||
* synchronization details of Vulkan objects, see the Vulkan specification.
|
* 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
|
* doing and how to fix problems caused by using them. If you don't, you
|
||||||
* shouldn't be using them.**
|
* 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.
|
* window system API macro and zero or more context creation API macros.
|
||||||
*
|
*
|
||||||
* The chosen backends must match those the library was compiled for. Failure
|
* 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_NSGL`
|
||||||
* * `GLFW_EXPOSE_NATIVE_GLX`
|
* * `GLFW_EXPOSE_NATIVE_GLX`
|
||||||
* * `GLFW_EXPOSE_NATIVE_EGL`
|
* * `GLFW_EXPOSE_NATIVE_EGL`
|
||||||
|
* * `GLFW_EXPOSE_NATIVE_OSMESA`
|
||||||
*
|
*
|
||||||
* These macros select which of the native access functions that are declared
|
* 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
|
* 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)
|
#if defined(GLFW_EXPOSE_NATIVE_EGL)
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#endif
|
#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);
|
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
|
||||||
#endif
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -45,6 +45,12 @@ elseif (_GLFW_MIR)
|
|||||||
set(glfw_SOURCES ${common_SOURCES} mir_init.c mir_monitor.c mir_window.c
|
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
|
linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c
|
||||||
egl_context.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()
|
endif()
|
||||||
|
|
||||||
if (APPLE)
|
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>
|
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
|
@ -272,24 +272,24 @@ static void matchCallback(void* context,
|
|||||||
IOHIDDeviceRef deviceRef)
|
IOHIDDeviceRef deviceRef)
|
||||||
{
|
{
|
||||||
_GLFWjoystickNS* js;
|
_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;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (joy > GLFW_JOYSTICK_LAST)
|
if (jid > GLFW_JOYSTICK_LAST)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
js = _glfw.ns_js + joy;
|
js = _glfw.ns_js + jid;
|
||||||
js->present = GLFW_TRUE;
|
js->present = GLFW_TRUE;
|
||||||
js->deviceRef = deviceRef;
|
js->deviceRef = deviceRef;
|
||||||
|
|
||||||
@ -324,7 +324,7 @@ static void matchCallback(void* context,
|
|||||||
js->buttons = calloc(CFArrayGetCount(js->buttonElements) +
|
js->buttons = calloc(CFArrayGetCount(js->buttonElements) +
|
||||||
CFArrayGetCount(js->hatElements) * 4, 1);
|
CFArrayGetCount(js->hatElements) * 4, 1);
|
||||||
|
|
||||||
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callback for user-initiated joystick removal
|
// Callback for user-initiated joystick removal
|
||||||
@ -334,13 +334,13 @@ static void removeCallback(void* context,
|
|||||||
void* sender,
|
void* sender,
|
||||||
IOHIDDeviceRef deviceRef)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -456,11 +456,11 @@ void _glfwInitJoysticksNS(void)
|
|||||||
//
|
//
|
||||||
void _glfwTerminateJoysticksNS(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);
|
removeJoystick(js);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,15 +473,15 @@ void _glfwTerminateJoysticksNS(void)
|
|||||||
////// GLFW platform API //////
|
////// 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;
|
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))
|
if (!pollJoystickAxisEvents(js))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -489,9 +489,9 @@ const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
|||||||
return js->axes;
|
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))
|
if (!pollJoystickButtonEvents(js))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -500,9 +500,9 @@ const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
|||||||
return js->buttons;
|
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)
|
if (!js->present)
|
||||||
return NULL;
|
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) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
// 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>
|
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
@ -39,6 +39,18 @@
|
|||||||
typedef void* id;
|
typedef void* id;
|
||||||
#endif
|
#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 "posix_tls.h"
|
||||||
#include "cocoa_joystick.h"
|
#include "cocoa_joystick.h"
|
||||||
#include "nsgl_context.h"
|
#include "nsgl_context.h"
|
||||||
@ -74,6 +86,7 @@ typedef struct _GLFWwindowNS
|
|||||||
id object;
|
id object;
|
||||||
id delegate;
|
id delegate;
|
||||||
id view;
|
id view;
|
||||||
|
id layer;
|
||||||
|
|
||||||
GLFWbool maximized;
|
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>
|
// 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>
|
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
@ -32,6 +32,23 @@
|
|||||||
// Needed for _NSGetProgname
|
// Needed for _NSGetProgname
|
||||||
#include <crt_externs.h>
|
#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
|
// Returns the specified standard cursor
|
||||||
//
|
//
|
||||||
@ -63,14 +80,15 @@ static NSUInteger getStyleMask(_GLFWwindow* window)
|
|||||||
NSUInteger styleMask = 0;
|
NSUInteger styleMask = 0;
|
||||||
|
|
||||||
if (window->monitor || !window->decorated)
|
if (window->monitor || !window->decorated)
|
||||||
styleMask |= NSBorderlessWindowMask;
|
styleMask |= NSWindowStyleMaskBorderless;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
styleMask |= NSTitledWindowMask | NSClosableWindowMask |
|
styleMask |= NSWindowStyleMaskTitled |
|
||||||
NSMiniaturizableWindowMask;
|
NSWindowStyleMaskClosable |
|
||||||
|
NSWindowStyleMaskMiniaturizable;
|
||||||
|
|
||||||
if (window->resizable)
|
if (window->resizable)
|
||||||
styleMask |= NSResizableWindowMask;
|
styleMask |= NSWindowStyleMaskResizable;
|
||||||
}
|
}
|
||||||
|
|
||||||
return styleMask;
|
return styleMask;
|
||||||
@ -144,25 +162,25 @@ static void releaseMonitor(_GLFWwindow* window)
|
|||||||
_glfwRestoreVideoModeNS(window->monitor);
|
_glfwRestoreVideoModeNS(window->monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translates OS X key modifiers into GLFW ones
|
// Translates macOS key modifiers into GLFW ones
|
||||||
//
|
//
|
||||||
static int translateFlags(NSUInteger flags)
|
static int translateFlags(NSUInteger flags)
|
||||||
{
|
{
|
||||||
int mods = 0;
|
int mods = 0;
|
||||||
|
|
||||||
if (flags & NSShiftKeyMask)
|
if (flags & NSEventModifierFlagShift)
|
||||||
mods |= GLFW_MOD_SHIFT;
|
mods |= GLFW_MOD_SHIFT;
|
||||||
if (flags & NSControlKeyMask)
|
if (flags & NSEventModifierFlagControl)
|
||||||
mods |= GLFW_MOD_CONTROL;
|
mods |= GLFW_MOD_CONTROL;
|
||||||
if (flags & NSAlternateKeyMask)
|
if (flags & NSEventModifierFlagOption)
|
||||||
mods |= GLFW_MOD_ALT;
|
mods |= GLFW_MOD_ALT;
|
||||||
if (flags & NSCommandKeyMask)
|
if (flags & NSEventModifierFlagCommand)
|
||||||
mods |= GLFW_MOD_SUPER;
|
mods |= GLFW_MOD_SUPER;
|
||||||
|
|
||||||
return mods;
|
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)
|
static int translateKey(unsigned int key)
|
||||||
{
|
{
|
||||||
@ -180,16 +198,16 @@ static NSUInteger translateKeyToModifierFlag(int key)
|
|||||||
{
|
{
|
||||||
case GLFW_KEY_LEFT_SHIFT:
|
case GLFW_KEY_LEFT_SHIFT:
|
||||||
case GLFW_KEY_RIGHT_SHIFT:
|
case GLFW_KEY_RIGHT_SHIFT:
|
||||||
return NSShiftKeyMask;
|
return NSEventModifierFlagShift;
|
||||||
case GLFW_KEY_LEFT_CONTROL:
|
case GLFW_KEY_LEFT_CONTROL:
|
||||||
case GLFW_KEY_RIGHT_CONTROL:
|
case GLFW_KEY_RIGHT_CONTROL:
|
||||||
return NSControlKeyMask;
|
return NSEventModifierFlagControl;
|
||||||
case GLFW_KEY_LEFT_ALT:
|
case GLFW_KEY_LEFT_ALT:
|
||||||
case GLFW_KEY_RIGHT_ALT:
|
case GLFW_KEY_RIGHT_ALT:
|
||||||
return NSAlternateKeyMask;
|
return NSEventModifierFlagOption;
|
||||||
case GLFW_KEY_LEFT_SUPER:
|
case GLFW_KEY_LEFT_SUPER:
|
||||||
case GLFW_KEY_RIGHT_SUPER:
|
case GLFW_KEY_RIGHT_SUPER:
|
||||||
return NSCommandKeyMask;
|
return NSEventModifierFlagCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -413,6 +431,16 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)wantsUpdateLayer
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)makeBackingLayer
|
||||||
|
{
|
||||||
|
return window->ns.layer;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)cursorUpdate:(NSEvent *)event
|
- (void)cursorUpdate:(NSEvent *)event
|
||||||
{
|
{
|
||||||
updateCursorImage(window);
|
updateCursorImage(window);
|
||||||
@ -565,7 +593,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
{
|
{
|
||||||
int action;
|
int action;
|
||||||
const unsigned int modifierFlags =
|
const unsigned int modifierFlags =
|
||||||
[event modifierFlags] & NSDeviceIndependentModifierFlagsMask;
|
[event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
|
||||||
const int key = translateKey([event keyCode]);
|
const int key = translateKey([event keyCode]);
|
||||||
const int mods = translateFlags(modifierFlags);
|
const int mods = translateFlags(modifierFlags);
|
||||||
const NSUInteger keyFlag = translateKeyToModifierFlag(key);
|
const NSUInteger keyFlag = translateKeyToModifierFlag(key);
|
||||||
@ -760,7 +788,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
|
|
||||||
- (BOOL)canBecomeKeyWindow
|
- (BOOL)canBecomeKeyWindow
|
||||||
{
|
{
|
||||||
// Required for NSBorderlessWindowMask windows
|
// Required for NSWindowStyleMaskBorderless windows
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -781,8 +809,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
// down the command key don't get sent to the key window.
|
// down the command key don't get sent to the key window.
|
||||||
- (void)sendEvent:(NSEvent *)event
|
- (void)sendEvent:(NSEvent *)event
|
||||||
{
|
{
|
||||||
if ([event type] == NSKeyUp && ([event modifierFlags] & NSCommandKeyMask))
|
if ([event type] == NSEventTypeKeyUp &&
|
||||||
|
([event modifierFlags] & NSEventModifierFlagCommand))
|
||||||
|
{
|
||||||
[[self keyWindow] sendEvent:event];
|
[[self keyWindow] sendEvent:event];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
[super sendEvent:event];
|
[super sendEvent:event];
|
||||||
}
|
}
|
||||||
@ -866,7 +897,7 @@ static void createMenuBar(void)
|
|||||||
[[appMenu addItemWithTitle:@"Hide Others"
|
[[appMenu addItemWithTitle:@"Hide Others"
|
||||||
action:@selector(hideOtherApplications:)
|
action:@selector(hideOtherApplications:)
|
||||||
keyEquivalent:@"h"]
|
keyEquivalent:@"h"]
|
||||||
setKeyEquivalentModifierMask:NSAlternateKeyMask | NSCommandKeyMask];
|
setKeyEquivalentModifierMask:NSEventModifierFlagOption | NSEventModifierFlagCommand];
|
||||||
[appMenu addItemWithTitle:@"Show All"
|
[appMenu addItemWithTitle:@"Show All"
|
||||||
action:@selector(unhideAllApplications:)
|
action:@selector(unhideAllApplications:)
|
||||||
keyEquivalent:@""];
|
keyEquivalent:@""];
|
||||||
@ -898,7 +929,7 @@ static void createMenuBar(void)
|
|||||||
[[windowMenu addItemWithTitle:@"Enter Full Screen"
|
[[windowMenu addItemWithTitle:@"Enter Full Screen"
|
||||||
action:@selector(toggleFullScreen:)
|
action:@selector(toggleFullScreen:)
|
||||||
keyEquivalent:@"f"]
|
keyEquivalent:@"f"]
|
||||||
setKeyEquivalentModifierMask:NSControlKeyMask | NSCommandKeyMask];
|
setKeyEquivalentModifierMask:NSEventModifierFlagControl | NSEventModifierFlagCommand];
|
||||||
|
|
||||||
// Prior to Snow Leopard, we need to use this oddly-named semi-private API
|
// Prior to Snow Leopard, we need to use this oddly-named semi-private API
|
||||||
// to get the application menu working properly.
|
// to get the application menu working properly.
|
||||||
@ -1011,11 +1042,11 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
|
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
|
||||||
#endif /*_GLFW_USE_RETINA*/
|
#endif /*_GLFW_USE_RETINA*/
|
||||||
|
|
||||||
|
[window->ns.object setContentView:window->ns.view];
|
||||||
[window->ns.object makeFirstResponder:window->ns.view];
|
[window->ns.object makeFirstResponder:window->ns.view];
|
||||||
[window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]];
|
[window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]];
|
||||||
[window->ns.object setDelegate:window->ns.delegate];
|
[window->ns.object setDelegate:window->ns.delegate];
|
||||||
[window->ns.object setAcceptsMouseMovedEvents:YES];
|
[window->ns.object setAcceptsMouseMovedEvents:YES];
|
||||||
[window->ns.object setContentView:window->ns.view];
|
|
||||||
[window->ns.object setRestorable:NO];
|
[window->ns.object setRestorable:NO];
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
@ -1162,7 +1193,7 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
|||||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
|
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
|
||||||
{
|
{
|
||||||
if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
|
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
|
else
|
||||||
[window->ns.object setContentAspectRatio:NSMakeSize(numer, denom)];
|
[window->ns.object setContentAspectRatio:NSMakeSize(numer, denom)];
|
||||||
}
|
}
|
||||||
@ -1358,7 +1389,7 @@ void _glfwPlatformPollEvents(void)
|
|||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
||||||
untilDate:[NSDate distantPast]
|
untilDate:[NSDate distantPast]
|
||||||
inMode:NSDefaultRunLoopMode
|
inMode:NSDefaultRunLoopMode
|
||||||
dequeue:YES];
|
dequeue:YES];
|
||||||
@ -1377,7 +1408,7 @@ void _glfwPlatformWaitEvents(void)
|
|||||||
// I wanted to pass NO to dequeue:, and rely on PollEvents to
|
// I wanted to pass NO to dequeue:, and rely on PollEvents to
|
||||||
// dequeue and send. For reasons not at all clear to me, passing
|
// dequeue and send. For reasons not at all clear to me, passing
|
||||||
// NO to dequeue: causes this method never to return.
|
// NO to dequeue: causes this method never to return.
|
||||||
NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
||||||
untilDate:[NSDate distantFuture]
|
untilDate:[NSDate distantFuture]
|
||||||
inMode:NSDefaultRunLoopMode
|
inMode:NSDefaultRunLoopMode
|
||||||
dequeue:YES];
|
dequeue:YES];
|
||||||
@ -1389,7 +1420,7 @@ void _glfwPlatformWaitEvents(void)
|
|||||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||||
{
|
{
|
||||||
NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout];
|
NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout];
|
||||||
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
||||||
untilDate:date
|
untilDate:date
|
||||||
inMode:NSDefaultRunLoopMode
|
inMode:NSDefaultRunLoopMode
|
||||||
dequeue:YES];
|
dequeue:YES];
|
||||||
@ -1402,7 +1433,7 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
|
|||||||
void _glfwPlatformPostEmptyEvent(void)
|
void _glfwPlatformPostEmptyEvent(void)
|
||||||
{
|
{
|
||||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||||
NSEvent* event = [NSEvent otherEventWithType:NSApplicationDefined
|
NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
|
||||||
location:NSMakePoint(0, 0)
|
location:NSMakePoint(0, 0)
|
||||||
modifierFlags:0
|
modifierFlags:0
|
||||||
timestamp:0
|
timestamp:0
|
||||||
@ -1632,13 +1663,18 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
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,
|
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||||
VkPhysicalDevice device,
|
VkPhysicalDevice device,
|
||||||
uint32_t queuefamily)
|
uint32_t queuefamily)
|
||||||
{
|
{
|
||||||
return GLFW_FALSE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||||
@ -1646,9 +1682,59 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
|||||||
const VkAllocationCallbacks* allocator,
|
const VkAllocationCallbacks* allocator,
|
||||||
VkSurfaceKHR* surface)
|
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;
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW native API //////
|
////// GLFW native API //////
|
||||||
|
@ -44,6 +44,8 @@
|
|||||||
#cmakedefine _GLFW_WAYLAND
|
#cmakedefine _GLFW_WAYLAND
|
||||||
// Define this to 1 if building GLFW for Mir
|
// Define this to 1 if building GLFW for Mir
|
||||||
#cmakedefine _GLFW_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
|
// Define this to 1 if building as a shared library / dynamic library / DLL
|
||||||
#cmakedefine _GLFW_BUILD_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);
|
window->callbacks.drop((GLFWwindow*) window, count, paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwInputJoystickChange(int joy, int event)
|
void _glfwInputJoystickChange(int jid, int event)
|
||||||
{
|
{
|
||||||
if (_glfw.callbacks.joystick)
|
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;
|
return cbfun;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI int glfwJoystickPresent(int joy)
|
GLFWAPI int glfwJoystickPresent(int jid)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
_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 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);
|
assert(count != NULL);
|
||||||
*count = 0;
|
*count = 0;
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_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 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);
|
assert(count != NULL);
|
||||||
*count = 0;
|
*count = 0;
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_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 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);
|
_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 NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _glfwPlatformGetJoystickName(joy);
|
return _glfwPlatformGetJoystickName(jid);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
|
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
|
||||||
|
@ -69,6 +69,7 @@ typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
|
|||||||
#define GL_VERSION 0x1f02
|
#define GL_VERSION 0x1f02
|
||||||
#define GL_NONE 0
|
#define GL_NONE 0
|
||||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||||
|
#define GL_UNSIGNED_BYTE 0x1401
|
||||||
#define GL_EXTENSIONS 0x1f03
|
#define GL_EXTENSIONS 0x1f03
|
||||||
#define GL_NUM_EXTENSIONS 0x821d
|
#define GL_NUM_EXTENSIONS 0x821d
|
||||||
#define GL_CONTEXT_FLAGS 0x821e
|
#define GL_CONTEXT_FLAGS 0x821e
|
||||||
@ -110,6 +111,7 @@ typedef enum VkStructureType
|
|||||||
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
|
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
|
||||||
VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
|
VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
|
||||||
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
|
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
|
||||||
|
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000053000,
|
||||||
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
|
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
|
||||||
} VkStructureType;
|
} VkStructureType;
|
||||||
|
|
||||||
@ -171,6 +173,8 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
|||||||
#include "wl_platform.h"
|
#include "wl_platform.h"
|
||||||
#elif defined(_GLFW_MIR)
|
#elif defined(_GLFW_MIR)
|
||||||
#include "mir_platform.h"
|
#include "mir_platform.h"
|
||||||
|
#elif defined(_GLFW_OSMESA)
|
||||||
|
#include "osmesa_platform.h"
|
||||||
#else
|
#else
|
||||||
#error "No supported window creation API selected"
|
#error "No supported window creation API selected"
|
||||||
#endif
|
#endif
|
||||||
@ -458,6 +462,8 @@ struct _GLFWlibrary
|
|||||||
GLFWbool KHR_surface;
|
GLFWbool KHR_surface;
|
||||||
#if defined(_GLFW_WIN32)
|
#if defined(_GLFW_WIN32)
|
||||||
GLFWbool KHR_win32_surface;
|
GLFWbool KHR_win32_surface;
|
||||||
|
#elif defined(_GLFW_COCOA)
|
||||||
|
GLFWbool MVK_macos_surface;
|
||||||
#elif defined(_GLFW_X11)
|
#elif defined(_GLFW_X11)
|
||||||
GLFWbool KHR_xlib_surface;
|
GLFWbool KHR_xlib_surface;
|
||||||
GLFWbool KHR_xcb_surface;
|
GLFWbool KHR_xcb_surface;
|
||||||
@ -608,22 +614,22 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window);
|
|||||||
/*! @copydoc glfwJoystickPresent
|
/*! @copydoc glfwJoystickPresent
|
||||||
* @ingroup platform
|
* @ingroup platform
|
||||||
*/
|
*/
|
||||||
int _glfwPlatformJoystickPresent(int joy);
|
int _glfwPlatformJoystickPresent(int jid);
|
||||||
|
|
||||||
/*! @copydoc glfwGetJoystickAxes
|
/*! @copydoc glfwGetJoystickAxes
|
||||||
* @ingroup platform
|
* @ingroup platform
|
||||||
*/
|
*/
|
||||||
const float* _glfwPlatformGetJoystickAxes(int joy, int* count);
|
const float* _glfwPlatformGetJoystickAxes(int jid, int* count);
|
||||||
|
|
||||||
/*! @copydoc glfwGetJoystickButtons
|
/*! @copydoc glfwGetJoystickButtons
|
||||||
* @ingroup platform
|
* @ingroup platform
|
||||||
*/
|
*/
|
||||||
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count);
|
const unsigned char* _glfwPlatformGetJoystickButtons(int jid, int* count);
|
||||||
|
|
||||||
/*! @copydoc glfwGetJoystickName
|
/*! @copydoc glfwGetJoystickName
|
||||||
* @ingroup platform
|
* @ingroup platform
|
||||||
*/
|
*/
|
||||||
const char* _glfwPlatformGetJoystickName(int joy);
|
const char* _glfwPlatformGetJoystickName(int jid);
|
||||||
|
|
||||||
/*! @copydoc glfwGetTimerValue
|
/*! @copydoc glfwGetTimerValue
|
||||||
* @ingroup platform
|
* @ingroup platform
|
||||||
@ -961,11 +967,11 @@ void _glfwInputError(int error, const char* format, ...);
|
|||||||
void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
|
void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
|
||||||
|
|
||||||
/*! @brief Notifies shared code of a joystick connection/disconnection event.
|
/*! @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`.
|
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
|
||||||
* @ingroup event
|
* @ingroup event
|
||||||
*/
|
*/
|
||||||
void _glfwInputJoystickChange(int joy, int event);
|
void _glfwInputJoystickChange(int jid, int event);
|
||||||
|
|
||||||
|
|
||||||
//========================================================================
|
//========================================================================
|
||||||
@ -1060,7 +1066,7 @@ GLFWbool _glfwIsPrintable(int key);
|
|||||||
|
|
||||||
/*! @ingroup utility
|
/*! @ingroup utility
|
||||||
*/
|
*/
|
||||||
GLFWbool _glfwInitVulkan(void);
|
GLFWbool _glfwInitVulkan(int mode);
|
||||||
|
|
||||||
/*! @ingroup utility
|
/*! @ingroup utility
|
||||||
*/
|
*/
|
||||||
|
@ -50,25 +50,25 @@ static GLFWbool openJoystickDevice(const char* path)
|
|||||||
{
|
{
|
||||||
char axisCount, buttonCount;
|
char axisCount, buttonCount;
|
||||||
char name[256] = "";
|
char name[256] = "";
|
||||||
int joy, fd, version;
|
int jid, fd, version;
|
||||||
_GLFWjoystickLinux* js;
|
_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;
|
continue;
|
||||||
|
|
||||||
if (strcmp(_glfw.linux_js.js[joy].path, path) == 0)
|
if (strcmp(_glfw.linux_js.js[jid].path, path) == 0)
|
||||||
return GLFW_FALSE;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (joy > GLFW_JOYSTICK_LAST)
|
if (jid > GLFW_JOYSTICK_LAST)
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
fd = open(path, O_RDONLY | O_NONBLOCK);
|
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)
|
if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
|
||||||
strncpy(name, "Unknown", sizeof(name));
|
strncpy(name, "Unknown", sizeof(name));
|
||||||
|
|
||||||
js = _glfw.linux_js.js + joy;
|
js = _glfw.linux_js.js + jid;
|
||||||
js->present = GLFW_TRUE;
|
js->present = GLFW_TRUE;
|
||||||
js->name = strdup(name);
|
js->name = strdup(name);
|
||||||
js->path = strdup(path);
|
js->path = strdup(path);
|
||||||
@ -101,7 +101,7 @@ static GLFWbool openJoystickDevice(const char* path)
|
|||||||
js->buttonCount = (int) buttonCount;
|
js->buttonCount = (int) buttonCount;
|
||||||
js->buttons = calloc(buttonCount, 1);
|
js->buttons = calloc(buttonCount, 1);
|
||||||
|
|
||||||
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
#endif // __linux__
|
#endif // __linux__
|
||||||
@ -304,15 +304,15 @@ void _glfwPollJoystickEvents(void)
|
|||||||
////// GLFW platform API //////
|
////// 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);
|
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))
|
if (!pollJoystickEvents(js))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -320,9 +320,9 @@ const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
|||||||
return js->axes;
|
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))
|
if (!pollJoystickEvents(js))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -330,9 +330,9 @@ const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
|||||||
return js->buttons;
|
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))
|
if (!pollJoystickEvents(js))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -175,10 +175,12 @@ void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window)
|
|||||||
_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
|
_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
|
||||||
{
|
{
|
||||||
_GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
|
_GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
|
||||||
monitor->name = strdup(name);
|
|
||||||
monitor->widthMM = widthMM;
|
monitor->widthMM = widthMM;
|
||||||
monitor->heightMM = heightMM;
|
monitor->heightMM = heightMM;
|
||||||
|
|
||||||
|
if (name)
|
||||||
|
monitor->name = strdup(name);
|
||||||
|
|
||||||
return monitor;
|
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>
|
// 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>
|
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
@ -124,14 +124,14 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"NSGL: OpenGL ES is not available on OS X");
|
"NSGL: OpenGL ES is not available on macOS");
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->major == 3 && ctxconfig->minor < 2)
|
if (ctxconfig->major == 3 && ctxconfig->minor < 2)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_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;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,23 +140,23 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
if (!ctxconfig->forward)
|
if (!ctxconfig->forward)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_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;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE)
|
if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_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;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context robustness modes (GL_KHR_robustness) are not yet supported on
|
// 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
|
// 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_ATTR(x) { attributes[attributeCount++] = x; }
|
||||||
#define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); }
|
#define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); }
|
||||||
@ -206,7 +206,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
fbconfig->greenBits +
|
fbconfig->greenBits +
|
||||||
fbconfig->blueBits;
|
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)
|
if (colorBits == 0)
|
||||||
colorBits = 24;
|
colorBits = 24;
|
||||||
else if (colorBits < 15)
|
else if (colorBits < 15)
|
||||||
@ -225,7 +225,15 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
ADD_ATTR2(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
|
ADD_ATTR2(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
|
||||||
|
|
||||||
if (fbconfig->stereo)
|
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);
|
ADD_ATTR(NSOpenGLPFAStereo);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if (fbconfig->doublebuffer)
|
if (fbconfig->doublebuffer)
|
||||||
ADD_ATTR(NSOpenGLPFADoubleBuffer);
|
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 <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define _GLFW_FIND_LOADER 1
|
||||||
|
#define _GLFW_REQUIRE_LOADER 2
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GLFWbool _glfwInitVulkan(void)
|
GLFWbool _glfwInitVulkan(int mode)
|
||||||
{
|
{
|
||||||
VkResult err;
|
VkResult err;
|
||||||
VkExtensionProperties* ep;
|
VkExtensionProperties* ep;
|
||||||
uint32_t i, count;
|
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)
|
if (_glfw.vk.available)
|
||||||
return GLFW_TRUE;
|
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 (!_glfw.vk.handle)
|
||||||
|
{
|
||||||
|
if (mode == _GLFW_REQUIRE_LOADER)
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
|
||||||
|
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
_glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
|
_glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
|
||||||
_glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
|
_glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
|
||||||
if (!_glfw.vk.GetInstanceProcAddr)
|
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,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"Vulkan: Loader does not export vkGetInstanceProcAddr");
|
"Vulkan: Loader does not export vkGetInstanceProcAddr");
|
||||||
|
#endif
|
||||||
|
|
||||||
_glfwTerminateVulkan();
|
_glfwTerminateVulkan();
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
@ -111,6 +128,9 @@ GLFWbool _glfwInitVulkan(void)
|
|||||||
#if defined(_GLFW_WIN32)
|
#if defined(_GLFW_WIN32)
|
||||||
else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
|
else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
|
||||||
_glfw.vk.KHR_win32_surface = GLFW_TRUE;
|
_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)
|
#elif defined(_GLFW_X11)
|
||||||
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
|
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
|
||||||
_glfw.vk.KHR_xlib_surface = GLFW_TRUE;
|
_glfw.vk.KHR_xlib_surface = GLFW_TRUE;
|
||||||
@ -136,8 +156,10 @@ GLFWbool _glfwInitVulkan(void)
|
|||||||
|
|
||||||
void _glfwTerminateVulkan(void)
|
void _glfwTerminateVulkan(void)
|
||||||
{
|
{
|
||||||
|
#if !defined(_GLFW_VULKAN_STATIC)
|
||||||
if (_glfw.vk.handle)
|
if (_glfw.vk.handle)
|
||||||
_glfw_dlclose(_glfw.vk.handle);
|
_glfw_dlclose(_glfw.vk.handle);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwGetVulkanResultString(VkResult result)
|
const char* _glfwGetVulkanResultString(VkResult result)
|
||||||
@ -203,7 +225,7 @@ const char* _glfwGetVulkanResultString(VkResult result)
|
|||||||
GLFWAPI int glfwVulkanSupported(void)
|
GLFWAPI int glfwVulkanSupported(void)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
return _glfwInitVulkan();
|
return _glfwInitVulkan(_GLFW_FIND_LOADER);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
|
GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
|
||||||
@ -212,11 +234,11 @@ GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
|
|||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
if (!_glfwInitVulkan())
|
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||||
{
|
return NULL;
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
|
|
||||||
|
if (!_glfw.vk.extensions[0])
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
*count = 2;
|
*count = 2;
|
||||||
return (const char**) _glfw.vk.extensions;
|
return (const char**) _glfw.vk.extensions;
|
||||||
@ -229,15 +251,20 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
|
|||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
if (!_glfwInitVulkan())
|
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
|
proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
|
||||||
|
#if defined(_GLFW_VULKAN_STATIC)
|
||||||
|
if (!proc)
|
||||||
|
{
|
||||||
|
if (strcmp(procname, "vkGetInstanceProcAddr") == 0)
|
||||||
|
return (GLFWvkproc) vkGetInstanceProcAddr;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (!proc)
|
if (!proc)
|
||||||
proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
|
proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
|
||||||
|
#endif
|
||||||
|
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
@ -248,11 +275,8 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
|
|||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
|
||||||
if (!_glfwInitVulkan())
|
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
|
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
if (!_glfw.vk.extensions[0])
|
if (!_glfw.vk.extensions[0])
|
||||||
{
|
{
|
||||||
@ -279,11 +303,8 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
|
|||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
|
_GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
|
||||||
|
|
||||||
if (!_glfwInitVulkan())
|
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
|
|
||||||
return VK_ERROR_INITIALIZATION_FAILED;
|
return VK_ERROR_INITIALIZATION_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
if (!_glfw.vk.extensions[0])
|
if (!_glfw.vk.extensions[0])
|
||||||
{
|
{
|
||||||
|
@ -304,6 +304,7 @@ static void createKeyTables(void)
|
|||||||
//
|
//
|
||||||
static HWND createHelperWindow(void)
|
static HWND createHelperWindow(void)
|
||||||
{
|
{
|
||||||
|
MSG msg;
|
||||||
HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
|
HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
|
||||||
_GLFW_WNDCLASSNAME,
|
_GLFW_WNDCLASSNAME,
|
||||||
L"GLFW helper window",
|
L"GLFW helper window",
|
||||||
@ -336,6 +337,12 @@ static HWND createHelperWindow(void)
|
|||||||
DEVICE_NOTIFY_WINDOW_HANDLE);
|
DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
|
||||||
|
{
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessageW(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,8 +430,6 @@ int _glfwPlatformInit(void)
|
|||||||
if (!_glfw.win32.helperWindowHandle)
|
if (!_glfw.win32.helperWindowHandle)
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
_glfwPlatformPollEvents();
|
|
||||||
|
|
||||||
_glfwInitTimerWin32();
|
_glfwInitTimerWin32();
|
||||||
_glfwInitJoysticksWin32();
|
_glfwInitJoysticksWin32();
|
||||||
|
|
||||||
|
@ -332,26 +332,26 @@ static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
|
|||||||
//
|
//
|
||||||
static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||||
{
|
{
|
||||||
int joy = 0;
|
int jid = 0;
|
||||||
DIDEVCAPS dc;
|
DIDEVCAPS dc;
|
||||||
DIPROPDWORD dipd;
|
DIPROPDWORD dipd;
|
||||||
IDirectInputDevice8* device;
|
IDirectInputDevice8* device;
|
||||||
_GLFWobjenumWin32 data;
|
_GLFWobjenumWin32 data;
|
||||||
_GLFWjoystickWin32* js;
|
_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;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (joy > GLFW_JOYSTICK_LAST)
|
if (jid > GLFW_JOYSTICK_LAST)
|
||||||
return DIENUM_STOP;
|
return DIENUM_STOP;
|
||||||
|
|
||||||
if (supportsXInput(&di->guidProduct))
|
if (supportsXInput(&di->guidProduct))
|
||||||
@ -362,14 +362,14 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|||||||
&device,
|
&device,
|
||||||
NULL)))
|
NULL)))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "DI: Failed to create device");
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create device");
|
||||||
return DIENUM_CONTINUE;
|
return DIENUM_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
|
if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"DI: Failed to set device data format");
|
"Win32: Failed to set device data format");
|
||||||
|
|
||||||
IDirectInputDevice8_Release(device);
|
IDirectInputDevice8_Release(device);
|
||||||
return DIENUM_CONTINUE;
|
return DIENUM_CONTINUE;
|
||||||
@ -381,7 +381,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|||||||
if (FAILED(IDirectInputDevice8_GetCapabilities(device, &dc)))
|
if (FAILED(IDirectInputDevice8_GetCapabilities(device, &dc)))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"DI: Failed to query device capabilities");
|
"Win32: Failed to query device capabilities");
|
||||||
|
|
||||||
IDirectInputDevice8_Release(device);
|
IDirectInputDevice8_Release(device);
|
||||||
return DIENUM_CONTINUE;
|
return DIENUM_CONTINUE;
|
||||||
@ -398,7 +398,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|||||||
&dipd.diph)))
|
&dipd.diph)))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"DI: Failed to set device axis mode");
|
"Win32: Failed to set device axis mode");
|
||||||
|
|
||||||
IDirectInputDevice8_Release(device);
|
IDirectInputDevice8_Release(device);
|
||||||
return DIENUM_CONTINUE;
|
return DIENUM_CONTINUE;
|
||||||
@ -415,7 +415,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|||||||
DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
|
DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"DI: Failed to enumerate device objects");
|
"Win32: Failed to enumerate device objects");
|
||||||
|
|
||||||
IDirectInputDevice8_Release(device);
|
IDirectInputDevice8_Release(device);
|
||||||
free(data.objects);
|
free(data.objects);
|
||||||
@ -426,7 +426,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|||||||
sizeof(_GLFWjoyobjectWin32),
|
sizeof(_GLFWjoyobjectWin32),
|
||||||
compareJoystickObjects);
|
compareJoystickObjects);
|
||||||
|
|
||||||
js = _glfw.win32_js + joy;
|
js = _glfw.win32_js + jid;
|
||||||
js->device = device;
|
js->device = device;
|
||||||
js->guid = di->guidInstance;
|
js->guid = di->guidInstance;
|
||||||
js->axisCount = data.axisCount + data.sliderCount;
|
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->name = _glfwCreateUTF8FromWideStringWin32(di->tszInstanceName);
|
||||||
js->present = GLFW_TRUE;
|
js->present = GLFW_TRUE;
|
||||||
|
|
||||||
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
||||||
return DIENUM_CONTINUE;
|
return DIENUM_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,33 +447,33 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|||||||
//
|
//
|
||||||
static GLFWbool openXinputDevice(DWORD index)
|
static GLFWbool openXinputDevice(DWORD index)
|
||||||
{
|
{
|
||||||
int joy;
|
int jid;
|
||||||
XINPUT_CAPABILITIES xic;
|
XINPUT_CAPABILITIES xic;
|
||||||
_GLFWjoystickWin32* js;
|
_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 &&
|
if (_glfw.win32_js[jid].present &&
|
||||||
_glfw.win32_js[joy].device == NULL &&
|
_glfw.win32_js[jid].device == NULL &&
|
||||||
_glfw.win32_js[joy].index == index)
|
_glfw.win32_js[jid].index == index)
|
||||||
{
|
{
|
||||||
return GLFW_FALSE;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (joy > GLFW_JOYSTICK_LAST)
|
if (jid > GLFW_JOYSTICK_LAST)
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
if (_glfw_XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
if (_glfw_XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
js = _glfw.win32_js + joy;
|
js = _glfw.win32_js + jid;
|
||||||
js->axisCount = 6;
|
js->axisCount = 6;
|
||||||
js->axes = calloc(js->axisCount, sizeof(float));
|
js->axes = calloc(js->axisCount, sizeof(float));
|
||||||
js->buttonCount = 14;
|
js->buttonCount = 14;
|
||||||
@ -482,7 +482,7 @@ static GLFWbool openXinputDevice(DWORD index)
|
|||||||
js->name = strdup(getDeviceDescription(&xic));
|
js->name = strdup(getDeviceDescription(&xic));
|
||||||
js->index = index;
|
js->index = index;
|
||||||
|
|
||||||
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
_glfwInputJoystickChange(jid, GLFW_CONNECTED);
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
@ -664,7 +664,7 @@ void _glfwInitJoysticksWin32(void)
|
|||||||
NULL)))
|
NULL)))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"DI: Failed to create interface");
|
"Win32: Failed to create interface");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,10 +675,10 @@ void _glfwInitJoysticksWin32(void)
|
|||||||
//
|
//
|
||||||
void _glfwTerminateJoysticksWin32(void)
|
void _glfwTerminateJoysticksWin32(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++)
|
||||||
closeJoystick(_glfw.win32_js + joy);
|
closeJoystick(_glfw.win32_js + jid);
|
||||||
|
|
||||||
if (_glfw.win32.dinput8.api)
|
if (_glfw.win32.dinput8.api)
|
||||||
IDirectInput8_Release(_glfw.win32.dinput8.api);
|
IDirectInput8_Release(_glfw.win32.dinput8.api);
|
||||||
@ -715,10 +715,10 @@ void _glfwDetectJoystickConnectionWin32(void)
|
|||||||
//
|
//
|
||||||
void _glfwDetectJoystickDisconnectionWin32(void)
|
void _glfwDetectJoystickDisconnectionWin32(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++)
|
||||||
pollJoystickState(_glfw.win32_js + joy, _GLFW_PRESENCE_ONLY);
|
pollJoystickState(_glfw.win32_js + jid, _GLFW_PRESENCE_ONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -726,15 +726,15 @@ void _glfwDetectJoystickDisconnectionWin32(void)
|
|||||||
////// GLFW platform API //////
|
////// 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);
|
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))
|
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -742,9 +742,9 @@ const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
|||||||
return js->axes;
|
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))
|
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -752,9 +752,9 @@ const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
|||||||
return js->buttons;
|
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))
|
if (!pollJoystickState(js, _GLFW_PRESENCE_ONLY))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -668,7 +668,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
case WM_MOUSEHWHEEL:
|
case WM_MOUSEHWHEEL:
|
||||||
{
|
{
|
||||||
// This message is only sent on Windows Vista and later
|
// 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);
|
_glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
132
src/wl_init.c
132
src/wl_init.c
@ -128,7 +128,7 @@ static void pointerHandleAxis(void* data,
|
|||||||
wl_fixed_t value)
|
wl_fixed_t value)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
||||||
double scroll_factor;
|
double scrollFactor;
|
||||||
double x, y;
|
double x, y;
|
||||||
|
|
||||||
if (!window)
|
if (!window)
|
||||||
@ -137,17 +137,17 @@ static void pointerHandleAxis(void* data,
|
|||||||
/* Wayland scroll events are in pointer motion coordinate space (think
|
/* Wayland scroll events are in pointer motion coordinate space (think
|
||||||
* two finger scroll). The factor 10 is commonly used to convert to
|
* two finger scroll). The factor 10 is commonly used to convert to
|
||||||
* "scroll step means 1.0. */
|
* "scroll step means 1.0. */
|
||||||
scroll_factor = 1.0/10.0;
|
scrollFactor = 1.0/10.0;
|
||||||
|
|
||||||
switch (axis)
|
switch (axis)
|
||||||
{
|
{
|
||||||
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
|
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
|
||||||
x = wl_fixed_to_double(value) * scroll_factor;
|
x = wl_fixed_to_double(value) * scrollFactor;
|
||||||
y = 0.0;
|
y = 0.0;
|
||||||
break;
|
break;
|
||||||
case WL_POINTER_AXIS_VERTICAL_SCROLL:
|
case WL_POINTER_AXIS_VERTICAL_SCROLL:
|
||||||
x = 0.0;
|
x = 0.0;
|
||||||
y = wl_fixed_to_double(value) * scroll_factor;
|
y = wl_fixed_to_double(value) * scrollFactor;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -172,7 +172,10 @@ static void keyboardHandleKeymap(void* data,
|
|||||||
{
|
{
|
||||||
struct xkb_keymap* keymap;
|
struct xkb_keymap* keymap;
|
||||||
struct xkb_state* state;
|
struct xkb_state* state;
|
||||||
|
struct xkb_compose_table* composeTable;
|
||||||
|
struct xkb_compose_state* composeState;
|
||||||
char* mapStr;
|
char* mapStr;
|
||||||
|
const char* locale;
|
||||||
|
|
||||||
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
|
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
|
||||||
{
|
{
|
||||||
@ -186,7 +189,7 @@ static void keyboardHandleKeymap(void* data,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
keymap = xkb_map_new_from_string(_glfw.wl.xkb.context,
|
keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context,
|
||||||
mapStr,
|
mapStr,
|
||||||
XKB_KEYMAP_FORMAT_TEXT_V1,
|
XKB_KEYMAP_FORMAT_TEXT_V1,
|
||||||
0);
|
0);
|
||||||
@ -205,23 +208,52 @@ static void keyboardHandleKeymap(void* data,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Failed to create XKB state");
|
"Wayland: Failed to create XKB state");
|
||||||
xkb_map_unref(keymap);
|
xkb_keymap_unref(keymap);
|
||||||
return;
|
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_keymap_unref(_glfw.wl.xkb.keymap);
|
||||||
xkb_state_unref(_glfw.wl.xkb.state);
|
xkb_state_unref(_glfw.wl.xkb.state);
|
||||||
_glfw.wl.xkb.keymap = keymap;
|
_glfw.wl.xkb.keymap = keymap;
|
||||||
_glfw.wl.xkb.state = state;
|
_glfw.wl.xkb.state = state;
|
||||||
|
|
||||||
_glfw.wl.xkb.control_mask =
|
_glfw.wl.xkb.controlMask =
|
||||||
1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Control");
|
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control");
|
||||||
_glfw.wl.xkb.alt_mask =
|
_glfw.wl.xkb.altMask =
|
||||||
1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
|
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
|
||||||
_glfw.wl.xkb.shift_mask =
|
_glfw.wl.xkb.shiftMask =
|
||||||
1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
|
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
|
||||||
_glfw.wl.xkb.super_mask =
|
_glfw.wl.xkb.superMask =
|
||||||
1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
|
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboardHandleEnter(void* data,
|
static void keyboardHandleEnter(void* data,
|
||||||
@ -258,18 +290,40 @@ static int toGLFWKeyCode(uint32_t key)
|
|||||||
return GLFW_KEY_UNKNOWN;
|
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)
|
static void inputChar(_GLFWwindow* window, uint32_t key)
|
||||||
{
|
{
|
||||||
uint32_t code, num_syms;
|
uint32_t code, numSyms;
|
||||||
long cp;
|
long cp;
|
||||||
const xkb_keysym_t *syms;
|
const xkb_keysym_t *syms;
|
||||||
|
xkb_keysym_t sym;
|
||||||
|
|
||||||
code = key + 8;
|
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)
|
if (cp != -1)
|
||||||
{
|
{
|
||||||
const int mods = _glfw.wl.xkb.modifiers;
|
const int mods = _glfw.wl.xkb.modifiers;
|
||||||
@ -327,15 +381,17 @@ static void keyboardHandleModifiers(void* data,
|
|||||||
group);
|
group);
|
||||||
|
|
||||||
mask = xkb_state_serialize_mods(_glfw.wl.xkb.state,
|
mask = xkb_state_serialize_mods(_glfw.wl.xkb.state,
|
||||||
XKB_STATE_DEPRESSED |
|
XKB_STATE_MODS_DEPRESSED |
|
||||||
XKB_STATE_LATCHED);
|
XKB_STATE_LAYOUT_DEPRESSED |
|
||||||
if (mask & _glfw.wl.xkb.control_mask)
|
XKB_STATE_MODS_LATCHED |
|
||||||
|
XKB_STATE_LAYOUT_LATCHED);
|
||||||
|
if (mask & _glfw.wl.xkb.controlMask)
|
||||||
modifiers |= GLFW_MOD_CONTROL;
|
modifiers |= GLFW_MOD_CONTROL;
|
||||||
if (mask & _glfw.wl.xkb.alt_mask)
|
if (mask & _glfw.wl.xkb.altMask)
|
||||||
modifiers |= GLFW_MOD_ALT;
|
modifiers |= GLFW_MOD_ALT;
|
||||||
if (mask & _glfw.wl.xkb.shift_mask)
|
if (mask & _glfw.wl.xkb.shiftMask)
|
||||||
modifiers |= GLFW_MOD_SHIFT;
|
modifiers |= GLFW_MOD_SHIFT;
|
||||||
if (mask & _glfw.wl.xkb.super_mask)
|
if (mask & _glfw.wl.xkb.superMask)
|
||||||
modifiers |= GLFW_MOD_SUPER;
|
modifiers |= GLFW_MOD_SUPER;
|
||||||
_glfw.wl.xkb.modifiers = modifiers;
|
_glfw.wl.xkb.modifiers = modifiers;
|
||||||
}
|
}
|
||||||
@ -387,10 +443,10 @@ static void registryHandleGlobal(void* data,
|
|||||||
{
|
{
|
||||||
if (strcmp(interface, "wl_compositor") == 0)
|
if (strcmp(interface, "wl_compositor") == 0)
|
||||||
{
|
{
|
||||||
_glfw.wl.wl_compositor_version = min(3, version);
|
_glfw.wl.compositorVersion = min(3, version);
|
||||||
_glfw.wl.compositor =
|
_glfw.wl.compositor =
|
||||||
wl_registry_bind(registry, name, &wl_compositor_interface,
|
wl_registry_bind(registry, name, &wl_compositor_interface,
|
||||||
_glfw.wl.wl_compositor_version);
|
_glfw.wl.compositorVersion);
|
||||||
}
|
}
|
||||||
else if (strcmp(interface, "wl_shm") == 0)
|
else if (strcmp(interface, "wl_shm") == 0)
|
||||||
{
|
{
|
||||||
@ -643,17 +699,39 @@ void _glfwPlatformTerminate(void)
|
|||||||
_glfwTerminateJoysticksLinux();
|
_glfwTerminateJoysticksLinux();
|
||||||
_glfwTerminateThreadLocalStoragePOSIX();
|
_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)
|
if (_glfw.wl.cursorTheme)
|
||||||
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
|
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
|
||||||
if (_glfw.wl.cursorSurface)
|
if (_glfw.wl.cursorSurface)
|
||||||
wl_surface_destroy(_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)
|
if (_glfw.wl.registry)
|
||||||
wl_registry_destroy(_glfw.wl.registry);
|
wl_registry_destroy(_glfw.wl.registry);
|
||||||
if (_glfw.wl.display)
|
if (_glfw.wl.display)
|
||||||
|
{
|
||||||
wl_display_flush(_glfw.wl.display);
|
wl_display_flush(_glfw.wl.display);
|
||||||
if (_glfw.wl.display)
|
|
||||||
wl_display_disconnect(_glfw.wl.display);
|
wl_display_disconnect(_glfw.wl.display);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
{
|
{
|
||||||
|
@ -50,11 +50,21 @@ static void geometry(void* data,
|
|||||||
int32_t transform)
|
int32_t transform)
|
||||||
{
|
{
|
||||||
struct _GLFWmonitor *monitor = data;
|
struct _GLFWmonitor *monitor = data;
|
||||||
|
char* name;
|
||||||
|
size_t nameLength;
|
||||||
|
|
||||||
monitor->wl.x = x;
|
monitor->wl.x = x;
|
||||||
monitor->wl.y = y;
|
monitor->wl.y = y;
|
||||||
monitor->widthMM = physicalWidth;
|
monitor->widthMM = physicalWidth;
|
||||||
monitor->heightMM = physicalHeight;
|
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,
|
static void mode(void* data,
|
||||||
@ -102,7 +112,7 @@ static void scale(void* data,
|
|||||||
monitor->wl.scale = factor;
|
monitor->wl.scale = factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_output_listener output_listener = {
|
static const struct wl_output_listener outputListener = {
|
||||||
geometry,
|
geometry,
|
||||||
mode,
|
mode,
|
||||||
done,
|
done,
|
||||||
@ -118,10 +128,6 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
|
|||||||
{
|
{
|
||||||
_GLFWmonitor *monitor;
|
_GLFWmonitor *monitor;
|
||||||
struct wl_output *output;
|
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)
|
if (version < 2)
|
||||||
{
|
{
|
||||||
@ -130,7 +136,8 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
|
|||||||
return;
|
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,
|
output = wl_registry_bind(_glfw.wl.registry,
|
||||||
name,
|
name,
|
||||||
@ -148,7 +155,7 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
|
|||||||
monitor->wl.scale = 1;
|
monitor->wl.scale = 1;
|
||||||
|
|
||||||
monitor->wl.output = output;
|
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)
|
if (_glfw.wl.monitorsCount + 1 >= _glfw.wl.monitorsSize)
|
||||||
{
|
{
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#include <xkbcommon/xkbcommon-compose.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
|
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
|
||||||
@ -83,7 +84,7 @@ typedef struct _GLFWwindowWayland
|
|||||||
GLFWbool maximized;
|
GLFWbool maximized;
|
||||||
struct wl_surface* surface;
|
struct wl_surface* surface;
|
||||||
struct wl_egl_window* native;
|
struct wl_egl_window* native;
|
||||||
struct wl_shell_surface* shell_surface;
|
struct wl_shell_surface* shellSurface;
|
||||||
struct wl_callback* callback;
|
struct wl_callback* callback;
|
||||||
|
|
||||||
_GLFWcursor* currentCursor;
|
_GLFWcursor* currentCursor;
|
||||||
@ -119,7 +120,7 @@ typedef struct _GLFWlibraryWayland
|
|||||||
struct zwp_relative_pointer_manager_v1* relativePointerManager;
|
struct zwp_relative_pointer_manager_v1* relativePointerManager;
|
||||||
struct zwp_pointer_constraints_v1* pointerConstraints;
|
struct zwp_pointer_constraints_v1* pointerConstraints;
|
||||||
|
|
||||||
int wl_compositor_version;
|
int compositorVersion;
|
||||||
|
|
||||||
struct wl_cursor_theme* cursorTheme;
|
struct wl_cursor_theme* cursorTheme;
|
||||||
struct wl_surface* cursorSurface;
|
struct wl_surface* cursorSurface;
|
||||||
@ -136,10 +137,11 @@ typedef struct _GLFWlibraryWayland
|
|||||||
struct xkb_context* context;
|
struct xkb_context* context;
|
||||||
struct xkb_keymap* keymap;
|
struct xkb_keymap* keymap;
|
||||||
struct xkb_state* state;
|
struct xkb_state* state;
|
||||||
xkb_mod_mask_t control_mask;
|
struct xkb_compose_state* composeState;
|
||||||
xkb_mod_mask_t alt_mask;
|
xkb_mod_mask_t controlMask;
|
||||||
xkb_mod_mask_t shift_mask;
|
xkb_mod_mask_t altMask;
|
||||||
xkb_mod_mask_t super_mask;
|
xkb_mod_mask_t shiftMask;
|
||||||
|
xkb_mod_mask_t superMask;
|
||||||
unsigned int modifiers;
|
unsigned int modifiers;
|
||||||
} xkb;
|
} xkb;
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ static void checkScaleChange(_GLFWwindow* window)
|
|||||||
int monitorScale;
|
int monitorScale;
|
||||||
|
|
||||||
// Check if we will be able to set the buffer scale or not.
|
// 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;
|
return;
|
||||||
|
|
||||||
// Get the scale factor from the highest scale monitor.
|
// Get the scale factor from the highest scale monitor.
|
||||||
@ -220,33 +220,33 @@ static GLFWbool createSurface(_GLFWwindow* window,
|
|||||||
|
|
||||||
static GLFWbool createShellSurface(_GLFWwindow* window)
|
static GLFWbool createShellSurface(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
window->wl.shell_surface = wl_shell_get_shell_surface(_glfw.wl.shell,
|
window->wl.shellSurface = wl_shell_get_shell_surface(_glfw.wl.shell,
|
||||||
window->wl.surface);
|
window->wl.surface);
|
||||||
if (!window->wl.shell_surface)
|
if (!window->wl.shellSurface)
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
wl_shell_surface_add_listener(window->wl.shell_surface,
|
wl_shell_surface_add_listener(window->wl.shellSurface,
|
||||||
&shellSurfaceListener,
|
&shellSurfaceListener,
|
||||||
window);
|
window);
|
||||||
|
|
||||||
if (window->wl.title)
|
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)
|
if (window->monitor)
|
||||||
{
|
{
|
||||||
wl_shell_surface_set_fullscreen(
|
wl_shell_surface_set_fullscreen(
|
||||||
window->wl.shell_surface,
|
window->wl.shellSurface,
|
||||||
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
|
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
|
||||||
0,
|
0,
|
||||||
window->monitor->wl.output);
|
window->monitor->wl.output);
|
||||||
}
|
}
|
||||||
else if (window->wl.maximized)
|
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
|
else
|
||||||
{
|
{
|
||||||
wl_shell_surface_set_toplevel(window->wl.shell_surface);
|
wl_shell_surface_set_toplevel(window->wl.shellSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
@ -411,7 +411,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
window->wl.shell_surface = NULL;
|
window->wl.shellSurface = NULL;
|
||||||
window->wl.visible = GLFW_FALSE;
|
window->wl.visible = GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,8 +443,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|||||||
if (window->wl.native)
|
if (window->wl.native)
|
||||||
wl_egl_window_destroy(window->wl.native);
|
wl_egl_window_destroy(window->wl.native);
|
||||||
|
|
||||||
if (window->wl.shell_surface)
|
if (window->wl.shellSurface)
|
||||||
wl_shell_surface_destroy(window->wl.shell_surface);
|
wl_shell_surface_destroy(window->wl.shellSurface);
|
||||||
|
|
||||||
if (window->wl.surface)
|
if (window->wl.surface)
|
||||||
wl_surface_destroy(window->wl.surface);
|
wl_surface_destroy(window->wl.surface);
|
||||||
@ -458,8 +458,8 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
|||||||
if (window->wl.title)
|
if (window->wl.title)
|
||||||
free(window->wl.title);
|
free(window->wl.title);
|
||||||
window->wl.title = strdup(title);
|
window->wl.title = strdup(title);
|
||||||
if (window->wl.shell_surface)
|
if (window->wl.shellSurface)
|
||||||
wl_shell_surface_set_title(window->wl.shell_surface, title);
|
wl_shell_surface_set_title(window->wl.shellSurface, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
||||||
@ -546,8 +546,8 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
|||||||
// TODO: also do the same for iconified.
|
// TODO: also do the same for iconified.
|
||||||
if (window->monitor || window->wl.maximized)
|
if (window->monitor || window->wl.maximized)
|
||||||
{
|
{
|
||||||
if (window->wl.shell_surface)
|
if (window->wl.shellSurface)
|
||||||
wl_shell_surface_set_toplevel(window->wl.shell_surface);
|
wl_shell_surface_set_toplevel(window->wl.shellSurface);
|
||||||
|
|
||||||
window->wl.maximized = GLFW_FALSE;
|
window->wl.maximized = GLFW_FALSE;
|
||||||
}
|
}
|
||||||
@ -557,10 +557,10 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
if (!window->monitor && !window->wl.maximized)
|
if (!window->monitor && !window->wl.maximized)
|
||||||
{
|
{
|
||||||
if (window->wl.shell_surface)
|
if (window->wl.shellSurface)
|
||||||
{
|
{
|
||||||
// Let the compositor select the best output.
|
// 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;
|
window->wl.maximized = GLFW_TRUE;
|
||||||
}
|
}
|
||||||
@ -570,7 +570,7 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
if (!window->monitor)
|
if (!window->monitor)
|
||||||
{
|
{
|
||||||
if (!window->wl.shell_surface)
|
if (!window->wl.shellSurface)
|
||||||
createShellSurface(window);
|
createShellSurface(window);
|
||||||
window->wl.visible = GLFW_TRUE;
|
window->wl.visible = GLFW_TRUE;
|
||||||
}
|
}
|
||||||
@ -580,8 +580,8 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
if (!window->monitor)
|
if (!window->monitor)
|
||||||
{
|
{
|
||||||
if (window->wl.shell_surface)
|
if (window->wl.shellSurface)
|
||||||
wl_shell_surface_destroy(window->wl.shell_surface);
|
wl_shell_surface_destroy(window->wl.shellSurface);
|
||||||
window->wl.visible = GLFW_FALSE;
|
window->wl.visible = GLFW_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -601,14 +601,14 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
|||||||
if (monitor)
|
if (monitor)
|
||||||
{
|
{
|
||||||
wl_shell_surface_set_fullscreen(
|
wl_shell_surface_set_fullscreen(
|
||||||
window->wl.shell_surface,
|
window->wl.shellSurface,
|
||||||
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
|
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
|
||||||
refreshRate * 1000, // Convert Hz to mHz.
|
refreshRate * 1000, // Convert Hz to mHz.
|
||||||
monitor->wl.output);
|
monitor->wl.output);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wl_shell_surface_set_toplevel(window->wl.shell_surface);
|
wl_shell_surface_set_toplevel(window->wl.shellSurface);
|
||||||
}
|
}
|
||||||
_glfwInputWindowMonitorChange(window, monitor);
|
_glfwInputWindowMonitorChange(window, monitor);
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ if (VULKAN_FOUND)
|
|||||||
add_executable(vulkan WIN32 vulkan.c ${ICON})
|
add_executable(vulkan WIN32 vulkan.c ${ICON})
|
||||||
target_include_directories(vulkan PRIVATE "${VULKAN_INCLUDE_DIR}")
|
target_include_directories(vulkan PRIVATE "${VULKAN_INCLUDE_DIR}")
|
||||||
if (NOT GLFW_VULKAN_STATIC)
|
if (NOT GLFW_VULKAN_STATIC)
|
||||||
target_link_libraries(vulkan "${VULKAN_LIBRARY}")
|
target_link_libraries(vulkan "${VULKAN_LIBRARY}" ${GLFW_VULKAN_DEPS})
|
||||||
endif()
|
endif()
|
||||||
list(APPEND WINDOWS_BINARIES vulkan)
|
list(APPEND WINDOWS_BINARIES vulkan)
|
||||||
endif()
|
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)
|
if (event == GLFW_CONNECTED)
|
||||||
{
|
{
|
||||||
int axisCount, buttonCount;
|
int axisCount, buttonCount;
|
||||||
|
|
||||||
glfwGetJoystickAxes(joy, &axisCount);
|
glfwGetJoystickAxes(jid, &axisCount);
|
||||||
glfwGetJoystickButtons(joy, &buttonCount);
|
glfwGetJoystickButtons(jid, &buttonCount);
|
||||||
|
|
||||||
printf("%08x at %0.3f: Joystick %i (%s) was connected with %i axes and %i buttons\n",
|
printf("%08x at %0.3f: Joystick %i (%s) was connected with %i axes and %i buttons\n",
|
||||||
counter++, glfwGetTime(),
|
counter++, glfwGetTime(),
|
||||||
joy,
|
jid,
|
||||||
glfwGetJoystickName(joy),
|
glfwGetJoystickName(jid),
|
||||||
axisCount,
|
axisCount,
|
||||||
buttonCount);
|
buttonCount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("%08x at %0.3f: Joystick %i was disconnected\n",
|
printf("%08x at %0.3f: Joystick %i was disconnected\n",
|
||||||
counter++, glfwGetTime(), joy);
|
counter++, glfwGetTime(), jid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,8 +46,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
static int windowed_xpos, windowed_ypos, windowed_width, windowed_height;
|
|
||||||
|
|
||||||
static void error_callback(int error, const char* description)
|
static void error_callback(int error, const char* description)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error: %s\n", description);
|
fprintf(stderr, "Error: %s\n", description);
|
||||||
|
@ -820,9 +820,14 @@ int main(int argc, char** argv)
|
|||||||
re = glfwGetRequiredInstanceExtensions(&re_count);
|
re = glfwGetRequiredInstanceExtensions(&re_count);
|
||||||
|
|
||||||
printf("Vulkan required instance extensions:");
|
printf("Vulkan required instance extensions:");
|
||||||
|
if (re)
|
||||||
|
{
|
||||||
for (i = 0; i < re_count; i++)
|
for (i = 0; i < re_count; i++)
|
||||||
printf(" %s", re[i]);
|
printf(" %s", re[i]);
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf(" missing\n");
|
||||||
|
|
||||||
if (list_extensions)
|
if (list_extensions)
|
||||||
list_vulkan_instance_extensions();
|
list_vulkan_instance_extensions();
|
||||||
|
@ -60,17 +60,17 @@ static void error_callback(int error, const char* description)
|
|||||||
fprintf(stderr, "Error: %s\n", 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)
|
if (event == GLFW_CONNECTED)
|
||||||
joysticks[joystick_count++] = joy;
|
joysticks[joystick_count++] = jid;
|
||||||
else if (event == GLFW_DISCONNECTED)
|
else if (event == GLFW_DISCONNECTED)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < joystick_count; i++)
|
for (i = 0; i < joystick_count; i++)
|
||||||
{
|
{
|
||||||
if (joysticks[i] == joy)
|
if (joysticks[i] == jid)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ static const char* joystick_label(int jid)
|
|||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
int joy;
|
int jid;
|
||||||
GLFWwindow* window;
|
GLFWwindow* window;
|
||||||
struct nk_context* nk;
|
struct nk_context* nk;
|
||||||
struct nk_font_atlas* atlas;
|
struct nk_font_atlas* atlas;
|
||||||
@ -102,10 +102,10 @@ int main(void)
|
|||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
exit(EXIT_FAILURE);
|
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))
|
if (glfwJoystickPresent(jid))
|
||||||
joystick_callback(joy, GLFW_CONNECTED);
|
joystick_callback(jid, GLFW_CONNECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwSetJoystickCallback(joystick_callback);
|
glfwSetJoystickCallback(joystick_callback);
|
||||||
|
@ -52,6 +52,12 @@ static void error_callback(int error, const char* description)
|
|||||||
fprintf(stderr, "Error: %s\n", 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)
|
static int thread_main(void* data)
|
||||||
{
|
{
|
||||||
const Thread* thread = data;
|
const Thread* thread = data;
|
||||||
@ -101,6 +107,8 @@ int main(void)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glfwSetKeyCallback(threads[i].window, key_callback);
|
||||||
|
|
||||||
glfwSetWindowPos(threads[i].window, 200 + 250 * i, 200);
|
glfwSetWindowPos(threads[i].window, 200 + 250 * i, 200);
|
||||||
glfwShowWindow(threads[i].window);
|
glfwShowWindow(threads[i].window);
|
||||||
}
|
}
|
||||||
|
493
tests/vulkan.c
493
tests/vulkan.c
@ -3,24 +3,17 @@
|
|||||||
* Copyright (c) 2015-2016 Valve Corporation
|
* Copyright (c) 2015-2016 Valve Corporation
|
||||||
* Copyright (c) 2015-2016 LunarG, Inc.
|
* Copyright (c) 2015-2016 LunarG, Inc.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* of this software and/or associated documentation files (the "Materials"), to
|
* you may not use this file except in compliance with the License.
|
||||||
* deal in the Materials without restriction, including without limitation the
|
* You may obtain a copy of the License at
|
||||||
* 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:
|
|
||||||
*
|
*
|
||||||
* The above copyright notice(s) and this permission notice shall be included in
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
* all copies or substantial portions of the Materials.
|
|
||||||
*
|
*
|
||||||
* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
*
|
* See the License for the specific language governing permissions and
|
||||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
* limitations under the License.
|
||||||
* 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.
|
|
||||||
*
|
*
|
||||||
* Author: Chia-I Wu <olvaffe@gmail.com>
|
* Author: Chia-I Wu <olvaffe@gmail.com>
|
||||||
* Author: Cody Northrop <cody@lunarg.com>
|
* Author: Cody Northrop <cody@lunarg.com>
|
||||||
@ -28,6 +21,8 @@
|
|||||||
* Author: Ian Elliott <ian@LunarG.com>
|
* Author: Ian Elliott <ian@LunarG.com>
|
||||||
* Author: Jon Ashburn <jon@lunarg.com>
|
* Author: Jon Ashburn <jon@lunarg.com>
|
||||||
* Author: Piers Daniell <pdaniell@nvidia.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
|
* Draw a textured triangle with depth testing. This is written against Intel
|
||||||
@ -35,22 +30,24 @@
|
|||||||
* should. It also does no error checking.
|
* should. It also does no error checking.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
#define _ISOC11_SOURCE /* for aligned_alloc() */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <assert.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>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
#define DEMO_TEXTURE_COUNT 1
|
#define DEMO_TEXTURE_COUNT 1
|
||||||
#define VERTEX_BUFFER_BIND_ID 0
|
#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 APP_LONG_NAME "The Vulkan Triangle Demo Program"
|
||||||
|
|
||||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||||
@ -245,39 +242,23 @@ struct texture_object {
|
|||||||
int32_t tex_width, tex_height;
|
int32_t tex_width, tex_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int validation_error = 0;
|
||||||
|
|
||||||
VKAPI_ATTR VkBool32 VKAPI_CALL
|
VKAPI_ATTR VkBool32 VKAPI_CALL
|
||||||
dbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
|
BreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
|
||||||
uint64_t srcObject, size_t location, int32_t msgCode,
|
uint64_t srcObject, size_t location, int32_t msgCode,
|
||||||
const char *pLayerPrefix, const char *pMsg, void *pUserData) {
|
const char *pLayerPrefix, const char *pMsg,
|
||||||
char *message = (char *)malloc(strlen(pMsg) + 100);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%s\n", message);
|
typedef struct {
|
||||||
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 {
|
|
||||||
VkImage image;
|
VkImage image;
|
||||||
VkCommandBuffer cmd;
|
VkCommandBuffer cmd;
|
||||||
VkImageView view;
|
VkImageView view;
|
||||||
@ -288,20 +269,19 @@ struct demo {
|
|||||||
VkSurfaceKHR surface;
|
VkSurfaceKHR surface;
|
||||||
bool use_staging_buffer;
|
bool use_staging_buffer;
|
||||||
|
|
||||||
VkAllocationCallbacks allocator;
|
|
||||||
|
|
||||||
VkInstance inst;
|
VkInstance inst;
|
||||||
VkPhysicalDevice gpu;
|
VkPhysicalDevice gpu;
|
||||||
VkDevice device;
|
VkDevice device;
|
||||||
VkQueue queue;
|
VkQueue queue;
|
||||||
VkPhysicalDeviceProperties gpu_props;
|
VkPhysicalDeviceProperties gpu_props;
|
||||||
|
VkPhysicalDeviceFeatures gpu_features;
|
||||||
VkQueueFamilyProperties *queue_props;
|
VkQueueFamilyProperties *queue_props;
|
||||||
uint32_t graphics_queue_node_index;
|
uint32_t graphics_queue_node_index;
|
||||||
|
|
||||||
uint32_t enabled_extension_count;
|
uint32_t enabled_extension_count;
|
||||||
uint32_t enabled_layer_count;
|
uint32_t enabled_layer_count;
|
||||||
const char *extension_names[64];
|
const char *extension_names[64];
|
||||||
char *device_validation_layers[64];
|
const char *enabled_layers[64];
|
||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
VkFormat format;
|
VkFormat format;
|
||||||
@ -363,10 +343,14 @@ struct demo {
|
|||||||
|
|
||||||
VkPhysicalDeviceMemoryProperties memory_properties;
|
VkPhysicalDeviceMemoryProperties memory_properties;
|
||||||
|
|
||||||
|
int32_t curFrame;
|
||||||
|
int32_t frameCount;
|
||||||
bool validate;
|
bool validate;
|
||||||
|
bool use_break;
|
||||||
PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallback;
|
PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallback;
|
||||||
PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallback;
|
PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallback;
|
||||||
VkDebugReportCallbackEXT msg_callback;
|
VkDebugReportCallbackEXT msg_callback;
|
||||||
|
PFN_vkDebugReportMessageEXT DebugReportMessage;
|
||||||
|
|
||||||
float depthStencil;
|
float depthStencil;
|
||||||
float depthIncrement;
|
float depthIncrement;
|
||||||
@ -375,6 +359,40 @@ struct demo {
|
|||||||
uint32_t queue_count;
|
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:
|
// Forward declaration:
|
||||||
static void demo_resize(struct demo *demo);
|
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,
|
VkFlags requirements_mask,
|
||||||
uint32_t *typeIndex) {
|
uint32_t *typeIndex) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
// Search memtypes to find first index with those properties
|
// 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) {
|
if ((typeBits & 1) == 1) {
|
||||||
// Type is available, does it match user properties?
|
// Type is available, does it match user properties?
|
||||||
if ((demo->memory_properties.memoryTypes[i].propertyFlags &
|
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,
|
static void demo_set_image_layout(struct demo *demo, VkImage image,
|
||||||
VkImageAspectFlags aspectMask,
|
VkImageAspectFlags aspectMask,
|
||||||
VkImageLayout old_image_layout,
|
VkImageLayout old_image_layout,
|
||||||
VkImageLayout new_image_layout) {
|
VkImageLayout new_image_layout,
|
||||||
|
VkAccessFlagBits srcAccessMask) {
|
||||||
|
|
||||||
VkResult U_ASSERT_ONLY err;
|
VkResult U_ASSERT_ONLY err;
|
||||||
|
|
||||||
if (demo->setup_cmd == VK_NULL_HANDLE) {
|
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);
|
err = vkAllocateCommandBuffers(demo->device, &cmd, &demo->setup_cmd);
|
||||||
assert(!err);
|
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 = {
|
VkCommandBufferBeginInfo cmd_buf_info = {
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||||
.pNext = NULL,
|
.pNext = NULL,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.pInheritanceInfo = &cmd_buf_hinfo,
|
.pInheritanceInfo = NULL,
|
||||||
};
|
};
|
||||||
err = vkBeginCommandBuffer(demo->setup_cmd, &cmd_buf_info);
|
err = vkBeginCommandBuffer(demo->setup_cmd, &cmd_buf_info);
|
||||||
assert(!err);
|
assert(!err);
|
||||||
@ -471,7 +480,7 @@ static void demo_set_image_layout(struct demo *demo, VkImage image,
|
|||||||
VkImageMemoryBarrier image_memory_barrier = {
|
VkImageMemoryBarrier image_memory_barrier = {
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
.pNext = NULL,
|
.pNext = NULL,
|
||||||
.srcAccessMask = 0,
|
.srcAccessMask = srcAccessMask,
|
||||||
.dstAccessMask = 0,
|
.dstAccessMask = 0,
|
||||||
.oldLayout = old_image_layout,
|
.oldLayout = old_image_layout,
|
||||||
.newLayout = new_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) {
|
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 = {
|
const VkCommandBufferBeginInfo cmd_buf_info = {
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||||
.pNext = NULL,
|
.pNext = NULL,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.pInheritanceInfo = &cmd_buf_hinfo,
|
.pInheritanceInfo = NULL,
|
||||||
};
|
};
|
||||||
const VkClearValue clear_values[2] = {
|
const VkClearValue clear_values[2] = {
|
||||||
[0] = {.color.float32 = {0.2f, 0.2f, 0.2f, 0.2f}},
|
[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);
|
err = vkBeginCommandBuffer(demo->draw_cmd, &cmd_buf_info);
|
||||||
assert(!err);
|
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);
|
vkCmdBeginRenderPass(demo->draw_cmd, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
vkCmdBindPipeline(demo->draw_cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
vkCmdBindPipeline(demo->draw_cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
demo->pipeline);
|
demo->pipeline);
|
||||||
@ -599,20 +615,24 @@ static void demo_draw_build_cmd(struct demo *demo) {
|
|||||||
|
|
||||||
static void demo_draw(struct demo *demo) {
|
static void demo_draw(struct demo *demo) {
|
||||||
VkResult U_ASSERT_ONLY err;
|
VkResult U_ASSERT_ONLY err;
|
||||||
VkSemaphore presentCompleteSemaphore;
|
VkSemaphore imageAcquiredSemaphore, drawCompleteSemaphore;
|
||||||
VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {
|
VkSemaphoreCreateInfo semaphoreCreateInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
||||||
.pNext = NULL,
|
.pNext = NULL,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
err = vkCreateSemaphore(demo->device, &presentCompleteSemaphoreCreateInfo,
|
err = vkCreateSemaphore(demo->device, &semaphoreCreateInfo,
|
||||||
NULL, &presentCompleteSemaphore);
|
NULL, &imageAcquiredSemaphore);
|
||||||
|
assert(!err);
|
||||||
|
|
||||||
|
err = vkCreateSemaphore(demo->device, &semaphoreCreateInfo,
|
||||||
|
NULL, &drawCompleteSemaphore);
|
||||||
assert(!err);
|
assert(!err);
|
||||||
|
|
||||||
// Get the index of the next available swapchain image:
|
// Get the index of the next available swapchain image:
|
||||||
err = demo->fpAcquireNextImageKHR(demo->device, demo->swapchain, UINT64_MAX,
|
err = demo->fpAcquireNextImageKHR(demo->device, demo->swapchain, UINT64_MAX,
|
||||||
presentCompleteSemaphore,
|
imageAcquiredSemaphore,
|
||||||
(VkFence)0, // TODO: Show use of fence
|
(VkFence)0, // TODO: Show use of fence
|
||||||
&demo->current_buffer);
|
&demo->current_buffer);
|
||||||
if (err == VK_ERROR_OUT_OF_DATE_KHR) {
|
if (err == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||||
@ -620,7 +640,8 @@ static void demo_draw(struct demo *demo) {
|
|||||||
// must be recreated:
|
// must be recreated:
|
||||||
demo_resize(demo);
|
demo_resize(demo);
|
||||||
demo_draw(demo);
|
demo_draw(demo);
|
||||||
vkDestroySemaphore(demo->device, presentCompleteSemaphore, NULL);
|
vkDestroySemaphore(demo->device, imageAcquiredSemaphore, NULL);
|
||||||
|
vkDestroySemaphore(demo->device, drawCompleteSemaphore, NULL);
|
||||||
return;
|
return;
|
||||||
} else if (err == VK_SUBOPTIMAL_KHR) {
|
} else if (err == VK_SUBOPTIMAL_KHR) {
|
||||||
// demo->swapchain is not as optimal as it could be, but the platform's
|
// 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);
|
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);
|
demo_flush_init_cmd(demo);
|
||||||
|
|
||||||
// Wait for the present complete semaphore to be signaled to ensure
|
// 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
|
// engine has fully released ownership to the application, and it is
|
||||||
// okay to render to the image.
|
// okay to render to the image.
|
||||||
|
|
||||||
// FIXME/TODO: DEAL WITH VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
|
|
||||||
demo_draw_build_cmd(demo);
|
demo_draw_build_cmd(demo);
|
||||||
VkFence nullFence = VK_NULL_HANDLE;
|
VkFence nullFence = VK_NULL_HANDLE;
|
||||||
VkPipelineStageFlags pipe_stage_flags =
|
VkPipelineStageFlags pipe_stage_flags =
|
||||||
@ -650,12 +664,12 @@ static void demo_draw(struct demo *demo) {
|
|||||||
VkSubmitInfo submit_info = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
VkSubmitInfo submit_info = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||||
.pNext = NULL,
|
.pNext = NULL,
|
||||||
.waitSemaphoreCount = 1,
|
.waitSemaphoreCount = 1,
|
||||||
.pWaitSemaphores = &presentCompleteSemaphore,
|
.pWaitSemaphores = &imageAcquiredSemaphore,
|
||||||
.pWaitDstStageMask = &pipe_stage_flags,
|
.pWaitDstStageMask = &pipe_stage_flags,
|
||||||
.commandBufferCount = 1,
|
.commandBufferCount = 1,
|
||||||
.pCommandBuffers = &demo->draw_cmd,
|
.pCommandBuffers = &demo->draw_cmd,
|
||||||
.signalSemaphoreCount = 0,
|
.signalSemaphoreCount = 1,
|
||||||
.pSignalSemaphores = NULL};
|
.pSignalSemaphores = &drawCompleteSemaphore};
|
||||||
|
|
||||||
err = vkQueueSubmit(demo->queue, 1, &submit_info, nullFence);
|
err = vkQueueSubmit(demo->queue, 1, &submit_info, nullFence);
|
||||||
assert(!err);
|
assert(!err);
|
||||||
@ -663,12 +677,13 @@ static void demo_draw(struct demo *demo) {
|
|||||||
VkPresentInfoKHR present = {
|
VkPresentInfoKHR present = {
|
||||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||||
.pNext = NULL,
|
.pNext = NULL,
|
||||||
|
.waitSemaphoreCount = 1,
|
||||||
|
.pWaitSemaphores = &drawCompleteSemaphore,
|
||||||
.swapchainCount = 1,
|
.swapchainCount = 1,
|
||||||
.pSwapchains = &demo->swapchain,
|
.pSwapchains = &demo->swapchain,
|
||||||
.pImageIndices = &demo->current_buffer,
|
.pImageIndices = &demo->current_buffer,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TBD/TODO: SHOULD THE "present" PARAMETER BE "const" IN THE HEADER?
|
|
||||||
err = demo->fpQueuePresentKHR(demo->queue, &present);
|
err = demo->fpQueuePresentKHR(demo->queue, &present);
|
||||||
if (err == VK_ERROR_OUT_OF_DATE_KHR) {
|
if (err == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||||
// demo->swapchain is out of date (e.g. the window was resized) and
|
// 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);
|
err = vkQueueWaitIdle(demo->queue);
|
||||||
assert(err == VK_SUCCESS);
|
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) {
|
static void demo_prepare_buffers(struct demo *demo) {
|
||||||
@ -709,12 +725,25 @@ static void demo_prepare_buffers(struct demo *demo) {
|
|||||||
assert(!err);
|
assert(!err);
|
||||||
|
|
||||||
VkExtent2D swapchainExtent;
|
VkExtent2D swapchainExtent;
|
||||||
// width and height are either both -1, or both not -1.
|
// width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF.
|
||||||
if (surfCapabilities.currentExtent.width == (uint32_t)-1) {
|
if (surfCapabilities.currentExtent.width == 0xFFFFFFFF) {
|
||||||
// If the surface size is undefined, the size is set to
|
// If the surface size is undefined, the size is set to the size
|
||||||
// the size of the images requested.
|
// of the images requested, which must fit within the minimum and
|
||||||
|
// maximum values.
|
||||||
swapchainExtent.width = demo->width;
|
swapchainExtent.width = demo->width;
|
||||||
swapchainExtent.height = demo->height;
|
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 {
|
} else {
|
||||||
// If the surface size is defined, the swap chain size must match
|
// If the surface size is defined, the swap chain size must match
|
||||||
swapchainExtent = surfCapabilities.currentExtent;
|
swapchainExtent = surfCapabilities.currentExtent;
|
||||||
@ -724,15 +753,16 @@ static void demo_prepare_buffers(struct demo *demo) {
|
|||||||
|
|
||||||
VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
|
|
||||||
// Determine the number of VkImage's to use in the swap chain (we desire to
|
// Determine the number of VkImage's to use in the swap chain.
|
||||||
// own only 1 image at a time, besides the images being displayed and
|
// Application desires to only acquire 1 image at a time (which is
|
||||||
// queued for display):
|
// "surfCapabilities.minImageCount").
|
||||||
uint32_t desiredNumberOfSwapchainImages =
|
uint32_t desiredNumOfSwapchainImages = surfCapabilities.minImageCount;
|
||||||
surfCapabilities.minImageCount + 1;
|
// If maxImageCount is 0, we can ask for as many images as we want;
|
||||||
|
// otherwise we're limited to maxImageCount
|
||||||
if ((surfCapabilities.maxImageCount > 0) &&
|
if ((surfCapabilities.maxImageCount > 0) &&
|
||||||
(desiredNumberOfSwapchainImages > surfCapabilities.maxImageCount)) {
|
(desiredNumOfSwapchainImages > surfCapabilities.maxImageCount)) {
|
||||||
// Application must settle for fewer images than desired:
|
// Application must settle for fewer images than desired:
|
||||||
desiredNumberOfSwapchainImages = surfCapabilities.maxImageCount;
|
desiredNumOfSwapchainImages = surfCapabilities.maxImageCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkSurfaceTransformFlagsKHR preTransform;
|
VkSurfaceTransformFlagsKHR preTransform;
|
||||||
@ -747,7 +777,7 @@ static void demo_prepare_buffers(struct demo *demo) {
|
|||||||
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
||||||
.pNext = NULL,
|
.pNext = NULL,
|
||||||
.surface = demo->surface,
|
.surface = demo->surface,
|
||||||
.minImageCount = desiredNumberOfSwapchainImages,
|
.minImageCount = desiredNumOfSwapchainImages,
|
||||||
.imageFormat = demo->format,
|
.imageFormat = demo->format,
|
||||||
.imageColorSpace = demo->color_space,
|
.imageColorSpace = demo->color_space,
|
||||||
.imageExtent =
|
.imageExtent =
|
||||||
@ -818,14 +848,6 @@ static void demo_prepare_buffers(struct demo *demo) {
|
|||||||
|
|
||||||
demo->buffers[i].image = swapchainImages[i];
|
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;
|
color_attachment_view.image = demo->buffers[i].image;
|
||||||
|
|
||||||
err = vkCreateImageView(demo->device, &color_attachment_view, NULL,
|
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,
|
demo_set_image_layout(demo, demo->depth.image, VK_IMAGE_ASPECT_DEPTH_BIT,
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||||
|
0);
|
||||||
|
|
||||||
/* create image view */
|
/* create image view */
|
||||||
view.image = demo->depth.image;
|
view.image = demo->depth.image;
|
||||||
@ -939,6 +962,7 @@ demo_prepare_texture_image(struct demo *demo, const uint32_t *tex_colors,
|
|||||||
.tiling = tiling,
|
.tiling = tiling,
|
||||||
.usage = usage,
|
.usage = usage,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
|
.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED
|
||||||
};
|
};
|
||||||
VkMemoryAllocateInfo mem_alloc = {
|
VkMemoryAllocateInfo mem_alloc = {
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
.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;
|
tex_obj->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
demo_set_image_layout(demo, tex_obj->image, VK_IMAGE_ASPECT_COLOR_BIT,
|
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
|
/* setting the image layout does not reference the actual memory so no need
|
||||||
* to add a mem ref */
|
* to add a mem ref */
|
||||||
}
|
}
|
||||||
@ -1025,20 +1050,22 @@ static void demo_prepare_textures(struct demo *demo) {
|
|||||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) &&
|
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) &&
|
||||||
!demo->use_staging_buffer) {
|
!demo->use_staging_buffer) {
|
||||||
/* Device can texture using linear textures */
|
/* Device can texture using linear textures */
|
||||||
demo_prepare_texture_image(demo, tex_colors[i], &demo->textures[i],
|
demo_prepare_texture_image(
|
||||||
VK_IMAGE_TILING_LINEAR,
|
demo, tex_colors[i], &demo->textures[i], VK_IMAGE_TILING_LINEAR,
|
||||||
VK_IMAGE_USAGE_SAMPLED_BIT,
|
VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||||
|
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||||
} else if (props.optimalTilingFeatures &
|
} else if (props.optimalTilingFeatures &
|
||||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
|
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
|
||||||
/* Must use staging buffer to copy linear texture to optimized */
|
/* Must use staging buffer to copy linear texture to optimized */
|
||||||
struct texture_object staging_texture;
|
struct texture_object staging_texture;
|
||||||
|
|
||||||
memset(&staging_texture, 0, sizeof(staging_texture));
|
memset(&staging_texture, 0, sizeof(staging_texture));
|
||||||
demo_prepare_texture_image(demo, tex_colors[i], &staging_texture,
|
demo_prepare_texture_image(
|
||||||
VK_IMAGE_TILING_LINEAR,
|
demo, tex_colors[i], &staging_texture, VK_IMAGE_TILING_LINEAR,
|
||||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||||
|
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||||
|
|
||||||
demo_prepare_texture_image(
|
demo_prepare_texture_image(
|
||||||
demo, tex_colors[i], &demo->textures[i],
|
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,
|
demo_set_image_layout(demo, staging_texture.image,
|
||||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
staging_texture.imageLayout,
|
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,
|
demo_set_image_layout(demo, demo->textures[i].image,
|
||||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
demo->textures[i].imageLayout,
|
demo->textures[i].imageLayout,
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
0);
|
||||||
|
|
||||||
VkImageCopy copy_region = {
|
VkImageCopy copy_region = {
|
||||||
.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
|
.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,
|
demo_set_image_layout(demo, demo->textures[i].image,
|
||||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
demo->textures[i].imageLayout);
|
demo->textures[i].imageLayout,
|
||||||
|
0);
|
||||||
|
|
||||||
demo_flush_init_cmd(demo);
|
demo_flush_init_cmd(demo);
|
||||||
|
|
||||||
@ -1165,7 +1195,8 @@ static void demo_prepare_vertices(struct demo *demo) {
|
|||||||
|
|
||||||
mem_alloc.allocationSize = mem_reqs.size;
|
mem_alloc.allocationSize = mem_reqs.size;
|
||||||
pass = memory_type_from_properties(demo, mem_reqs.memoryTypeBits,
|
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);
|
&mem_alloc.memoryTypeIndex);
|
||||||
assert(pass);
|
assert(pass);
|
||||||
|
|
||||||
@ -1376,6 +1407,7 @@ static void demo_prepare_pipeline(struct demo *demo) {
|
|||||||
rs.depthClampEnable = VK_FALSE;
|
rs.depthClampEnable = VK_FALSE;
|
||||||
rs.rasterizerDiscardEnable = VK_FALSE;
|
rs.rasterizerDiscardEnable = VK_FALSE;
|
||||||
rs.depthBiasEnable = VK_FALSE;
|
rs.depthBiasEnable = VK_FALSE;
|
||||||
|
rs.lineWidth = 1.0f;
|
||||||
|
|
||||||
memset(&cb, 0, sizeof(cb));
|
memset(&cb, 0, sizeof(cb));
|
||||||
cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
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.
|
// Wait for work to finish before updating MVP.
|
||||||
vkDeviceWaitIdle(demo->device);
|
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
|
* Return 1 (true) if all layer names specified in check_names
|
||||||
* can be found in given layer properties.
|
* 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,
|
uint32_t layer_count,
|
||||||
VkLayerProperties *layers) {
|
VkLayerProperties *layers) {
|
||||||
uint32_t i, j;
|
uint32_t i, j;
|
||||||
@ -1656,55 +1691,37 @@ static VkBool32 demo_check_layers(uint32_t check_count, char **check_names,
|
|||||||
return 1;
|
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) {
|
static void demo_init_vk(struct demo *demo) {
|
||||||
VkResult err;
|
VkResult err;
|
||||||
uint32_t required_extension_count;
|
uint32_t i = 0;
|
||||||
const char** required_extensions;
|
uint32_t required_extension_count = 0;
|
||||||
uint32_t i;
|
|
||||||
uint32_t instance_extension_count = 0;
|
uint32_t instance_extension_count = 0;
|
||||||
uint32_t instance_layer_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_extension_count = 0;
|
||||||
demo->enabled_layer_count = 0;
|
demo->enabled_layer_count = 0;
|
||||||
|
|
||||||
char *instance_validation_layers[] = {
|
char *instance_validation_layers_alt1[] = {
|
||||||
"VK_LAYER_LUNARG_mem_tracker",
|
"VK_LAYER_LUNARG_standard_validation"
|
||||||
"VK_LAYER_GOOGLE_unique_objects",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
demo->device_validation_layers[0] = "VK_LAYER_LUNARG_mem_tracker";
|
char *instance_validation_layers_alt2[] = {
|
||||||
demo->device_validation_layers[1] = "VK_LAYER_GOOGLE_unique_objects";
|
"VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation",
|
||||||
device_validation_layer_count = 2;
|
"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 */
|
/* Look for validation layers */
|
||||||
VkBool32 validation_found = 0;
|
VkBool32 validation_found = 0;
|
||||||
|
if (demo->validate) {
|
||||||
|
|
||||||
err = vkEnumerateInstanceLayerProperties(&instance_layer_count, NULL);
|
err = vkEnumerateInstanceLayerProperties(&instance_layer_count, NULL);
|
||||||
assert(!err);
|
assert(!err);
|
||||||
|
|
||||||
|
instance_validation_layers = instance_validation_layers_alt1;
|
||||||
if (instance_layer_count > 0) {
|
if (instance_layer_count > 0) {
|
||||||
VkLayerProperties *instance_layers =
|
VkLayerProperties *instance_layers =
|
||||||
malloc(sizeof (VkLayerProperties) * instance_layer_count);
|
malloc(sizeof (VkLayerProperties) * instance_layer_count);
|
||||||
@ -1712,24 +1729,40 @@ static void demo_init_vk(struct demo *demo) {
|
|||||||
instance_layers);
|
instance_layers);
|
||||||
assert(!err);
|
assert(!err);
|
||||||
|
|
||||||
if (demo->validate) {
|
|
||||||
validation_found = demo_check_layers(
|
validation_found = demo_check_layers(
|
||||||
ARRAY_SIZE(instance_validation_layers),
|
ARRAY_SIZE(instance_validation_layers_alt1),
|
||||||
instance_validation_layers, instance_layer_count,
|
instance_validation_layers, instance_layer_count,
|
||||||
instance_layers);
|
instance_layers);
|
||||||
demo->enabled_layer_count = ARRAY_SIZE(instance_validation_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) {
|
if (!validation_found) {
|
||||||
ERR_EXIT("vkEnumerateInstanceLayerProperties failed to find "
|
ERR_EXIT("vkEnumerateInstanceLayerProperties failed to find "
|
||||||
"required validation layer.\n\n"
|
"required validation layer.\n\n"
|
||||||
"Please look at the Getting Started guide for additional "
|
"Please look at the Getting Started guide for additional "
|
||||||
"information.\n",
|
"information.\n",
|
||||||
"vkCreateInstance Failure");
|
"vkCreateInstance Failure");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Look for instance extensions */
|
/* Look for instance extensions */
|
||||||
required_extensions = glfwGetRequiredInstanceExtensions(&required_extension_count);
|
required_extensions = glfwGetRequiredInstanceExtensions(&required_extension_count);
|
||||||
@ -1792,11 +1825,7 @@ static void demo_init_vk(struct demo *demo) {
|
|||||||
|
|
||||||
uint32_t gpu_count;
|
uint32_t gpu_count;
|
||||||
|
|
||||||
demo->allocator.pfnAllocation = myalloc;
|
err = vkCreateInstance(&inst_info, NULL, &demo->inst);
|
||||||
demo->allocator.pfnFree = myfree;
|
|
||||||
demo->allocator.pfnReallocation = myrealloc;
|
|
||||||
|
|
||||||
err = vkCreateInstance(&inst_info, &demo->allocator, &demo->inst);
|
|
||||||
if (err == VK_ERROR_INCOMPATIBLE_DRIVER) {
|
if (err == VK_ERROR_INCOMPATIBLE_DRIVER) {
|
||||||
ERR_EXIT("Cannot find a compatible Vulkan installable client driver "
|
ERR_EXIT("Cannot find a compatible Vulkan installable client driver "
|
||||||
"(ICD).\n\nPlease look at the Getting Started guide for "
|
"(ICD).\n\nPlease look at the Getting Started guide for "
|
||||||
@ -1834,40 +1863,6 @@ static void demo_init_vk(struct demo *demo) {
|
|||||||
"vkEnumeratePhysicalDevices Failure");
|
"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 */
|
/* Look for device extensions */
|
||||||
uint32_t device_extension_count = 0;
|
uint32_t device_extension_count = 0;
|
||||||
VkBool32 swapchainExtFound = 0;
|
VkBool32 swapchainExtFound = 0;
|
||||||
@ -1911,17 +1906,33 @@ static void demo_init_vk(struct demo *demo) {
|
|||||||
demo->CreateDebugReportCallback =
|
demo->CreateDebugReportCallback =
|
||||||
(PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(
|
(PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(
|
||||||
demo->inst, "vkCreateDebugReportCallbackEXT");
|
demo->inst, "vkCreateDebugReportCallbackEXT");
|
||||||
|
demo->DestroyDebugReportCallback =
|
||||||
|
(PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(
|
||||||
|
demo->inst, "vkDestroyDebugReportCallbackEXT");
|
||||||
if (!demo->CreateDebugReportCallback) {
|
if (!demo->CreateDebugReportCallback) {
|
||||||
ERR_EXIT(
|
ERR_EXIT(
|
||||||
"GetProcAddr: Unable to find vkCreateDebugReportCallbackEXT\n",
|
"GetProcAddr: Unable to find vkCreateDebugReportCallbackEXT\n",
|
||||||
"vkGetProcAddr Failure");
|
"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;
|
VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;
|
||||||
dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
|
dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
|
||||||
dbgCreateInfo.flags =
|
dbgCreateInfo.flags =
|
||||||
VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
|
VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
|
||||||
dbgCreateInfo.pfnCallback = dbgFunc;
|
dbgCreateInfo.pfnCallback = demo->use_break ? BreakCallback : dbgFunc;
|
||||||
dbgCreateInfo.pUserData = NULL;
|
dbgCreateInfo.pUserData = demo;
|
||||||
dbgCreateInfo.pNext = NULL;
|
dbgCreateInfo.pNext = NULL;
|
||||||
err = demo->CreateDebugReportCallback(demo->inst, &dbgCreateInfo, NULL,
|
err = demo->CreateDebugReportCallback(demo->inst, &dbgCreateInfo, NULL,
|
||||||
&demo->msg_callback);
|
&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, GetPhysicalDeviceSurfaceFormatsKHR);
|
||||||
GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfacePresentModesKHR);
|
GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfacePresentModesKHR);
|
||||||
GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceSupportKHR);
|
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);
|
vkGetPhysicalDeviceProperties(demo->gpu, &demo->gpu_props);
|
||||||
|
|
||||||
@ -1963,6 +1969,8 @@ static void demo_init_vk(struct demo *demo) {
|
|||||||
demo->queue_props);
|
demo->queue_props);
|
||||||
assert(demo->queue_count >= 1);
|
assert(demo->queue_count >= 1);
|
||||||
|
|
||||||
|
vkGetPhysicalDeviceFeatures(demo->gpu, &demo->gpu_features);
|
||||||
|
|
||||||
// Graphics queue and MemMgr queue can be separate.
|
// Graphics queue and MemMgr queue can be separate.
|
||||||
// TODO: Add support for separate queues, including synchronization,
|
// TODO: Add support for separate queues, including synchronization,
|
||||||
// and appropriate tracking for QueueSubmit
|
// and appropriate tracking for QueueSubmit
|
||||||
@ -1979,18 +1987,23 @@ static void demo_init_device(struct demo *demo) {
|
|||||||
.queueCount = 1,
|
.queueCount = 1,
|
||||||
.pQueuePriorities = queue_priorities};
|
.pQueuePriorities = queue_priorities};
|
||||||
|
|
||||||
|
|
||||||
|
VkPhysicalDeviceFeatures features;
|
||||||
|
memset(&features, 0, sizeof(features));
|
||||||
|
if (demo->gpu_features.shaderClipDistance) {
|
||||||
|
features.shaderClipDistance = VK_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
VkDeviceCreateInfo device = {
|
VkDeviceCreateInfo device = {
|
||||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||||
.pNext = NULL,
|
.pNext = NULL,
|
||||||
.queueCreateInfoCount = 1,
|
.queueCreateInfoCount = 1,
|
||||||
.pQueueCreateInfos = &queue,
|
.pQueueCreateInfos = &queue,
|
||||||
.enabledLayerCount = demo->enabled_layer_count,
|
.enabledLayerCount = 0,
|
||||||
.ppEnabledLayerNames =
|
.ppEnabledLayerNames = NULL,
|
||||||
(const char *const *)((demo->validate)
|
|
||||||
? demo->device_validation_layers
|
|
||||||
: NULL),
|
|
||||||
.enabledExtensionCount = demo->enabled_extension_count,
|
.enabledExtensionCount = demo->enabled_extension_count,
|
||||||
.ppEnabledExtensionNames = (const char *const *)demo->extension_names,
|
.ppEnabledExtensionNames = (const char *const *)demo->extension_names,
|
||||||
|
.pEnabledFeatures = &features,
|
||||||
};
|
};
|
||||||
|
|
||||||
err = vkCreateDevice(demo->gpu, &device, NULL, &demo->device);
|
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->color_space = surfFormats[0].colorSpace;
|
||||||
|
|
||||||
|
demo->curFrame = 0;
|
||||||
|
|
||||||
// Get Memory information and properties
|
// Get Memory information and properties
|
||||||
vkGetPhysicalDeviceMemoryProperties(demo->gpu, &demo->memory_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[])
|
static void demo_init(struct demo *demo, const int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
memset(demo, 0, sizeof(*demo));
|
memset(demo, 0, sizeof(*demo));
|
||||||
|
demo->frameCount = INT32_MAX;
|
||||||
|
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
if (strncmp(argv[i], "--use_staging", strlen("--use_staging")) == 0)
|
if (strcmp(argv[i], "--use_staging") == 0) {
|
||||||
demo->use_staging_buffer = true;
|
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);
|
demo_init_connection(demo);
|
||||||
@ -2174,8 +2211,11 @@ static void demo_cleanup(struct demo *demo) {
|
|||||||
free(demo->buffers);
|
free(demo->buffers);
|
||||||
|
|
||||||
vkDestroyDevice(demo->device, NULL);
|
vkDestroyDevice(demo->device, NULL);
|
||||||
|
if (demo->validate) {
|
||||||
|
demo->DestroyDebugReportCallback(demo->inst, demo->msg_callback, NULL);
|
||||||
|
}
|
||||||
vkDestroySurfaceKHR(demo->inst, demo->surface, NULL);
|
vkDestroySurfaceKHR(demo->inst, demo->surface, NULL);
|
||||||
vkDestroyInstance(demo->inst, &demo->allocator);
|
vkDestroyInstance(demo->inst, NULL);
|
||||||
|
|
||||||
free(demo->queue_props);
|
free(demo->queue_props);
|
||||||
|
|
||||||
@ -2186,6 +2226,11 @@ static void demo_cleanup(struct demo *demo) {
|
|||||||
static void demo_resize(struct demo *demo) {
|
static void demo_resize(struct demo *demo) {
|
||||||
uint32_t i;
|
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++) {
|
for (i = 0; i < demo->swapchainImageCount; i++) {
|
||||||
vkDestroyFramebuffer(demo->device, demo->framebuffers[i], NULL);
|
vkDestroyFramebuffer(demo->device, demo->framebuffers[i], NULL);
|
||||||
}
|
}
|
||||||
@ -2240,6 +2285,6 @@ int main(const int argc, const char *argv[]) {
|
|||||||
|
|
||||||
demo_cleanup(&demo);
|
demo_cleanup(&demo);
|
||||||
|
|
||||||
return 0;
|
return validation_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user