Add run-time context creation API selection

Fixes #145.
This commit is contained in:
Camilla Berglund 2016-03-28 13:19:31 +02:00
parent 9d50a346f0
commit ef80beab81
32 changed files with 806 additions and 804 deletions

View File

@ -35,13 +35,11 @@ if (APPLE)
option(GLFW_USE_CHDIR "Make glfwInit chdir to Contents/Resources" ON) option(GLFW_USE_CHDIR "Make glfwInit chdir to Contents/Resources" ON)
option(GLFW_USE_MENUBAR "Populate the menu bar on first window creation" ON) option(GLFW_USE_MENUBAR "Populate the menu bar on first window creation" ON)
option(GLFW_USE_RETINA "Use the full resolution of Retina displays" ON) option(GLFW_USE_RETINA "Use the full resolution of Retina displays" ON)
else()
option(GLFW_USE_EGL "Use EGL for context creation" OFF)
endif() endif()
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
option(GLFW_USE_WAYLAND "Use Wayland for context creation (implies EGL as well)" OFF) option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
option(GLFW_USE_MIR "Use Mir for context creation (implies EGL as well)" OFF) option(GLFW_USE_MIR "Use Mir for window creation" OFF)
endif() endif()
if (MSVC) if (MSVC)
@ -59,12 +57,6 @@ else()
set(GLFW_LIB_NAME glfw3) set(GLFW_LIB_NAME glfw3)
endif() endif()
if (GLFW_USE_WAYLAND)
set(GLFW_USE_EGL ON)
elseif (GLFW_USE_MIR)
set(GLFW_USE_EGL ON)
endif()
set(CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules") set(CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules")
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
@ -129,19 +121,9 @@ endif()
if (WIN32) if (WIN32)
set(_GLFW_WIN32 1) set(_GLFW_WIN32 1)
message(STATUS "Using Win32 for window creation") message(STATUS "Using Win32 for window creation")
if (GLFW_USE_EGL)
set(_GLFW_EGL 1)
message(STATUS "Using EGL for context creation")
else()
set(_GLFW_WGL 1)
message(STATUS "Using WGL for context creation")
endif()
elseif (APPLE) elseif (APPLE)
set(_GLFW_COCOA 1) set(_GLFW_COCOA 1)
message(STATUS "Using Cocoa for window creation") message(STATUS "Using Cocoa for window creation")
set(_GLFW_NSGL 1)
message(STATUS "Using NSGL for context creation")
elseif (UNIX) elseif (UNIX)
if (GLFW_USE_WAYLAND) if (GLFW_USE_WAYLAND)
set(_GLFW_WAYLAND 1) set(_GLFW_WAYLAND 1)
@ -153,14 +135,6 @@ 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() endif()
if (GLFW_USE_EGL)
set(_GLFW_EGL 1)
message(STATUS "Using EGL for context creation")
else()
set(_GLFW_GLX 1)
message(STATUS "Using GLX for context creation")
endif()
else() else()
message(FATAL_ERROR "No supported platform was detected") message(FATAL_ERROR "No supported platform was detected")
endif() endif()
@ -306,7 +280,7 @@ endif()
#-------------------------------------------------------------------- #--------------------------------------------------------------------
# Use Cocoa for window creation and NSOpenGL for context creation # Use Cocoa for window creation and NSOpenGL for context creation
#-------------------------------------------------------------------- #--------------------------------------------------------------------
if (_GLFW_COCOA AND _GLFW_NSGL) if (_GLFW_COCOA)
if (GLFW_USE_MENUBAR) if (GLFW_USE_MENUBAR)
set(_GLFW_USE_MENUBAR 1) set(_GLFW_USE_MENUBAR 1)

View File

@ -93,12 +93,14 @@ does not find Doxygen, the documentation will not be generated.
- Added `GLFW_NO_API` for creating window without contexts - Added `GLFW_NO_API` for creating window without contexts
- Added `GLFW_CONTEXT_NO_ERROR` context hint for `GL_KHR_no_error` support - Added `GLFW_CONTEXT_NO_ERROR` context hint for `GL_KHR_no_error` support
- Added `GLFW_INCLUDE_VULKAN` for including the Vulkan header - Added `GLFW_INCLUDE_VULKAN` for including the Vulkan header
- Added `GLFW_CONTEXT_CREATION_API`, `GLFW_NATIVE_CONTEXT_API` and
`GLFW_EGL_CONTEXT_API` for run-time context creation API selection
- Added `GLFW_TRUE` and `GLFW_FALSE` as client API independent boolean values - Added `GLFW_TRUE` and `GLFW_FALSE` as client API independent boolean values
- Added icons to examples on Windows and OS X - Added icons to examples on Windows and OS X
- Relaxed rules for native access header macros - Relaxed rules for native access header macros
- Removed dependency on external OpenGL or OpenGL ES headers - Removed dependency on external OpenGL or OpenGL ES headers
- Removed `_GLFW_USE_OPENGL`, `_GLFW_USE_GLESV1` and `_GLFW_USE_GLESV2` - Removed `_GLFW_USE_OPENGL`, `_GLFW_USE_GLESV1`, `_GLFW_USE_GLESV2`,
configuration macros `_GLFW_WGL`, `_GLFW_NSGL`, `_GLFW_GLX` and `_GLFW_EGL` configuration macros
- [Win32] Added support for Windows 8.1 per-monitor DPI - [Win32] Added support for Windows 8.1 per-monitor DPI
- [Win32] Replaced winmm with XInput and DirectInput for joystick input - [Win32] Replaced winmm with XInput and DirectInput for joystick input
- [Win32] Bugfix: Window creation would segfault if video mode setting required - [Win32] Bugfix: Window creation would segfault if video mode setting required

View File

@ -225,19 +225,13 @@ need to be exported by the EXE to be detected by the driver, so the override
will not work if GLFW is built as a DLL. will not work if GLFW is built as a DLL.
@subsubsection compile_options_egl EGL specific CMake options
`GLFW_USE_EGL` determines whether to use EGL instead of the platform-specific
context creation API. Note that EGL is not yet provided on all supported
platforms.
@section compile_manual Compiling GLFW manually @section compile_manual Compiling GLFW manually
If you wish to compile GLFW without its CMake build environment then you will If you wish to compile GLFW without its CMake build environment then you will
have to do at least some of the platform detection yourself. GLFW needs have to do at least some of the platform detection yourself. GLFW needs
a number of configuration macros to be defined in order to know what it's being a configuration macro to be defined in order to know what window system it's
compiled for and has many optional, platform-specific ones for various features. being compiled for and also has optional, platform-specific ones for various
features.
When building with CMake, the `glfw_config.h` configuration header is generated When building with CMake, the `glfw_config.h` configuration header is generated
based on the current platform and CMake options. The GLFW CMake environment based on the current platform and CMake options. The GLFW CMake environment
@ -245,10 +239,6 @@ defines `_GLFW_USE_CONFIG_H`, which causes this header to be included by
`internal.h`. Without this macro, GLFW will expect the necessary configuration `internal.h`. Without this macro, GLFW will expect the necessary configuration
macros to be defined on the command-line. macros to be defined on the command-line.
Three macros _must_ be defined when compiling GLFW: one selecting the window
creation API and one selecting the context creation API. Exactly one of each
kind must be defined for GLFW to compile and link.
The window creation API is used to create windows, handle input, monitors, gamma The window creation API is used to create windows, handle input, monitors, gamma
ramps and clipboard. The options are: ramps and clipboard. The options are:
@ -258,19 +248,14 @@ ramps and clipboard. The options are:
- `_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)
The context creation API is used to enumerate pixel formats / framebuffer
configurations and to create contexts. The options are:
- `_GLFW_NSGL` to use the Cocoa OpenGL framework
- `_GLFW_WGL` to use the Win32 WGL API
- `_GLFW_GLX` to use the X11 GLX API
- `_GLFW_EGL` to use the EGL API
Wayland and Mir both require the EGL backend.
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.
For the EGL context creation API, the following options are available:
- `_GLFW_USE_EGLPLATFORM_H` to use `EGL/eglplatform.h` for native handle
definitions (fallback)
If you are using the X11 window creation API, support for the following X11 If you are using the X11 window creation API, support for the following X11
extensions can be enabled: extensions can be enabled:
@ -287,12 +272,6 @@ available:
- `_GLFW_USE_RETINA` to have windows use the full resolution of Retina displays - `_GLFW_USE_RETINA` to have windows use the full resolution of Retina displays
(recommended) (recommended)
If you are using the EGL context creation API, the following options are
available:
- `_GLFW_USE_EGLPLATFORM_H` to use `EGL/eglplatform.h` for native handle
definitions (fallback)
@note None of the @ref build_macros may be defined during the compilation of @note None of the @ref build_macros may be defined during the compilation of
GLFW. If you define any of these in your build files, make sure they are not GLFW. If you define any of these in your build files, make sure they are not
applied to the GLFW sources. applied to the GLFW sources.

View File

@ -177,9 +177,10 @@ python main.py --generator c --no-loader --out-path output
@endcode @endcode
The `--no-loader` option is added because GLFW already provides a function for The `--no-loader` option is added because GLFW already provides a function for
loading OpenGL and OpenGL ES function pointers and glad can call this instead of loading OpenGL and OpenGL ES function pointers, one that automatically uses the
having to implement its own. There are several other command-line options as selected context creation API, and glad can call this instead of having to
well. See the glad documentation for details. implement its own. There are several other command-line options as well. See
the glad documentation for details.
Add the generated `output/src/glad.c`, `output/include/glad/glad.h` and Add the generated `output/src/glad.c`, `output/include/glad/glad.h` and
`output/include/KHR/khrplatform.h` files to your build. Then you need to `output/include/KHR/khrplatform.h` files to your build. Then you need to

View File

@ -61,6 +61,12 @@ GLFW now supports waiting for events for a set amount of time with @ref
glfwWaitEventsTimeout. glfwWaitEventsTimeout.
@subsection news_32_contextapi Run-time context creation API selection
GLFW now supports selecting the context creation API at run-time with
[GLFW_CONTEXT_CREATION_API](@ref window_hints_ctx).
@section news_31 New features in 3.1 @section news_31 New features in 3.1
These are the release highlights. For a full list of changes see the These are the release highlights. For a full list of changes see the

View File

@ -159,6 +159,7 @@ The following hints are always hard constraints:
- `GLFW_STEREO` - `GLFW_STEREO`
- `GLFW_DOUBLEBUFFER` - `GLFW_DOUBLEBUFFER`
- `GLFW_CLIENT_API` - `GLFW_CLIENT_API`
- `GLFW_CONTEXT_CREATION_API`
The following additional hints are hard constraints when requesting an OpenGL The following additional hints are hard constraints when requesting an OpenGL
context, but are ignored when requesting an OpenGL ES context: context, but are ignored when requesting an OpenGL ES context:
@ -249,6 +250,24 @@ This hint is ignored for windowed mode windows.
Possible values are `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` and `GLFW_NO_API`. Possible values are `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` and `GLFW_NO_API`.
This is a hard constraint. This is a hard constraint.
`GLFW_CONTEXT_CREATION_API` specifies which context creation API to use to
create the context. Possible values are `GLFW_NATIVE_CONTEXT_API` and
`GLFW_EGL_CONTEXT_API`. This is a hard constraint. If no client API is
requested, this hint is ignored.
@par
__OS X:__ The EGL API is not available on this platform and requests to use it
will fail.
@par
__Wayland, Mir:__ The EGL API _is_ the native context creation API, so this hint
will have no effect.
@note An OpenGL extension loader library that assumes it knows which context
creation API is used on a given platform may fail if you change this hint. This
can be resolved by having it load via @ref glfwGetProcAddress, which always uses
the selected API.
`GLFW_CONTEXT_VERSION_MAJOR` and `GLFW_CONTEXT_VERSION_MINOR` specify the client `GLFW_CONTEXT_VERSION_MAJOR` and `GLFW_CONTEXT_VERSION_MINOR` specify the client
API version that the created context must be compatible with. The exact API version that the created context must be compatible with. The exact
behavior of these hints depend on the requested client API. behavior of these hints depend on the requested client API.
@ -362,6 +381,7 @@ Window hint | Default value | Supported values
`GLFW_SRGB_CAPABLE` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` `GLFW_SRGB_CAPABLE` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_DOUBLEBUFFER` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` `GLFW_DOUBLEBUFFER` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
`GLFW_CLIENT_API` | `GLFW_OPENGL_API` | `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API` `GLFW_CLIENT_API` | `GLFW_OPENGL_API` | `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`
`GLFW_CONTEXT_CREATION_API` | `GLFW_NATIVE_CONTEXT_API` | `GLFW_NATIVE_CONTEXT_API` or `GLFW_EGL_CONTEXT_API`
`GLFW_CONTEXT_VERSION_MAJOR` | 1 | Any valid major version number of the chosen client API `GLFW_CONTEXT_VERSION_MAJOR` | 1 | Any valid major version number of the chosen client API
`GLFW_CONTEXT_VERSION_MINOR` | 0 | Any valid minor version number of the chosen client API `GLFW_CONTEXT_VERSION_MINOR` | 0 | Any valid minor version number of the chosen client API
`GLFW_CONTEXT_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS`, `GLFW_NO_RESET_NOTIFICATION` or `GLFW_LOSE_CONTEXT_ON_RESET` `GLFW_CONTEXT_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS`, `GLFW_NO_RESET_NOTIFICATION` or `GLFW_LOSE_CONTEXT_ON_RESET`
@ -889,6 +909,10 @@ topmost or always-on-top. This is controlled by the
`GLFW_CLIENT_API` indicates the client API provided by the window's context; `GLFW_CLIENT_API` indicates the client API provided by the window's context;
either `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`. either `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`.
`GLFW_CONTEXT_CREATION_API` indicates the context creation API used to create
the window's context; either `GLFW_NATIVE_CONTEXT_API` or
`GLFW_EGL_CONTEXT_API`.
`GLFW_CONTEXT_VERSION_MAJOR`, `GLFW_CONTEXT_VERSION_MINOR` and `GLFW_CONTEXT_VERSION_MAJOR`, `GLFW_CONTEXT_VERSION_MINOR` and
`GLFW_CONTEXT_REVISION` indicate the client API version of the window's context. `GLFW_CONTEXT_REVISION` indicate the client API version of the window's context.

View File

@ -655,6 +655,7 @@ extern "C" {
#define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_OPENGL_PROFILE 0x00022008
#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009
#define GLFW_CONTEXT_NO_ERROR 0x0002200A #define GLFW_CONTEXT_NO_ERROR 0x0002200A
#define GLFW_CONTEXT_CREATION_API 0x0002200B
#define GLFW_NO_API 0 #define GLFW_NO_API 0
#define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_API 0x00030001
@ -680,6 +681,9 @@ extern "C" {
#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001 #define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001
#define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002 #define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002
#define GLFW_NATIVE_CONTEXT_API 0x00036001
#define GLFW_EGL_CONTEXT_API 0x00036002
/*! @defgroup shapes Standard cursor shapes /*! @defgroup shapes Standard cursor shapes
* *
* See [standard cursor creation](@ref cursor_standard) for how these are used. * See [standard cursor creation](@ref cursor_standard) for how these are used.

View File

@ -7,23 +7,29 @@ set(common_SOURCES context.c init.c input.c monitor.c vulkan.c window.c)
if (_GLFW_COCOA) if (_GLFW_COCOA)
set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h cocoa_joystick.h set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h cocoa_joystick.h
posix_tls.h) posix_tls.h nsgl_context.h)
set(glfw_SOURCES ${common_SOURCES} cocoa_init.m cocoa_joystick.m set(glfw_SOURCES ${common_SOURCES} cocoa_init.m cocoa_joystick.m
cocoa_monitor.m cocoa_window.m cocoa_time.c posix_tls.c) cocoa_monitor.m cocoa_window.m cocoa_time.c posix_tls.c
nsgl_context.m)
elseif (_GLFW_WIN32) elseif (_GLFW_WIN32)
set(glfw_HEADERS ${common_HEADERS} win32_platform.h win32_joystick.h) set(glfw_HEADERS ${common_HEADERS} win32_platform.h win32_joystick.h
wgl_context.h egl_context.h)
set(glfw_SOURCES ${common_SOURCES} win32_init.c win32_joystick.c set(glfw_SOURCES ${common_SOURCES} win32_init.c win32_joystick.c
win32_monitor.c win32_time.c win32_tls.c win32_window.c) win32_monitor.c win32_time.c win32_tls.c win32_window.c
wgl_context.c egl_context.c)
elseif (_GLFW_X11) elseif (_GLFW_X11)
set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h
linux_joystick.h posix_time.h posix_tls.h) linux_joystick.h posix_time.h posix_tls.h glx_context.h
egl_context.h)
set(glfw_SOURCES ${common_SOURCES} x11_init.c x11_monitor.c x11_window.c set(glfw_SOURCES ${common_SOURCES} x11_init.c x11_monitor.c x11_window.c
xkb_unicode.c linux_joystick.c posix_time.c posix_tls.c) xkb_unicode.c linux_joystick.c posix_time.c posix_tls.c
glx_context.c egl_context.c)
elseif (_GLFW_WAYLAND) elseif (_GLFW_WAYLAND)
set(glfw_HEADERS ${common_HEADERS} wl_platform.h linux_joystick.h set(glfw_HEADERS ${common_HEADERS} wl_platform.h linux_joystick.h
posix_time.h posix_tls.h xkb_unicode.h) posix_time.h posix_tls.h xkb_unicode.h egl_context.h)
set(glfw_SOURCES ${common_SOURCES} wl_init.c wl_monitor.c wl_window.c set(glfw_SOURCES ${common_SOURCES} wl_init.c wl_monitor.c wl_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)
ecm_add_wayland_client_protocol(glfw_SOURCES ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL PROTOCOL
@ -35,23 +41,10 @@ elseif (_GLFW_WAYLAND)
BASENAME pointer-constraints-unstable-v1) BASENAME pointer-constraints-unstable-v1)
elseif (_GLFW_MIR) elseif (_GLFW_MIR)
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
posix_time.h posix_tls.h xkb_unicode.h) posix_time.h posix_tls.h xkb_unicode.h egl_context.h)
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
endif() egl_context.c)
if (_GLFW_EGL)
list(APPEND glfw_HEADERS ${common_HEADERS} egl_context.h)
list(APPEND glfw_SOURCES ${common_SOURCES} egl_context.c)
elseif (_GLFW_NSGL)
list(APPEND glfw_HEADERS ${common_HEADERS} nsgl_context.h)
list(APPEND glfw_SOURCES ${common_SOURCES} nsgl_context.m)
elseif (_GLFW_WGL)
list(APPEND glfw_HEADERS ${common_HEADERS} wgl_context.h)
list(APPEND glfw_SOURCES ${common_SOURCES} wgl_context.c)
elseif (_GLFW_X11)
list(APPEND glfw_HEADERS ${common_HEADERS} glx_context.h)
list(APPEND glfw_SOURCES ${common_SOURCES} glx_context.c)
endif() endif()
if (APPLE) if (APPLE)

View File

@ -280,10 +280,7 @@ void _glfwPlatformTerminate(void)
const char* _glfwPlatformGetVersionString(void) const char* _glfwPlatformGetVersionString(void)
{ {
return _GLFW_VERSION_NUMBER " Cocoa" return _GLFW_VERSION_NUMBER " Cocoa NSGL"
#if defined(_GLFW_NSGL)
" NSGL"
#endif
#if defined(_GLFW_USE_CHDIR) #if defined(_GLFW_USE_CHDIR)
" chdir" " chdir"
#endif #endif

View File

@ -41,12 +41,7 @@ typedef void* id;
#include "posix_tls.h" #include "posix_tls.h"
#include "cocoa_joystick.h" #include "cocoa_joystick.h"
#include "nsgl_context.h"
#if defined(_GLFW_NSGL)
#include "nsgl_context.h"
#else
#error "The Cocoa backend depends on NSGL platform support"
#endif
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle) #define _glfw_dlclose(handle) dlclose(handle)
@ -58,6 +53,9 @@ typedef void* id;
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNS ns #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNS ns
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorNS ns #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorNS ns
#define _GLFW_EGL_CONTEXT_STATE
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
// Cocoa-specific per-window data // Cocoa-specific per-window data
// //

View File

@ -209,7 +209,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)windowDidResize:(NSNotification *)notification - (void)windowDidResize:(NSNotification *)notification
{ {
if (window->context.api != GLFW_NO_API) if (window->context.client != GLFW_NO_API)
[window->context.nsgl.object update]; [window->context.nsgl.object update];
if (_glfw.cursorWindow == window && if (_glfw.cursorWindow == window &&
@ -227,7 +227,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)windowDidMove:(NSNotification *)notification - (void)windowDidMove:(NSNotification *)notification
{ {
if (window->context.api != GLFW_NO_API) if (window->context.client != GLFW_NO_API)
[window->context.nsgl.object update]; [window->context.nsgl.object update];
if (_glfw.cursorWindow == window && if (_glfw.cursorWindow == window &&
@ -1002,10 +1002,18 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (!createWindow(window, wndconfig)) if (!createWindow(window, wndconfig))
return GLFW_FALSE; return GLFW_FALSE;
if (ctxconfig->api != GLFW_NO_API) if (ctxconfig->client != GLFW_NO_API)
{ {
if (!_glfwCreateContextNSGL(window, ctxconfig, fbconfig)) if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
{
if (!_glfwCreateContextNSGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
else
{
_glfwInputError(GLFW_API_UNAVAILABLE, "Cocoa: EGL not available");
return GLFW_FALSE; return GLFW_FALSE;
}
} }
if (window->monitor) if (window->monitor)
@ -1026,8 +1034,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
if (window->monitor) if (window->monitor)
releaseMonitor(window); releaseMonitor(window);
if (window->context.api != GLFW_NO_API) if (window->context.client != GLFW_NO_API)
_glfwDestroyContextNSGL(window); window->context.destroyContext(window);
[window->ns.object setDelegate:nil]; [window->ns.object setDelegate:nil];
[window->ns.delegate release]; [window->ns.delegate release];

View File

@ -90,17 +90,26 @@ static GLFWbool parseVersionString(int* api, int* major, int* minor, int* rev)
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
{ {
if (ctxconfig->api != GLFW_NO_API && if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
ctxconfig->api != GLFW_OPENGL_API && ctxconfig->source != GLFW_EGL_CONTEXT_API)
ctxconfig->api != GLFW_OPENGL_ES_API)
{ {
_glfwInputError(GLFW_INVALID_ENUM, _glfwInputError(GLFW_INVALID_ENUM,
"Invalid client API %i", "Invalid context creation API %i",
ctxconfig->api); ctxconfig->source);
return GLFW_FALSE; return GLFW_FALSE;
} }
if (ctxconfig->api == GLFW_OPENGL_API) if (ctxconfig->client != GLFW_NO_API &&
ctxconfig->client != GLFW_OPENGL_API &&
ctxconfig->client != GLFW_OPENGL_ES_API)
{
_glfwInputError(GLFW_INVALID_ENUM,
"Invalid client API %i",
ctxconfig->client);
return GLFW_FALSE;
}
if (ctxconfig->client == GLFW_OPENGL_API)
{ {
if ((ctxconfig->major < 1 || ctxconfig->minor < 0) || if ((ctxconfig->major < 1 || ctxconfig->minor < 0) ||
(ctxconfig->major == 1 && ctxconfig->minor > 5) || (ctxconfig->major == 1 && ctxconfig->minor > 5) ||
@ -150,7 +159,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
return GLFW_FALSE; return GLFW_FALSE;
} }
} }
else if (ctxconfig->api == GLFW_OPENGL_ES_API) else if (ctxconfig->client == GLFW_OPENGL_ES_API)
{ {
if (ctxconfig->major < 1 || ctxconfig->minor < 0 || if (ctxconfig->major < 1 || ctxconfig->minor < 0 ||
(ctxconfig->major == 1 && ctxconfig->minor > 1) || (ctxconfig->major == 1 && ctxconfig->minor > 1) ||
@ -366,8 +375,13 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
glfwGetProcAddress("glGetIntegerv"); glfwGetProcAddress("glGetIntegerv");
window->context.GetString = (PFNGLGETSTRINGPROC) window->context.GetString = (PFNGLGETSTRINGPROC)
glfwGetProcAddress("glGetString"); glfwGetProcAddress("glGetString");
if (!window->context.GetIntegerv || !window->context.GetString)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
return GLFW_FALSE;
}
if (!parseVersionString(&window->context.api, if (!parseVersionString(&window->context.client,
&window->context.major, &window->context.major,
&window->context.minor, &window->context.minor,
&window->context.revision)) &window->context.revision))
@ -375,6 +389,8 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
return GLFW_FALSE; return GLFW_FALSE;
} }
window->context.source = ctxconfig->source;
if (window->context.major < ctxconfig->major || if (window->context.major < ctxconfig->major ||
(window->context.major == ctxconfig->major && (window->context.major == ctxconfig->major &&
window->context.minor < ctxconfig->minor)) window->context.minor < ctxconfig->minor))
@ -409,7 +425,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
} }
} }
if (window->context.api == GLFW_OPENGL_API) if (window->context.client == GLFW_OPENGL_API)
{ {
// Read back context flags (OpenGL 3.0 and above) // Read back context flags (OpenGL 3.0 and above)
if (window->context.major >= 3) if (window->context.major >= 3)
@ -507,7 +523,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
{ {
PFNGLCLEARPROC glClear = (PFNGLCLEARPROC) glfwGetProcAddress("glClear"); PFNGLCLEARPROC glClear = (PFNGLCLEARPROC) glfwGetProcAddress("glClear");
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
_glfwPlatformSwapBuffers(window); window->context.swapBuffers(window);
} }
return GLFW_TRUE; return GLFW_TRUE;
@ -547,16 +563,24 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle) GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFWwindow* previous = _glfwPlatformGetCurrentContext();
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (window && window->context.api == GLFW_NO_API) if (window && window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return; return;
} }
_glfwPlatformMakeContextCurrent(window); if (previous)
{
if (!window || window->context.source != previous->context.source)
previous->context.makeContextCurrent(NULL);
}
if (window)
window->context.makeContextCurrent(window);
} }
GLFWAPI GLFWwindow* glfwGetCurrentContext(void) GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
@ -572,26 +596,29 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (window->context.api == GLFW_NO_API) if (window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return; return;
} }
_glfwPlatformSwapBuffers(window); window->context.swapBuffers(window);
} }
GLFWAPI void glfwSwapInterval(int interval) GLFWAPI void glfwSwapInterval(int interval)
{ {
_GLFWwindow* window;
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (!_glfwPlatformGetCurrentContext()) window = _glfwPlatformGetCurrentContext();
if (!window)
{ {
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL); _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
return; return;
} }
_glfwPlatformSwapInterval(interval); window->context.swapInterval(interval);
} }
GLFWAPI int glfwExtensionSupported(const char* extension) GLFWAPI int glfwExtensionSupported(const char* extension)
@ -657,21 +684,23 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
} }
// Check if extension is in the platform-specific string // Check if extension is in the platform-specific string
return _glfwPlatformExtensionSupported(extension); return window->context.extensionSupported(extension);
} }
GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname) GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
{ {
_GLFWwindow* window;
assert(procname != NULL); assert(procname != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (!_glfwPlatformGetCurrentContext()) window = _glfwPlatformGetCurrentContext();
if (!window)
{ {
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL); _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
return NULL; return NULL;
} }
return _glfwPlatformGetProcAddress(procname); return window->context.getProcAddress(procname);
} }

View File

@ -125,7 +125,7 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
continue; continue;
#endif // _GLFW_X11 #endif // _GLFW_X11
if (ctxconfig->api == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
{ {
if (ctxconfig->major == 1) if (ctxconfig->major == 1)
{ {
@ -138,7 +138,7 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
continue; continue;
} }
} }
else if (ctxconfig->api == GLFW_OPENGL_API) else if (ctxconfig->client == GLFW_OPENGL_API)
{ {
if (!(getConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT)) if (!(getConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
continue; continue;
@ -169,6 +169,110 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
return closest != NULL; return closest != NULL;
} }
static void makeContextCurrent(_GLFWwindow* window)
{
if (window)
{
if (!eglMakeCurrent(_glfw.egl.display,
window->context.egl.surface,
window->context.egl.surface,
window->context.egl.handle))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to make context current: %s",
getErrorString(eglGetError()));
return;
}
}
else
{
if (!eglMakeCurrent(_glfw.egl.display,
EGL_NO_SURFACE,
EGL_NO_SURFACE,
EGL_NO_CONTEXT))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to clear current context: %s",
getErrorString(eglGetError()));
return;
}
}
_glfwPlatformSetCurrentContext(window);
}
static void swapBuffers(_GLFWwindow* window)
{
if (window != _glfwPlatformGetCurrentContext())
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: The context must be current on the calling thread when swapping buffers");
return;
}
eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
}
static void swapInterval(int interval)
{
eglSwapInterval(_glfw.egl.display, interval);
}
static int extensionSupported(const char* extension)
{
const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
return GLFW_FALSE;
}
static GLFWglproc getProcAddress(const char* procname)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (window->context.egl.client)
{
GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->context.egl.client,
procname);
if (proc)
return proc;
}
return eglGetProcAddress(procname);
}
static void destroyContext(_GLFWwindow* window)
{
#if defined(_GLFW_X11)
// NOTE: Do not unload libGL.so.1 while the X11 display is still open,
// as it will make XCloseDisplay segfault
if (window->context.client != GLFW_OPENGL_API)
#endif // _GLFW_X11
{
if (window->context.egl.client)
{
_glfw_dlclose(window->context.egl.client);
window->context.egl.client = NULL;
}
}
if (window->context.egl.surface)
{
eglDestroySurface(_glfw.egl.display, window->context.egl.surface);
window->context.egl.surface = EGL_NO_SURFACE;
}
if (window->context.egl.handle)
{
eglDestroyContext(_glfw.egl.display, window->context.egl.handle);
window->context.egl.handle = EGL_NO_CONTEXT;
}
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
@ -200,10 +304,7 @@ GLFWbool _glfwInitEGL(void)
} }
if (!_glfw.egl.handle) if (!_glfw.egl.handle)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to load EGL");
return GLFW_FALSE; return GLFW_FALSE;
}
_glfw.egl.GetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC) _glfw.egl.GetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC)
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib"); _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
@ -244,6 +345,8 @@ GLFWbool _glfwInitEGL(void)
_glfwInputError(GLFW_API_UNAVAILABLE, _glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to get EGL display: %s", "EGL: Failed to get EGL display: %s",
getErrorString(eglGetError())); getErrorString(eglGetError()));
_glfwTerminateEGL();
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -252,15 +355,17 @@ GLFWbool _glfwInitEGL(void)
_glfwInputError(GLFW_API_UNAVAILABLE, _glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to initialize EGL: %s", "EGL: Failed to initialize EGL: %s",
getErrorString(eglGetError())); getErrorString(eglGetError()));
_glfwTerminateEGL();
return GLFW_FALSE; return GLFW_FALSE;
} }
_glfw.egl.KHR_create_context = _glfw.egl.KHR_create_context =
_glfwPlatformExtensionSupported("EGL_KHR_create_context"); extensionSupported("EGL_KHR_create_context");
_glfw.egl.KHR_create_context_no_error = _glfw.egl.KHR_create_context_no_error =
_glfwPlatformExtensionSupported("EGL_KHR_create_context_no_error"); extensionSupported("EGL_KHR_create_context_no_error");
_glfw.egl.KHR_gl_colorspace = _glfw.egl.KHR_gl_colorspace =
_glfwPlatformExtensionSupported("EGL_KHR_gl_colorspace"); extensionSupported("EGL_KHR_gl_colorspace");
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -299,6 +404,12 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
EGLConfig config; EGLConfig config;
EGLContext share = NULL; EGLContext share = NULL;
if (!_glfw.egl.display)
{
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available");
return GLFW_FALSE;
}
if (ctxconfig->share) if (ctxconfig->share)
share = ctxconfig->share->context.egl.handle; share = ctxconfig->share->context.egl.handle;
@ -309,7 +420,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
if (ctxconfig->api == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
{ {
if (!eglBindAPI(EGL_OPENGL_ES_API)) if (!eglBindAPI(EGL_OPENGL_ES_API))
{ {
@ -334,7 +445,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{ {
int index = 0, mask = 0, flags = 0; int index = 0, mask = 0, flags = 0;
if (ctxconfig->api == GLFW_OPENGL_API) if (ctxconfig->client == GLFW_OPENGL_API)
{ {
if (ctxconfig->forward) if (ctxconfig->forward)
flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
@ -388,7 +499,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{ {
int index = 0; int index = 0;
if (ctxconfig->api == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major); setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
setEGLattrib(EGL_NONE, EGL_NONE); setEGLattrib(EGL_NONE, EGL_NONE);
@ -477,7 +588,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
NULL NULL
}; };
if (ctxconfig->api == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
{ {
if (ctxconfig->major == 1) if (ctxconfig->major == 1)
sonames = es1sonames; sonames = es1sonames;
@ -502,41 +613,18 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
} }
} }
window->context.makeContextCurrent = makeContextCurrent;
window->context.swapBuffers = swapBuffers;
window->context.swapInterval = swapInterval;
window->context.extensionSupported = extensionSupported;
window->context.getProcAddress = getProcAddress;
window->context.destroyContext = destroyContext;
return GLFW_TRUE; return GLFW_TRUE;
} }
#undef setEGLattrib #undef setEGLattrib
// Destroy the OpenGL context
//
void _glfwDestroyContextEGL(_GLFWwindow* window)
{
#if defined(_GLFW_X11)
// NOTE: Do not unload libGL.so.1 while the X11 display is still open,
// as it will make XCloseDisplay segfault
if (window->context.api != GLFW_OPENGL_API)
#endif // _GLFW_X11
{
if (window->context.egl.client)
{
_glfw_dlclose(window->context.egl.client);
window->context.egl.client = NULL;
}
}
if (window->context.egl.surface)
{
eglDestroySurface(_glfw.egl.display, window->context.egl.surface);
window->context.egl.surface = EGL_NO_SURFACE;
}
if (window->context.egl.handle)
{
eglDestroyContext(_glfw.egl.display, window->context.egl.handle);
window->context.egl.handle = EGL_NO_CONTEXT;
}
}
// Returns the Visual and depth of the chosen EGLConfig // Returns the Visual and depth of the chosen EGLConfig
// //
#if defined(_GLFW_X11) #if defined(_GLFW_X11)
@ -580,87 +668,6 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,
#endif // _GLFW_X11 #endif // _GLFW_X11
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
{
if (window)
{
if (!eglMakeCurrent(_glfw.egl.display,
window->context.egl.surface,
window->context.egl.surface,
window->context.egl.handle))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to make context current: %s",
getErrorString(eglGetError()));
return;
}
}
else
{
if (!eglMakeCurrent(_glfw.egl.display,
EGL_NO_SURFACE,
EGL_NO_SURFACE,
EGL_NO_CONTEXT))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to clear current context: %s",
getErrorString(eglGetError()));
return;
}
}
_glfwPlatformSetCurrentContext(window);
}
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
{
if (window != _glfwPlatformGetCurrentContext())
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: The context must be current on the calling thread when swapping buffers");
return;
}
eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
}
void _glfwPlatformSwapInterval(int interval)
{
eglSwapInterval(_glfw.egl.display, interval);
}
int _glfwPlatformExtensionSupported(const char* extension)
{
const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
return GLFW_FALSE;
}
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (window->context.egl.client)
{
GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->context.egl.client,
procname);
if (proc)
return proc;
}
return eglGetProcAddress(procname);
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW native API ////// ////// GLFW native API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -676,7 +683,7 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT); _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT);
if (window->context.api == GLFW_NO_API) if (window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return EGL_NO_CONTEXT; return EGL_NO_CONTEXT;
@ -690,7 +697,7 @@ GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE); _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE);
if (window->context.api == GLFW_NO_API) if (window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return EGL_NO_SURFACE; return EGL_NO_SURFACE;

View File

@ -149,8 +149,8 @@ typedef GLFWglproc (EGLAPIENTRY * PFNEGLGETPROCADDRESSPROC)(const char*);
#define eglQueryString _glfw.egl.QueryString #define eglQueryString _glfw.egl.QueryString
#define eglGetProcAddress _glfw.egl.GetProcAddress #define eglGetProcAddress _glfw.egl.GetProcAddress
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextEGL egl #define _GLFW_EGL_CONTEXT_STATE _GLFWcontextEGL egl
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl #define _GLFW_EGL_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl
// EGL-specific per-context data // EGL-specific per-context data
@ -204,7 +204,6 @@ void _glfwTerminateEGL(void);
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);
void _glfwDestroyContextEGL(_GLFWwindow* window);
#if defined(_GLFW_X11) #if defined(_GLFW_X11)
GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig, GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig, const _GLFWfbconfig* fbconfig,

View File

@ -45,15 +45,6 @@
// 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 EGL
#cmakedefine _GLFW_EGL
// Define this to 1 if building GLFW for GLX
#cmakedefine _GLFW_GLX
// Define this to 1 if building GLFW for WGL
#cmakedefine _GLFW_WGL
// Define this to 1 if building GLFW for NSGL
#cmakedefine _GLFW_NSGL
// 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

View File

@ -142,6 +142,96 @@ static GLXContext createLegacyContext(_GLFWwindow* window,
True); True);
} }
static void makeContextCurrent(_GLFWwindow* window)
{
if (window)
{
if (!glXMakeCurrent(_glfw.x11.display,
window->context.glx.window,
window->context.glx.handle))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"GLX: Failed to make context current");
return;
}
}
else
{
if (!glXMakeCurrent(_glfw.x11.display, None, NULL))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"GLX: Failed to clear current context");
return;
}
}
_glfwPlatformSetCurrentContext(window);
}
static void swapBuffers(_GLFWwindow* window)
{
glXSwapBuffers(_glfw.x11.display, window->context.glx.window);
}
static void swapInterval(int interval)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (_glfw.glx.EXT_swap_control)
{
_glfw.glx.SwapIntervalEXT(_glfw.x11.display,
window->context.glx.window,
interval);
}
else if (_glfw.glx.MESA_swap_control)
_glfw.glx.SwapIntervalMESA(interval);
else if (_glfw.glx.SGI_swap_control)
{
if (interval > 0)
_glfw.glx.SwapIntervalSGI(interval);
}
}
static int extensionSupported(const char* extension)
{
const char* extensions =
glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen);
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
return GLFW_FALSE;
}
static GLFWglproc getProcAddress(const char* procname)
{
if (_glfw.glx.GetProcAddress)
return _glfw.glx.GetProcAddress((const GLubyte*) procname);
else if (_glfw.glx.GetProcAddressARB)
return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
else
return dlsym(_glfw.glx.handle, procname);
}
// Destroy the OpenGL context
//
static void destroyContext(_GLFWwindow* window)
{
if (window->context.glx.window)
{
glXDestroyWindow(_glfw.x11.display, window->context.glx.window);
window->context.glx.window = None;
}
if (window->context.glx.handle)
{
glXDestroyContext(_glfw.x11.display, window->context.glx.handle);
window->context.glx.handle = NULL;
}
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
@ -229,61 +319,61 @@ GLFWbool _glfwInitGLX(void)
return GLFW_FALSE; return GLFW_FALSE;
} }
if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) if (extensionSupported("GLX_EXT_swap_control"))
{ {
_glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) _glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)
_glfwPlatformGetProcAddress("glXSwapIntervalEXT"); getProcAddress("glXSwapIntervalEXT");
if (_glfw.glx.SwapIntervalEXT) if (_glfw.glx.SwapIntervalEXT)
_glfw.glx.EXT_swap_control = GLFW_TRUE; _glfw.glx.EXT_swap_control = GLFW_TRUE;
} }
if (_glfwPlatformExtensionSupported("GLX_SGI_swap_control")) if (extensionSupported("GLX_SGI_swap_control"))
{ {
_glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) _glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)
_glfwPlatformGetProcAddress("glXSwapIntervalSGI"); getProcAddress("glXSwapIntervalSGI");
if (_glfw.glx.SwapIntervalSGI) if (_glfw.glx.SwapIntervalSGI)
_glfw.glx.SGI_swap_control = GLFW_TRUE; _glfw.glx.SGI_swap_control = GLFW_TRUE;
} }
if (_glfwPlatformExtensionSupported("GLX_MESA_swap_control")) if (extensionSupported("GLX_MESA_swap_control"))
{ {
_glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC) _glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)
_glfwPlatformGetProcAddress("glXSwapIntervalMESA"); getProcAddress("glXSwapIntervalMESA");
if (_glfw.glx.SwapIntervalMESA) if (_glfw.glx.SwapIntervalMESA)
_glfw.glx.MESA_swap_control = GLFW_TRUE; _glfw.glx.MESA_swap_control = GLFW_TRUE;
} }
if (_glfwPlatformExtensionSupported("GLX_ARB_multisample")) if (extensionSupported("GLX_ARB_multisample"))
_glfw.glx.ARB_multisample = GLFW_TRUE; _glfw.glx.ARB_multisample = GLFW_TRUE;
if (_glfwPlatformExtensionSupported("GLX_ARB_framebuffer_sRGB")) if (extensionSupported("GLX_ARB_framebuffer_sRGB"))
_glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE; _glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE;
if (_glfwPlatformExtensionSupported("GLX_EXT_framebuffer_sRGB")) if (extensionSupported("GLX_EXT_framebuffer_sRGB"))
_glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE; _glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE;
if (_glfwPlatformExtensionSupported("GLX_ARB_create_context")) if (extensionSupported("GLX_ARB_create_context"))
{ {
_glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) _glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
_glfwPlatformGetProcAddress("glXCreateContextAttribsARB"); getProcAddress("glXCreateContextAttribsARB");
if (_glfw.glx.CreateContextAttribsARB) if (_glfw.glx.CreateContextAttribsARB)
_glfw.glx.ARB_create_context = GLFW_TRUE; _glfw.glx.ARB_create_context = GLFW_TRUE;
} }
if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness")) if (extensionSupported("GLX_ARB_create_context_robustness"))
_glfw.glx.ARB_create_context_robustness = GLFW_TRUE; _glfw.glx.ARB_create_context_robustness = GLFW_TRUE;
if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) if (extensionSupported("GLX_ARB_create_context_profile"))
_glfw.glx.ARB_create_context_profile = GLFW_TRUE; _glfw.glx.ARB_create_context_profile = GLFW_TRUE;
if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) if (extensionSupported("GLX_EXT_create_context_es2_profile"))
_glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE; _glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE;
if (_glfwPlatformExtensionSupported("GLX_ARB_context_flush_control")) if (extensionSupported("GLX_ARB_context_flush_control"))
_glfw.glx.ARB_context_flush_control = GLFW_TRUE; _glfw.glx.ARB_context_flush_control = GLFW_TRUE;
return GLFW_TRUE; return GLFW_TRUE;
@ -330,7 +420,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
if (ctxconfig->api == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
{ {
if (!_glfw.glx.ARB_create_context || if (!_glfw.glx.ARB_create_context ||
!_glfw.glx.ARB_create_context_profile || !_glfw.glx.ARB_create_context_profile ||
@ -369,7 +459,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
{ {
int index = 0, mask = 0, flags = 0; int index = 0, mask = 0, flags = 0;
if (ctxconfig->api == GLFW_OPENGL_API) if (ctxconfig->client == GLFW_OPENGL_API)
{ {
if (ctxconfig->forward) if (ctxconfig->forward)
flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
@ -454,7 +544,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
if (!window->context.glx.handle) if (!window->context.glx.handle)
{ {
if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB && if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&
ctxconfig->api == GLFW_OPENGL_API && ctxconfig->client == GLFW_OPENGL_API &&
ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE && ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&
ctxconfig->forward == GLFW_FALSE) ctxconfig->forward == GLFW_FALSE)
{ {
@ -482,28 +572,18 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
window->context.makeContextCurrent = makeContextCurrent;
window->context.swapBuffers = swapBuffers;
window->context.swapInterval = swapInterval;
window->context.extensionSupported = extensionSupported;
window->context.getProcAddress = getProcAddress;
window->context.destroyContext = destroyContext;
return GLFW_TRUE; return GLFW_TRUE;
} }
#undef setGLXattrib #undef setGLXattrib
// Destroy the OpenGL context
//
void _glfwDestroyContextGLX(_GLFWwindow* window)
{
if (window->context.glx.window)
{
glXDestroyWindow(_glfw.x11.display, window->context.glx.window);
window->context.glx.window = None;
}
if (window->context.glx.handle)
{
glXDestroyContext(_glfw.x11.display, window->context.glx.handle);
window->context.glx.handle = NULL;
}
}
// Returns the Visual and depth of the chosen GLXFBConfig // Returns the Visual and depth of the chosen GLXFBConfig
// //
GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig, GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig,
@ -536,84 +616,6 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig,
} }
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
{
if (window)
{
if (!glXMakeCurrent(_glfw.x11.display,
window->context.glx.window,
window->context.glx.handle))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"GLX: Failed to make context current");
return;
}
}
else
{
if (!glXMakeCurrent(_glfw.x11.display, None, NULL))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"GLX: Failed to clear current context");
return;
}
}
_glfwPlatformSetCurrentContext(window);
}
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
{
glXSwapBuffers(_glfw.x11.display, window->context.glx.window);
}
void _glfwPlatformSwapInterval(int interval)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (_glfw.glx.EXT_swap_control)
{
_glfw.glx.SwapIntervalEXT(_glfw.x11.display,
window->context.glx.window,
interval);
}
else if (_glfw.glx.MESA_swap_control)
_glfw.glx.SwapIntervalMESA(interval);
else if (_glfw.glx.SGI_swap_control)
{
if (interval > 0)
_glfw.glx.SwapIntervalSGI(interval);
}
}
int _glfwPlatformExtensionSupported(const char* extension)
{
const char* extensions =
glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen);
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
return GLFW_FALSE;
}
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
{
if (_glfw.glx.GetProcAddress)
return _glfw.glx.GetProcAddress((const GLubyte*) procname);
else if (_glfw.glx.GetProcAddressARB)
return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
else
return dlsym(_glfw.glx.handle, procname);
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW native API ////// ////// GLFW native API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -623,7 +625,7 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (window->context.api == GLFW_NO_API) if (window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL; return NULL;
@ -637,7 +639,7 @@ GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(None); _GLFW_REQUIRE_INIT_OR_RETURN(None);
if (window->context.api == GLFW_NO_API) if (window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return None; return None;

View File

@ -58,6 +58,13 @@ typedef struct _GLFWlibrary _GLFWlibrary;
typedef struct _GLFWmonitor _GLFWmonitor; typedef struct _GLFWmonitor _GLFWmonitor;
typedef struct _GLFWcursor _GLFWcursor; typedef struct _GLFWcursor _GLFWcursor;
typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*);
typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*);
typedef void (* _GLFWswapintervalfun)(int);
typedef int (* _GLFWextensionsupportedfun)(const char*);
typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*);
typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
#define GL_VERSION 0x1f02 #define GL_VERSION 0x1f02
#define GL_NONE 0 #define GL_NONE 0
#define GL_COLOR_BUFFER_BIT 0x00004000 #define GL_COLOR_BUFFER_BIT 0x00004000
@ -258,7 +265,8 @@ struct _GLFWwndconfig
*/ */
struct _GLFWctxconfig struct _GLFWctxconfig
{ {
int api; int client;
int source;
int major; int major;
int minor; int minor;
GLFWbool forward; GLFWbool forward;
@ -304,7 +312,8 @@ struct _GLFWfbconfig
*/ */
struct _GLFWcontext struct _GLFWcontext
{ {
int api; int client;
int source;
int major, minor, revision; int major, minor, revision;
GLFWbool forward, debug, noerror; GLFWbool forward, debug, noerror;
int profile; int profile;
@ -315,8 +324,17 @@ struct _GLFWcontext
PFNGLGETINTEGERVPROC GetIntegerv; PFNGLGETINTEGERVPROC GetIntegerv;
PFNGLGETSTRINGPROC GetString; PFNGLGETSTRINGPROC GetString;
_GLFWmakecontextcurrentfun makeContextCurrent;
_GLFWswapbuffersfun swapBuffers;
_GLFWswapintervalfun swapInterval;
_GLFWextensionsupportedfun extensionSupported;
_GLFWgetprocaddressfun getProcAddress;
_GLFWdestroycontextfun destroyContext;
// This is defined in the context API's context.h // This is defined in the context API's context.h
_GLFW_PLATFORM_CONTEXT_STATE; _GLFW_PLATFORM_CONTEXT_STATE;
// This is defined in egl_context.h
_GLFW_EGL_CONTEXT_STATE;
}; };
@ -461,6 +479,8 @@ struct _GLFWlibrary
_GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE; _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE;
// This is defined in the platform's tls.h // This is defined in the platform's tls.h
_GLFW_PLATFORM_LIBRARY_TLS_STATE; _GLFW_PLATFORM_LIBRARY_TLS_STATE;
// This is defined in egl_context.h
_GLFW_EGL_LIBRARY_CONTEXT_STATE;
}; };
@ -742,11 +762,6 @@ void _glfwPlatformWaitEventsTimeout(double timeout);
*/ */
void _glfwPlatformPostEmptyEvent(void); void _glfwPlatformPostEmptyEvent(void);
/*! @copydoc glfwMakeContextCurrent
* @ingroup platform
*/
void _glfwPlatformMakeContextCurrent(_GLFWwindow* window);
/*! @ingroup platform /*! @ingroup platform
*/ */
void _glfwPlatformSetCurrentContext(_GLFWwindow* context); void _glfwPlatformSetCurrentContext(_GLFWwindow* context);
@ -756,26 +771,6 @@ void _glfwPlatformSetCurrentContext(_GLFWwindow* context);
*/ */
_GLFWwindow* _glfwPlatformGetCurrentContext(void); _GLFWwindow* _glfwPlatformGetCurrentContext(void);
/*! @copydoc glfwSwapBuffers
* @ingroup platform
*/
void _glfwPlatformSwapBuffers(_GLFWwindow* window);
/*! @copydoc glfwSwapInterval
* @ingroup platform
*/
void _glfwPlatformSwapInterval(int interval);
/*! @copydoc glfwExtensionSupported
* @ingroup platform
*/
int _glfwPlatformExtensionSupported(const char* extension);
/*! @copydoc glfwGetProcAddress
* @ingroup platform
*/
GLFWglproc _glfwPlatformGetProcAddress(const char* procname);
/*! @copydoc glfwCreateCursor /*! @copydoc glfwCreateCursor
* @ingroup platform * @ingroup platform
*/ */

View File

@ -51,12 +51,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(Vk
#include "posix_time.h" #include "posix_time.h"
#include "linux_joystick.h" #include "linux_joystick.h"
#include "xkb_unicode.h" #include "xkb_unicode.h"
#include "egl_context.h"
#if defined(_GLFW_EGL)
#include "egl_context.h"
#else
#error "The Mir backend depends on EGL platform support"
#endif
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle) #define _glfw_dlclose(handle) dlclose(handle)
@ -70,6 +65,9 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(Vk
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir
#define _GLFW_PLATFORM_CONTEXT_STATE
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
// Mir-specific Event Queue // Mir-specific Event Queue
// //

View File

@ -378,7 +378,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
window->mir.window = mir_buffer_stream_get_egl_native_window( window->mir.window = mir_buffer_stream_get_egl_native_window(
mir_surface_get_buffer_stream(window->mir.surface)); mir_surface_get_buffer_stream(window->mir.surface));
if (ctxconfig->api != GLFW_NO_API) if (ctxconfig->client != GLFW_NO_API)
{ {
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE; return GLFW_FALSE;
@ -395,7 +395,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
window->mir.surface = NULL; window->mir.surface = NULL;
} }
_glfwDestroyContextEGL(window); if (window->context.client != GLFW_NO_API)
window->context.destroyContext(window);
} }
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)

View File

@ -27,6 +27,63 @@
#include "internal.h" #include "internal.h"
static void makeContextCurrent(_GLFWwindow* window)
{
if (window)
[window->context.nsgl.object makeCurrentContext];
else
[NSOpenGLContext clearCurrentContext];
_glfwPlatformSetCurrentContext(window);
}
static void swapBuffers(_GLFWwindow* window)
{
// ARP appears to be unnecessary, but this is future-proof
[window->context.nsgl.object flushBuffer];
}
static void swapInterval(int interval)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
GLint sync = interval;
[window->context.nsgl.object setValues:&sync
forParameter:NSOpenGLCPSwapInterval];
}
static int extensionSupported(const char* extension)
{
// There are no NSGL extensions
return GLFW_FALSE;
}
static GLFWglproc getProcAddress(const char* procname)
{
CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault,
procname,
kCFStringEncodingASCII);
GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework,
symbolName);
CFRelease(symbolName);
return symbol;
}
// Destroy the OpenGL context
//
static void destroyContext(_GLFWwindow* window)
{
[window->context.nsgl.pixelFormat release];
window->context.nsgl.pixelFormat = nil;
[window->context.nsgl.object release];
window->context.nsgl.object = nil;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -61,7 +118,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
{ {
unsigned int attributeCount = 0; unsigned int attributeCount = 0;
if (ctxconfig->api == 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 OS X");
@ -216,70 +273,17 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
} }
[window->context.nsgl.object setView:window->ns.view]; [window->context.nsgl.object setView:window->ns.view];
window->context.makeContextCurrent = makeContextCurrent;
window->context.swapBuffers = swapBuffers;
window->context.swapInterval = swapInterval;
window->context.extensionSupported = extensionSupported;
window->context.getProcAddress = getProcAddress;
window->context.destroyContext = destroyContext;
return GLFW_TRUE; return GLFW_TRUE;
} }
// Destroy the OpenGL context
//
void _glfwDestroyContextNSGL(_GLFWwindow* window)
{
[window->context.nsgl.pixelFormat release];
window->context.nsgl.pixelFormat = nil;
[window->context.nsgl.object release];
window->context.nsgl.object = nil;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
{
if (window)
[window->context.nsgl.object makeCurrentContext];
else
[NSOpenGLContext clearCurrentContext];
_glfwPlatformSetCurrentContext(window);
}
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
{
// ARP appears to be unnecessary, but this is future-proof
[window->context.nsgl.object flushBuffer];
}
void _glfwPlatformSwapInterval(int interval)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
GLint sync = interval;
[window->context.nsgl.object setValues:&sync
forParameter:NSOpenGLCPSwapInterval];
}
int _glfwPlatformExtensionSupported(const char* extension)
{
// There are no NSGL extensions
return GLFW_FALSE;
}
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
{
CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault,
procname,
kCFStringEncodingASCII);
GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework,
symbolName);
CFRelease(symbolName);
return symbol;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW native API ////// ////// GLFW native API //////
@ -290,7 +294,7 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(nil); _GLFW_REQUIRE_INIT_OR_RETURN(nil);
if (window->context.api == GLFW_NO_API) if (window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL; return NULL;

View File

@ -32,55 +32,6 @@
#include <assert.h> #include <assert.h>
// Initialize WGL-specific extensions
//
static void loadExtensions(void)
{
// Functions for WGL_EXT_extension_string
// NOTE: These are needed by _glfwPlatformExtensionSupported
_glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
wglGetProcAddress("wglGetExtensionsStringEXT");
_glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
wglGetProcAddress("wglGetExtensionsStringARB");
// Functions for WGL_ARB_create_context
_glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
wglGetProcAddress("wglCreateContextAttribsARB");
// Functions for WGL_EXT_swap_control
_glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
wglGetProcAddress("wglSwapIntervalEXT");
// Functions for WGL_ARB_pixel_format
_glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
wglGetProcAddress("wglGetPixelFormatAttribivARB");
// This needs to include every extension used below except for
// WGL_ARB_extensions_string and WGL_EXT_extensions_string
_glfw.wgl.ARB_multisample =
_glfwPlatformExtensionSupported("WGL_ARB_multisample");
_glfw.wgl.ARB_framebuffer_sRGB =
_glfwPlatformExtensionSupported("WGL_ARB_framebuffer_sRGB");
_glfw.wgl.EXT_framebuffer_sRGB =
_glfwPlatformExtensionSupported("WGL_EXT_framebuffer_sRGB");
_glfw.wgl.ARB_create_context =
_glfwPlatformExtensionSupported("WGL_ARB_create_context");
_glfw.wgl.ARB_create_context_profile =
_glfwPlatformExtensionSupported("WGL_ARB_create_context_profile");
_glfw.wgl.EXT_create_context_es2_profile =
_glfwPlatformExtensionSupported("WGL_EXT_create_context_es2_profile");
_glfw.wgl.ARB_create_context_robustness =
_glfwPlatformExtensionSupported("WGL_ARB_create_context_robustness");
_glfw.wgl.EXT_swap_control =
_glfwPlatformExtensionSupported("WGL_EXT_swap_control");
_glfw.wgl.ARB_pixel_format =
_glfwPlatformExtensionSupported("WGL_ARB_pixel_format");
_glfw.wgl.ARB_context_flush_control =
_glfwPlatformExtensionSupported("WGL_ARB_context_flush_control");
_glfw.wgl.extensionsLoaded = GLFW_TRUE;
}
// Returns the specified attribute of the specified pixel format // Returns the specified attribute of the specified pixel format
// //
static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib) static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib)
@ -280,6 +231,157 @@ static GLFWbool isCompositionEnabled(void)
return enabled; return enabled;
} }
static void makeContextCurrent(_GLFWwindow* window)
{
if (window)
{
if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
_glfwPlatformSetCurrentContext(window);
else
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to make context current");
_glfwPlatformSetCurrentContext(NULL);
}
}
else
{
if (!wglMakeCurrent(NULL, NULL))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to clear current context");
}
_glfwPlatformSetCurrentContext(NULL);
}
}
static void swapBuffers(_GLFWwindow* window)
{
// HACK: Use DwmFlush when desktop composition is enabled
if (isCompositionEnabled() && !window->monitor)
{
int count = abs(window->context.wgl.interval);
while (count--)
_glfw_DwmFlush();
}
SwapBuffers(window->context.wgl.dc);
}
static void swapInterval(int interval)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
window->context.wgl.interval = interval;
// HACK: Disable WGL swap interval when desktop composition is enabled to
// avoid interfering with DWM vsync
if (isCompositionEnabled() && !window->monitor)
interval = 0;
if (_glfw.wgl.EXT_swap_control)
_glfw.wgl.SwapIntervalEXT(interval);
}
static int extensionSupported(const char* extension)
{
const char* extensions;
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (_glfw.wgl.GetExtensionsStringEXT)
{
extensions = _glfw.wgl.GetExtensionsStringEXT();
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
}
if (_glfw.wgl.GetExtensionsStringARB)
{
extensions = _glfw.wgl.GetExtensionsStringARB(window->context.wgl.dc);
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
}
return GLFW_FALSE;
}
static GLFWglproc getProcAddress(const char* procname)
{
const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
if (proc)
return proc;
return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname);
}
// Destroy the OpenGL context
//
static void destroyContext(_GLFWwindow* window)
{
if (window->context.wgl.handle)
{
wglDeleteContext(window->context.wgl.handle);
window->context.wgl.handle = NULL;
}
}
// Initialize WGL-specific extensions
//
static void loadExtensions(void)
{
// Functions for WGL_EXT_extension_string
// NOTE: These are needed by extensionSupported
_glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
wglGetProcAddress("wglGetExtensionsStringEXT");
_glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
wglGetProcAddress("wglGetExtensionsStringARB");
// Functions for WGL_ARB_create_context
_glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
wglGetProcAddress("wglCreateContextAttribsARB");
// Functions for WGL_EXT_swap_control
_glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
wglGetProcAddress("wglSwapIntervalEXT");
// Functions for WGL_ARB_pixel_format
_glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
wglGetProcAddress("wglGetPixelFormatAttribivARB");
// This needs to include every extension used below except for
// WGL_ARB_extensions_string and WGL_EXT_extensions_string
_glfw.wgl.ARB_multisample =
extensionSupported("WGL_ARB_multisample");
_glfw.wgl.ARB_framebuffer_sRGB =
extensionSupported("WGL_ARB_framebuffer_sRGB");
_glfw.wgl.EXT_framebuffer_sRGB =
extensionSupported("WGL_EXT_framebuffer_sRGB");
_glfw.wgl.ARB_create_context =
extensionSupported("WGL_ARB_create_context");
_glfw.wgl.ARB_create_context_profile =
extensionSupported("WGL_ARB_create_context_profile");
_glfw.wgl.EXT_create_context_es2_profile =
extensionSupported("WGL_EXT_create_context_es2_profile");
_glfw.wgl.ARB_create_context_robustness =
extensionSupported("WGL_ARB_create_context_robustness");
_glfw.wgl.EXT_swap_control =
extensionSupported("WGL_EXT_swap_control");
_glfw.wgl.ARB_pixel_format =
extensionSupported("WGL_ARB_pixel_format");
_glfw.wgl.ARB_context_flush_control =
extensionSupported("WGL_ARB_context_flush_control");
_glfw.wgl.extensionsLoaded = GLFW_TRUE;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
@ -336,7 +438,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
PIXELFORMATDESCRIPTOR pfd; PIXELFORMATDESCRIPTOR pfd;
HGLRC share = NULL; HGLRC share = NULL;
if (ctxconfig->api == GLFW_NO_API) if (ctxconfig->client == GLFW_NO_API)
return GLFW_TRUE; return GLFW_TRUE;
if (ctxconfig->share) if (ctxconfig->share)
@ -372,7 +474,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
{ {
int index = 0, mask = 0, flags = 0; int index = 0, mask = 0, flags = 0;
if (ctxconfig->api == GLFW_OPENGL_API) if (ctxconfig->client == GLFW_OPENGL_API)
{ {
if (ctxconfig->forward) if (ctxconfig->forward)
flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
@ -474,22 +576,18 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
} }
} }
window->context.makeContextCurrent = makeContextCurrent;
window->context.swapBuffers = swapBuffers;
window->context.swapInterval = swapInterval;
window->context.extensionSupported = extensionSupported;
window->context.getProcAddress = getProcAddress;
window->context.destroyContext = destroyContext;
return GLFW_TRUE; return GLFW_TRUE;
} }
#undef setWGLattrib #undef setWGLattrib
// Destroy the OpenGL context
//
void _glfwDestroyContextWGL(_GLFWwindow* window)
{
if (window->context.wgl.handle)
{
wglDeleteContext(window->context.wgl.handle);
window->context.wgl.handle = NULL;
}
}
// Analyzes the specified context for possible recreation // Analyzes the specified context for possible recreation
// //
int _glfwAnalyzeContextWGL(_GLFWwindow* window, int _glfwAnalyzeContextWGL(_GLFWwindow* window,
@ -501,10 +599,10 @@ int _glfwAnalyzeContextWGL(_GLFWwindow* window,
if (_glfw.wgl.extensionsLoaded) if (_glfw.wgl.extensionsLoaded)
return _GLFW_RECREATION_NOT_NEEDED; return _GLFW_RECREATION_NOT_NEEDED;
_glfwPlatformMakeContextCurrent(window); makeContextCurrent(window);
loadExtensions(); loadExtensions();
if (ctxconfig->api == GLFW_OPENGL_API) if (ctxconfig->client == GLFW_OPENGL_API)
{ {
if (ctxconfig->forward) if (ctxconfig->forward)
{ {
@ -587,102 +685,6 @@ int _glfwAnalyzeContextWGL(_GLFWwindow* window,
} }
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
{
if (window)
{
if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
_glfwPlatformSetCurrentContext(window);
else
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to make context current");
_glfwPlatformSetCurrentContext(NULL);
}
}
else
{
if (!wglMakeCurrent(NULL, NULL))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to clear current context");
}
_glfwPlatformSetCurrentContext(NULL);
}
}
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
{
// HACK: Use DwmFlush when desktop composition is enabled
if (isCompositionEnabled() && !window->monitor)
{
int count = abs(window->context.wgl.interval);
while (count--)
_glfw_DwmFlush();
}
SwapBuffers(window->context.wgl.dc);
}
void _glfwPlatformSwapInterval(int interval)
{
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
window->context.wgl.interval = interval;
// HACK: Disable WGL swap interval when desktop composition is enabled to
// avoid interfering with DWM vsync
if (isCompositionEnabled() && !window->monitor)
interval = 0;
if (_glfw.wgl.EXT_swap_control)
_glfw.wgl.SwapIntervalEXT(interval);
}
int _glfwPlatformExtensionSupported(const char* extension)
{
const char* extensions;
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (_glfw.wgl.GetExtensionsStringEXT)
{
extensions = _glfw.wgl.GetExtensionsStringEXT();
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
}
if (_glfw.wgl.GetExtensionsStringARB)
{
extensions = _glfw.wgl.GetExtensionsStringARB(window->context.wgl.dc);
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
}
return GLFW_FALSE;
}
GLFWglproc _glfwPlatformGetProcAddress(const char* procname)
{
const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
if (proc)
return proc;
return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname);
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW native API ////// ////// GLFW native API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -692,7 +694,7 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (window->context.api == GLFW_NO_API) if (window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL; return NULL;

View File

@ -148,7 +148,6 @@ void _glfwTerminateWGL(void);
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);
void _glfwDestroyContextWGL(_GLFWwindow* window);
int _glfwAnalyzeContextWGL(_GLFWwindow* window, int _glfwAnalyzeContextWGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);

View File

@ -421,14 +421,10 @@ int _glfwPlatformInit(void)
_glfwPlatformPollEvents(); _glfwPlatformPollEvents();
#if defined(_GLFW_WGL)
if (!_glfwInitWGL()) if (!_glfwInitWGL())
return GLFW_FALSE; return GLFW_FALSE;
#elif defined(_GLFW_EGL)
if (!_glfwInitEGL())
return GLFW_FALSE;
#endif
_glfwInitEGL();
_glfwInitTimerWin32(); _glfwInitTimerWin32();
_glfwInitJoysticksWin32(); _glfwInitJoysticksWin32();
@ -449,11 +445,8 @@ void _glfwPlatformTerminate(void)
free(_glfw.win32.clipboardString); free(_glfw.win32.clipboardString);
#if defined(_GLFW_WGL)
_glfwTerminateWGL(); _glfwTerminateWGL();
#elif defined(_GLFW_EGL)
_glfwTerminateEGL(); _glfwTerminateEGL();
#endif
_glfwTerminateJoysticksWin32(); _glfwTerminateJoysticksWin32();
_glfwTerminateThreadLocalStorageWin32(); _glfwTerminateThreadLocalStorageWin32();
@ -463,12 +456,7 @@ void _glfwPlatformTerminate(void)
const char* _glfwPlatformGetVersionString(void) const char* _glfwPlatformGetVersionString(void)
{ {
return _GLFW_VERSION_NUMBER " Win32" return _GLFW_VERSION_NUMBER " Win32 WGL EGL"
#if defined(_GLFW_WGL)
" WGL"
#elif defined(_GLFW_EGL)
" EGL"
#endif
#if defined(__MINGW32__) #if defined(__MINGW32__)
" MinGW" " MinGW"
#elif defined(_MSC_VER) #elif defined(_MSC_VER)

View File

@ -205,16 +205,8 @@ typedef VkResult (APIENTRY *PFN_vkCreateWin32SurfaceKHR)(VkInstance,const VkWin3
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t); typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t);
#include "win32_joystick.h" #include "win32_joystick.h"
#include "wgl_context.h"
#if defined(_GLFW_WGL) #include "egl_context.h"
#include "wgl_context.h"
#elif defined(_GLFW_EGL)
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->win32.handle)
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
#include "egl_context.h"
#else
#error "No supported context creation API selected"
#endif
#define _GLFW_WNDCLASSNAME L"GLFW30" #define _GLFW_WNDCLASSNAME L"GLFW30"
@ -222,6 +214,9 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle) #define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name) #define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->win32.handle)
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32 #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32 #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time #define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time

View File

@ -940,55 +940,58 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (!createWindow(window, wndconfig)) if (!createWindow(window, wndconfig))
return GLFW_FALSE; return GLFW_FALSE;
if (ctxconfig->api != GLFW_NO_API) if (ctxconfig->client != GLFW_NO_API)
{ {
#if defined(_GLFW_WGL) if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
status = _glfwAnalyzeContextWGL(window, ctxconfig, fbconfig);
if (status == _GLFW_RECREATION_IMPOSSIBLE)
return GLFW_FALSE;
if (status == _GLFW_RECREATION_REQUIRED)
{ {
// Some window hints require us to re-create the context using WGL
// extensions retrieved through the current context, as we cannot
// check for WGL extensions or retrieve WGL entry points before we
// have a current context (actually until we have implicitly loaded
// the vendor ICD)
// Yes, this is strange, and yes, this is the proper way on WGL
// As Windows only allows you to set the pixel format once for
// a window, we need to destroy the current window and create a new
// one to be able to use the new pixel format
// Technically, it may be possible to keep the old window around if
// we're just creating an OpenGL 3.0+ context with the same pixel
// format, but it's not worth the added code complexity
// First we clear the current context (the one we just created)
// This is usually done by glfwDestroyWindow, but as we're not doing
// full GLFW window destruction, it's duplicated here
_glfwPlatformMakeContextCurrent(NULL);
// Next destroy the Win32 window and WGL context (without resetting
// or destroying the GLFW window object)
_glfwDestroyContextWGL(window);
destroyWindow(window);
// ...and then create them again, this time with better APIs
if (!createWindow(window, wndconfig))
return GLFW_FALSE;
if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig)) if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig))
return GLFW_FALSE; return GLFW_FALSE;
status = _glfwAnalyzeContextWGL(window, ctxconfig, fbconfig);
if (status == _GLFW_RECREATION_IMPOSSIBLE)
return GLFW_FALSE;
if (status == _GLFW_RECREATION_REQUIRED)
{
// Some window hints require us to re-create the context using WGL
// extensions retrieved through the current context, as we cannot
// check for WGL extensions or retrieve WGL entry points before we
// have a current context (actually until we have implicitly loaded
// the vendor ICD)
// Yes, this is strange, and yes, this is the proper way on WGL
// As Windows only allows you to set the pixel format once for
// a window, we need to destroy the current window and create a new
// one to be able to use the new pixel format
// Technically, it may be possible to keep the old window around if
// we're just creating an OpenGL 3.0+ context with the same pixel
// format, but it's not worth the added code complexity
// First we clear the current context (the one we just created)
// This is usually done by glfwDestroyWindow, but as we're not doing
// full GLFW window destruction, it's duplicated here
window->context.makeContextCurrent(NULL);
// Next destroy the Win32 window and WGL context (without resetting
// or destroying the GLFW window object)
window->context.destroyContext(window);
destroyWindow(window);
// ...and then create them again, this time with better APIs
if (!createWindow(window, wndconfig))
return GLFW_FALSE;
if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
}
else
{
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
} }
#elif defined(_GLFW_EGL)
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
#endif
} }
if (window->monitor) if (window->monitor)
@ -1007,14 +1010,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
if (window->monitor) if (window->monitor)
releaseMonitor(window); releaseMonitor(window);
if (window->context.api != GLFW_NO_API) if (window->context.client != GLFW_NO_API)
{ window->context.destroyContext(window);
#if defined(_GLFW_WGL)
_glfwDestroyContextWGL(window);
#elif defined(_GLFW_EGL)
_glfwDestroyContextEGL(window);
#endif
}
destroyWindow(window); destroyWindow(window);

View File

@ -155,7 +155,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
if (ctxconfig.share) if (ctxconfig.share)
{ {
if (ctxconfig.share->context.api == GLFW_NO_API) if (ctxconfig.share->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL; return NULL;
@ -192,29 +192,31 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
// Save the currently current context so it can be restored later // Save the currently current context so it can be restored later
previous = _glfwPlatformGetCurrentContext(); previous = _glfwPlatformGetCurrentContext();
if (ctxconfig.client != GLFW_NO_API)
glfwMakeContextCurrent(NULL);
// Open the actual window and create its context // Open the actual window and create its context
if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig)) if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig))
{ {
glfwMakeContextCurrent((GLFWwindow*) previous);
glfwDestroyWindow((GLFWwindow*) window); glfwDestroyWindow((GLFWwindow*) window);
_glfwPlatformMakeContextCurrent(previous);
return NULL; return NULL;
} }
if (ctxconfig.api != GLFW_NO_API) if (ctxconfig.client != GLFW_NO_API)
{ {
_glfwPlatformMakeContextCurrent(window); window->context.makeContextCurrent(window);
// Retrieve the actual (as opposed to requested) context attributes // Retrieve the actual (as opposed to requested) context attributes
if (!_glfwRefreshContextAttribs(&ctxconfig)) if (!_glfwRefreshContextAttribs(&ctxconfig))
{ {
glfwMakeContextCurrent((GLFWwindow*) previous);
glfwDestroyWindow((GLFWwindow*) window); glfwDestroyWindow((GLFWwindow*) window);
_glfwPlatformMakeContextCurrent(previous);
return NULL; return NULL;
} }
// Restore the previously current context (or NULL) // Restore the previously current context (or NULL)
_glfwPlatformMakeContextCurrent(previous); glfwMakeContextCurrent((GLFWwindow*) previous);
} }
if (window->monitor) if (window->monitor)
@ -247,9 +249,10 @@ void glfwDefaultWindowHints(void)
memset(&_glfw.hints, 0, sizeof(_glfw.hints)); memset(&_glfw.hints, 0, sizeof(_glfw.hints));
// The default is OpenGL with minimum version 1.0 // The default is OpenGL with minimum version 1.0
_glfw.hints.context.api = GLFW_OPENGL_API; _glfw.hints.context.client = GLFW_OPENGL_API;
_glfw.hints.context.major = 1; _glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API;
_glfw.hints.context.minor = 0; _glfw.hints.context.major = 1;
_glfw.hints.context.minor = 0;
// The default is a focused, visible, resizable window with decorations // The default is a focused, visible, resizable window with decorations
_glfw.hints.window.resizable = GLFW_TRUE; _glfw.hints.window.resizable = GLFW_TRUE;
@ -345,7 +348,10 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
break; break;
case GLFW_CLIENT_API: case GLFW_CLIENT_API:
_glfw.hints.context.api = value; _glfw.hints.context.client = value;
break;
case GLFW_CONTEXT_CREATION_API:
_glfw.hints.context.source = value;
break; break;
case GLFW_CONTEXT_VERSION_MAJOR: case GLFW_CONTEXT_VERSION_MAJOR:
_glfw.hints.context.major = value; _glfw.hints.context.major = value;
@ -396,7 +402,7 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
// The window's context must not be current on another thread when the // The window's context must not be current on another thread when the
// window is destroyed // window is destroyed
if (window == _glfwPlatformGetCurrentContext()) if (window == _glfwPlatformGetCurrentContext())
_glfwPlatformMakeContextCurrent(NULL); glfwMakeContextCurrent(NULL);
// Clear the focused window pointer if this is the focused window // Clear the focused window pointer if this is the focused window
if (_glfw.cursorWindow == window) if (_glfw.cursorWindow == window)
@ -683,7 +689,9 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
case GLFW_FLOATING: case GLFW_FLOATING:
return window->floating; return window->floating;
case GLFW_CLIENT_API: case GLFW_CLIENT_API:
return window->context.api; return window->context.client;
case GLFW_CONTEXT_CREATION_API:
return window->context.source;
case GLFW_CONTEXT_VERSION_MAJOR: case GLFW_CONTEXT_VERSION_MAJOR:
return window->context.major; return window->context.major;
case GLFW_CONTEXT_VERSION_MINOR: case GLFW_CONTEXT_VERSION_MINOR:

View File

@ -49,12 +49,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
#include "posix_time.h" #include "posix_time.h"
#include "linux_joystick.h" #include "linux_joystick.h"
#include "xkb_unicode.h" #include "xkb_unicode.h"
#include "egl_context.h"
#if defined(_GLFW_EGL)
#include "egl_context.h"
#else
#error "The Wayland backend depends on EGL platform support"
#endif
#include "wayland-relative-pointer-unstable-v1-client-protocol.h" #include "wayland-relative-pointer-unstable-v1-client-protocol.h"
#include "wayland-pointer-constraints-unstable-v1-client-protocol.h" #include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
@ -71,6 +66,9 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWayland wl #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWayland wl
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWayland wl #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWayland wl
#define _GLFW_PLATFORM_CONTEXT_STATE
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
// Wayland-specific video mode data // Wayland-specific video mode data
// //

View File

@ -373,7 +373,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (!createSurface(window, wndconfig)) if (!createSurface(window, wndconfig))
return GLFW_FALSE; return GLFW_FALSE;
if (ctxconfig->api != GLFW_NO_API) if (ctxconfig->client != GLFW_NO_API)
{ {
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE; return GLFW_FALSE;
@ -417,7 +417,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
_glfwInputWindowFocus(window, GLFW_FALSE); _glfwInputWindowFocus(window, GLFW_FALSE);
} }
_glfwDestroyContextEGL(window); if (window->context.client != GLFW_NO_API)
window->context.destroyContext(window);
if (window->wl.native) if (window->wl.native)
wl_egl_window_destroy(window->wl.native); wl_egl_window_destroy(window->wl.native);

View File

@ -766,17 +766,13 @@ int _glfwPlatformInit(void)
if (!_glfwInitThreadLocalStoragePOSIX()) if (!_glfwInitThreadLocalStoragePOSIX())
return GLFW_FALSE; return GLFW_FALSE;
#if defined(_GLFW_GLX)
if (!_glfwInitGLX()) if (!_glfwInitGLX())
return GLFW_FALSE; return GLFW_FALSE;
#elif defined(_GLFW_EGL)
if (!_glfwInitEGL())
return GLFW_FALSE;
#endif
if (!_glfwInitJoysticksLinux()) if (!_glfwInitJoysticksLinux())
return GLFW_FALSE; return GLFW_FALSE;
_glfwInitEGL();
_glfwInitTimerPOSIX(); _glfwInitTimerPOSIX();
return GLFW_TRUE; return GLFW_TRUE;
@ -804,9 +800,7 @@ void _glfwPlatformTerminate(void)
_glfw.x11.im = NULL; _glfw.x11.im = NULL;
} }
#if defined(_GLFW_EGL)
_glfwTerminateEGL(); _glfwTerminateEGL();
#endif
if (_glfw.x11.display) if (_glfw.x11.display)
{ {
@ -816,9 +810,7 @@ void _glfwPlatformTerminate(void)
// NOTE: This needs to be done after XCloseDisplay, as libGL registers // NOTE: This needs to be done after XCloseDisplay, as libGL registers
// cleanup callbacks that get called by it // cleanup callbacks that get called by it
#if defined(_GLFW_GLX)
_glfwTerminateGLX(); _glfwTerminateGLX();
#endif
_glfwTerminateJoysticksLinux(); _glfwTerminateJoysticksLinux();
_glfwTerminateThreadLocalStoragePOSIX(); _glfwTerminateThreadLocalStoragePOSIX();
@ -826,12 +818,7 @@ void _glfwPlatformTerminate(void)
const char* _glfwPlatformGetVersionString(void) const char* _glfwPlatformGetVersionString(void)
{ {
return _GLFW_VERSION_NUMBER " X11" return _GLFW_VERSION_NUMBER " X11 GLX EGL"
#if defined(_GLFW_GLX)
" GLX"
#elif defined(_GLFW_EGL)
" EGL"
#endif
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK) #if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
" clock_gettime" " clock_gettime"
#else #else

View File

@ -87,21 +87,16 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(Vk
#include "posix_time.h" #include "posix_time.h"
#include "linux_joystick.h" #include "linux_joystick.h"
#include "xkb_unicode.h" #include "xkb_unicode.h"
#include "glx_context.h"
#if defined(_GLFW_GLX) #include "egl_context.h"
#include "glx_context.h"
#elif defined(_GLFW_EGL)
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->x11.handle)
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.x11.display)
#include "egl_context.h"
#else
#error "No supported context creation API selected"
#endif
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle) #define _glfw_dlclose(handle) dlclose(handle)
#define _glfw_dlsym(handle, name) dlsym(handle, name) #define _glfw_dlsym(handle, name) dlsym(handle, name)
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->x11.handle)
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.x11.display)
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11 #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11 #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11 #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11

View File

@ -1478,34 +1478,40 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
Visual* visual; Visual* visual;
int depth; int depth;
if (ctxconfig->api == GLFW_NO_API) if (ctxconfig->client == GLFW_NO_API)
{ {
visual = DefaultVisual(_glfw.x11.display, _glfw.x11.screen); visual = DefaultVisual(_glfw.x11.display, _glfw.x11.screen);
depth = DefaultDepth(_glfw.x11.display, _glfw.x11.screen); depth = DefaultDepth(_glfw.x11.display, _glfw.x11.screen);
} }
else else
{ {
#if defined(_GLFW_GLX) if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
if (!_glfwChooseVisualGLX(ctxconfig, fbconfig, &visual, &depth)) {
return GLFW_FALSE; if (!_glfwChooseVisualGLX(ctxconfig, fbconfig, &visual, &depth))
#elif defined(_GLFW_EGL) return GLFW_FALSE;
if (!_glfwChooseVisualEGL(ctxconfig, fbconfig, &visual, &depth)) }
return GLFW_FALSE; else
#endif {
if (!_glfwChooseVisualEGL(ctxconfig, fbconfig, &visual, &depth))
return GLFW_FALSE;
}
} }
if (!createWindow(window, wndconfig, visual, depth)) if (!createWindow(window, wndconfig, visual, depth))
return GLFW_FALSE; return GLFW_FALSE;
if (ctxconfig->api != GLFW_NO_API) if (ctxconfig->client != GLFW_NO_API)
{ {
#if defined(_GLFW_GLX) if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
if (!_glfwCreateContextGLX(window, ctxconfig, fbconfig)) {
return GLFW_FALSE; if (!_glfwCreateContextGLX(window, ctxconfig, fbconfig))
#elif defined(_GLFW_EGL) return GLFW_FALSE;
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) }
return GLFW_FALSE; else
#endif {
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
} }
if (window->monitor) if (window->monitor)
@ -1530,14 +1536,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
window->x11.ic = NULL; window->x11.ic = NULL;
} }
if (window->context.api != GLFW_NO_API) if (window->context.client != GLFW_NO_API)
{ window->context.destroyContext(window);
#if defined(_GLFW_GLX)
_glfwDestroyContextGLX(window);
#elif defined(_GLFW_EGL)
_glfwDestroyContextEGL(window);
#endif
}
if (window->x11.handle) if (window->x11.handle)
{ {

View File

@ -41,6 +41,9 @@
#define API_NAME_OPENGL "gl" #define API_NAME_OPENGL "gl"
#define API_NAME_OPENGL_ES "es" #define API_NAME_OPENGL_ES "es"
#define API_NAME_NATIVE "native"
#define API_NAME_EGL "egl"
#define PROFILE_NAME_CORE "core" #define PROFILE_NAME_CORE "core"
#define PROFILE_NAME_COMPAT "compat" #define PROFILE_NAME_COMPAT "compat"
@ -60,6 +63,9 @@ static void usage(void)
printf(" -b, --behavior=BEHAVIOR the release behavior to use (" printf(" -b, --behavior=BEHAVIOR the release behavior to use ("
BEHAVIOR_NAME_NONE " or " BEHAVIOR_NAME_NONE " or "
BEHAVIOR_NAME_FLUSH ")\n"); BEHAVIOR_NAME_FLUSH ")\n");
printf(" -c, --context-api=API the context creation API to use ("
API_NAME_NATIVE " or "
API_NAME_EGL ")\n");
printf(" -d, --debug request a debug context\n"); printf(" -d, --debug request a debug context\n");
printf(" -f, --forward require a forward-compatible context\n"); printf(" -f, --forward require a forward-compatible context\n");
printf(" -h, --help show this help\n"); printf(" -h, --help show this help\n");
@ -165,15 +171,15 @@ static const char* get_strategy_name_glfw(int strategy)
return "unknown"; return "unknown";
} }
static void list_context_extensions(int api, int major, int minor) static void list_context_extensions(int client, int major, int minor)
{ {
int i; int i;
GLint count; GLint count;
const GLubyte* extensions; const GLubyte* extensions;
printf("%s context extensions:\n", get_api_name(api)); printf("%s context extensions:\n", get_api_name(client));
if (api == GLFW_OPENGL_API && major > 2) if (client == GLFW_OPENGL_API && major > 2)
{ {
glGetIntegerv(GL_NUM_EXTENSIONS, &count); glGetIntegerv(GL_NUM_EXTENSIONS, &count);
@ -351,13 +357,13 @@ static void print_version(void)
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
int ch, api, major, minor, revision, profile; int ch, client, context, major, minor, revision, profile;
GLint redbits, greenbits, bluebits, alphabits, depthbits, stencilbits; GLint redbits, greenbits, bluebits, alphabits, depthbits, stencilbits;
int list_extensions = GLFW_FALSE, list_layers = GLFW_FALSE; int list_extensions = GLFW_FALSE, list_layers = GLFW_FALSE;
GLenum error; GLenum error;
GLFWwindow* window; GLFWwindow* window;
enum { API, BEHAVIOR, DEBUG, FORWARD, HELP, EXTENSIONS, LAYERS, enum { CLIENT, CONTEXT, BEHAVIOR, DEBUG, FORWARD, HELP, EXTENSIONS, LAYERS,
MAJOR, MINOR, PROFILE, ROBUSTNESS, VERSION, MAJOR, MINOR, PROFILE, ROBUSTNESS, VERSION,
REDBITS, GREENBITS, BLUEBITS, ALPHABITS, DEPTHBITS, STENCILBITS, REDBITS, GREENBITS, BLUEBITS, ALPHABITS, DEPTHBITS, STENCILBITS,
ACCUMREDBITS, ACCUMGREENBITS, ACCUMBLUEBITS, ACCUMALPHABITS, ACCUMREDBITS, ACCUMGREENBITS, ACCUMBLUEBITS, ACCUMALPHABITS,
@ -365,7 +371,8 @@ int main(int argc, char** argv)
const struct option options[] = const struct option options[] =
{ {
{ "behavior", 1, NULL, BEHAVIOR }, { "behavior", 1, NULL, BEHAVIOR },
{ "client-api", 1, NULL, API }, { "client-api", 1, NULL, CLIENT },
{ "context-api", 1, NULL, CONTEXT },
{ "debug", 0, NULL, DEBUG }, { "debug", 0, NULL, DEBUG },
{ "forward", 0, NULL, FORWARD }, { "forward", 0, NULL, FORWARD },
{ "help", 0, NULL, HELP }, { "help", 0, NULL, HELP },
@ -410,7 +417,7 @@ int main(int argc, char** argv)
switch (ch) switch (ch)
{ {
case 'a': case 'a':
case API: case CLIENT:
if (strcasecmp(optarg, API_NAME_OPENGL) == 0) if (strcasecmp(optarg, API_NAME_OPENGL) == 0)
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
else if (strcasecmp(optarg, API_NAME_OPENGL_ES) == 0) else if (strcasecmp(optarg, API_NAME_OPENGL_ES) == 0)
@ -439,6 +446,18 @@ int main(int argc, char** argv)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
break; break;
case 'c':
case CONTEXT:
if (strcasecmp(optarg, API_NAME_NATIVE) == 0)
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_NATIVE_CONTEXT_API);
else if (strcasecmp(optarg, API_NAME_EGL) == 0)
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
else
{
usage();
exit(EXIT_FAILURE);
}
break;
case 'd': case 'd':
case DEBUG: case DEBUG:
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
@ -616,30 +635,31 @@ int main(int argc, char** argv)
// Report client API version // Report client API version
api = glfwGetWindowAttrib(window, GLFW_CLIENT_API); client = glfwGetWindowAttrib(window, GLFW_CLIENT_API);
context = glfwGetWindowAttrib(window, GLFW_CONTEXT_CREATION_API);
major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR); major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR);
minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR); minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR);
revision = glfwGetWindowAttrib(window, GLFW_CONTEXT_REVISION); revision = glfwGetWindowAttrib(window, GLFW_CONTEXT_REVISION);
profile = glfwGetWindowAttrib(window, GLFW_OPENGL_PROFILE); profile = glfwGetWindowAttrib(window, GLFW_OPENGL_PROFILE);
printf("%s context version string: \"%s\"\n", printf("%s context version string: \"%s\"\n",
get_api_name(api), get_api_name(client),
glGetString(GL_VERSION)); glGetString(GL_VERSION));
printf("%s context version parsed by GLFW: %u.%u.%u\n", printf("%s context version parsed by GLFW: %u.%u.%u\n",
get_api_name(api), get_api_name(client),
major, minor, revision); major, minor, revision);
// Report client API context properties // Report client API context properties
if (api == GLFW_OPENGL_API) if (client == GLFW_OPENGL_API)
{ {
if (major >= 3) if (major >= 3)
{ {
GLint flags; GLint flags;
glGetIntegerv(GL_CONTEXT_FLAGS, &flags); glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
printf("%s context flags (0x%08x):", get_api_name(api), flags); printf("%s context flags (0x%08x):", get_api_name(client), flags);
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT) if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
printf(" forward-compatible"); printf(" forward-compatible");
@ -651,7 +671,7 @@ int main(int argc, char** argv)
printf(" no-error"); printf(" no-error");
putchar('\n'); putchar('\n');
printf("%s context flags parsed by GLFW:", get_api_name(api)); printf("%s context flags parsed by GLFW:", get_api_name(client));
if (glfwGetWindowAttrib(window, GLFW_OPENGL_FORWARD_COMPAT)) if (glfwGetWindowAttrib(window, GLFW_OPENGL_FORWARD_COMPAT))
printf(" forward-compatible"); printf(" forward-compatible");
@ -670,12 +690,12 @@ int main(int argc, char** argv)
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask); glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
printf("%s profile mask (0x%08x): %s\n", printf("%s profile mask (0x%08x): %s\n",
get_api_name(api), get_api_name(client),
mask, mask,
get_profile_name_gl(mask)); get_profile_name_gl(mask));
printf("%s profile mask parsed by GLFW: %s\n", printf("%s profile mask parsed by GLFW: %s\n",
get_api_name(api), get_api_name(client),
get_profile_name_glfw(profile)); get_profile_name_glfw(profile));
} }
@ -686,33 +706,33 @@ int main(int argc, char** argv)
glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy); glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
printf("%s robustness strategy (0x%08x): %s\n", printf("%s robustness strategy (0x%08x): %s\n",
get_api_name(api), get_api_name(client),
strategy, strategy,
get_strategy_name_gl(strategy)); get_strategy_name_gl(strategy));
printf("%s robustness strategy parsed by GLFW: %s\n", printf("%s robustness strategy parsed by GLFW: %s\n",
get_api_name(api), get_api_name(client),
get_strategy_name_glfw(robustness)); get_strategy_name_glfw(robustness));
} }
} }
printf("%s context renderer string: \"%s\"\n", printf("%s context renderer string: \"%s\"\n",
get_api_name(api), get_api_name(client),
glGetString(GL_RENDERER)); glGetString(GL_RENDERER));
printf("%s context vendor string: \"%s\"\n", printf("%s context vendor string: \"%s\"\n",
get_api_name(api), get_api_name(client),
glGetString(GL_VENDOR)); glGetString(GL_VENDOR));
if (major >= 2) if (major >= 2)
{ {
printf("%s context shading language version: \"%s\"\n", printf("%s context shading language version: \"%s\"\n",
get_api_name(api), get_api_name(client),
glGetString(GL_SHADING_LANGUAGE_VERSION)); glGetString(GL_SHADING_LANGUAGE_VERSION));
} }
printf("%s framebuffer:\n", get_api_name(api)); printf("%s framebuffer:\n", get_api_name(client));
if (api == GLFW_OPENGL_API && profile == GLFW_OPENGL_CORE_PROFILE) if (client == GLFW_OPENGL_API && profile == GLFW_OPENGL_CORE_PROFILE)
{ {
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
GL_BACK_LEFT, GL_BACK_LEFT,
@ -752,7 +772,7 @@ int main(int argc, char** argv)
printf(" red: %u green: %u blue: %u alpha: %u depth: %u stencil: %u\n", printf(" red: %u green: %u blue: %u alpha: %u depth: %u stencil: %u\n",
redbits, greenbits, bluebits, alphabits, depthbits, stencilbits); redbits, greenbits, bluebits, alphabits, depthbits, stencilbits);
if (api == GLFW_OPENGL_ES_API || if (client == GLFW_OPENGL_ES_API ||
glfwExtensionSupported("GL_ARB_multisample") || glfwExtensionSupported("GL_ARB_multisample") ||
major > 1 || minor >= 3) major > 1 || minor >= 3)
{ {
@ -763,7 +783,7 @@ int main(int argc, char** argv)
printf(" samples: %u sample buffers: %u\n", samples, samplebuffers); printf(" samples: %u sample buffers: %u\n", samples, samplebuffers);
} }
if (api == GLFW_OPENGL_API && profile != GLFW_OPENGL_CORE_PROFILE) if (client == GLFW_OPENGL_API && profile != GLFW_OPENGL_CORE_PROFILE)
{ {
GLint accumredbits, accumgreenbits, accumbluebits, accumalphabits; GLint accumredbits, accumgreenbits, accumbluebits, accumalphabits;
GLint auxbuffers; GLint auxbuffers;
@ -779,7 +799,7 @@ int main(int argc, char** argv)
} }
if (list_extensions) if (list_extensions)
list_context_extensions(api, major, minor); list_context_extensions(client, major, minor);
printf("Vulkan loader: %s\n", printf("Vulkan loader: %s\n",
glfwVulkanSupported() ? "available" : "missing"); glfwVulkanSupported() ? "available" : "missing");