This commit is contained in:
cshesse 2019-12-10 03:07:52 +00:00 committed by GitHub
commit 58a82d74c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 201 additions and 15 deletions

View File

@ -28,6 +28,8 @@ option(GLFW_VULKAN_STATIC "Assume the Vulkan loader is linked with the applicati
include(GNUInstallDirs) include(GNUInstallDirs)
include(CMakeDependentOption) include(CMakeDependentOption)
cmake_dependent_option(GLFW_USE_EGLHEADLESS "Use EGL for offscreen context creation" OFF
"UNIX" OFF)
cmake_dependent_option(GLFW_USE_OSMESA "Use OSMesa for offscreen context creation" OFF cmake_dependent_option(GLFW_USE_OSMESA "Use OSMesa for offscreen context creation" OFF
"UNIX" OFF) "UNIX" OFF)
cmake_dependent_option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF cmake_dependent_option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF
@ -143,6 +145,9 @@ if (GLFW_USE_WAYLAND)
elseif (GLFW_USE_OSMESA) elseif (GLFW_USE_OSMESA)
set(_GLFW_OSMESA 1) set(_GLFW_OSMESA 1)
message(STATUS "Using OSMesa for headless context creation") message(STATUS "Using OSMesa for headless context creation")
elseif (GLFW_USE_EGLHEADLESS)
set(_GLFW_EGLHEADLESS 1)
message(STATUS "Using EGL for headless context creation")
elseif (WIN32) elseif (WIN32)
set(_GLFW_WIN32 1) set(_GLFW_WIN32 1)
message(STATUS "Using Win32 for window creation") message(STATUS "Using Win32 for window creation")
@ -278,6 +283,13 @@ if (_GLFW_OSMESA)
list(APPEND glfw_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}") list(APPEND glfw_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}")
endif() endif()
#--------------------------------------------------------------------
# Use EGL for offscreen context creation
#--------------------------------------------------------------------
if (_GLFW_EGLHEADLESS)
list(APPEND glfw_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}")
endif()
#-------------------------------------------------------------------- #--------------------------------------------------------------------
# Use Cocoa for window creation and NSOpenGL for context creation # Use Cocoa for window creation and NSOpenGL for context creation
#-------------------------------------------------------------------- #--------------------------------------------------------------------

View File

@ -503,6 +503,12 @@ ASCII encoded class and instance parts of the ICCCM `WM_CLASS` window property.
These are set with @ref glfwWindowHintString. These are set with @ref glfwWindowHintString.
@subsubsection window_hints_egl_headless EGL headless specific window hints
@anchor GLFW_EGL_HEADLESS_DEVICE_INDEX_hint
__GLFW_EGL_HEADLESS_DEVICE_INDEX__ specifies the device index to choose when using the EGL headless backend.
@subsubsection window_hints_values Supported and default values @subsubsection window_hints_values Supported and default values
Window hint | Default value | Supported values Window hint | Default value | Supported values

View File

@ -1011,9 +1011,13 @@ extern "C" {
*/ */
#define GLFW_X11_CLASS_NAME 0x00024001 #define GLFW_X11_CLASS_NAME 0x00024001
/*! @brief X11 specific /*! @brief X11 specific
* [window hint](@ref GLFW_X11_CLASS_NAME_hint). * [window hint](@ref GLFW_X11_INSTANCE_NAME_hint).
*/ */
#define GLFW_X11_INSTANCE_NAME 0x00024002 #define GLFW_X11_INSTANCE_NAME 0x00024002
/*! @brief EGL Headless specific
* [window hint](@ref GLFW_EGL_HEADLESS_DEVICE_INDEX_hint).
*/
#define GLFW_EGL_HEADLESS_DEVICE_INDEX 0x00024003
#define GLFW_WIN32_KEYBOARD_MENU 0x00025001 #define GLFW_WIN32_KEYBOARD_MENU 0x00025001
/*! @} */ /*! @} */

View File

@ -60,6 +60,11 @@ elseif (_GLFW_OSMESA)
posix_time.h posix_thread.h osmesa_context.h) posix_time.h posix_thread.h osmesa_context.h)
set(glfw_SOURCES ${common_SOURCES} null_init.c null_monitor.c null_window.c set(glfw_SOURCES ${common_SOURCES} null_init.c null_monitor.c null_window.c
null_joystick.c posix_time.c posix_thread.c osmesa_context.c) null_joystick.c posix_time.c posix_thread.c osmesa_context.c)
elseif (_GLFW_EGLHEADLESS)
set(glfw_HEADERS ${common_HEADERS} null_platform.h null_joystick.h
posix_time.h posix_thread.h egl_context.h)
set(glfw_SOURCES ${common_SOURCES} null_init.c null_monitor.c null_window.c
null_joystick.c posix_time.c posix_thread.c egl_context.c)
endif() endif()
if (_GLFW_X11 OR _GLFW_WAYLAND) if (_GLFW_X11 OR _GLFW_WAYLAND)

View File

@ -34,6 +34,13 @@
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#define setAttrib(a, v) \
{ \
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \
attribs[index++] = v; \
}
// Return a description of the specified EGL error // Return a description of the specified EGL error
// //
@ -118,9 +125,14 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER) if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
continue; continue;
#if defined(_GLFW_EGLHEADLESS)
if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_PBUFFER_BIT))
continue;
#else
// Only consider window EGLConfigs // Only consider window EGLConfigs
if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT)) if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
continue; continue;
#endif
#if defined(_GLFW_X11) #if defined(_GLFW_X11)
XVisualInfo vi = {0}; XVisualInfo vi = {0};
@ -239,13 +251,14 @@ static void swapIntervalEGL(int interval)
static int extensionSupportedEGL(const char* extension) static int extensionSupportedEGL(const char* extension)
{ {
#if !defined(_GLFW_EGLHEADLESS)
const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS); const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
if (extensions) if (extensions)
{ {
if (_glfwStringInExtensionString(extension, extensions)) if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE; return GLFW_TRUE;
} }
#endif
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -359,6 +372,10 @@ GLFWbool _glfwInitEGL(void)
_glfw_dlsym(_glfw.egl.handle, "eglDestroyContext"); _glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
_glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface) _glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface)
_glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface"); _glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
#if defined(_GLFW_EGLHEADLESS)
_glfw.egl.CreatePbufferSurface = (PFN_eglCreatePbufferSurface)
_glfw_dlsym(_glfw.egl.handle, "eglCreatePbufferSurface");
#endif
_glfw.egl.MakeCurrent = (PFN_eglMakeCurrent) _glfw.egl.MakeCurrent = (PFN_eglMakeCurrent)
_glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent"); _glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
_glfw.egl.SwapBuffers = (PFN_eglSwapBuffers) _glfw.egl.SwapBuffers = (PFN_eglSwapBuffers)
@ -381,6 +398,9 @@ GLFWbool _glfwInitEGL(void)
!_glfw.egl.DestroySurface || !_glfw.egl.DestroySurface ||
!_glfw.egl.DestroyContext || !_glfw.egl.DestroyContext ||
!_glfw.egl.CreateWindowSurface || !_glfw.egl.CreateWindowSurface ||
#if defined(_GLFW_EGLHEADLESS)
!_glfw.egl.CreatePbufferSurface ||
#endif
!_glfw.egl.MakeCurrent || !_glfw.egl.MakeCurrent ||
!_glfw.egl.SwapBuffers || !_glfw.egl.SwapBuffers ||
!_glfw.egl.SwapInterval || !_glfw.egl.SwapInterval ||
@ -394,7 +414,47 @@ GLFWbool _glfwInitEGL(void)
return GLFW_FALSE; return GLFW_FALSE;
} }
#if defined(_GLFW_EGLHEADLESS)
_glfw.egl.QueryDevicesEXT = (PFN_eglQueryDevicesEXT)
eglGetProcAddress("eglQueryDevicesEXT");
_glfw.egl.GetPlatformDisplayEXT = (PFN_eglGetPlatformDisplayEXT)
eglGetProcAddress("eglGetPlatformDisplayEXT");
if (!_glfw.egl.QueryDevicesEXT ||
!_glfw.egl.GetPlatformDisplayEXT)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGL: Failed to load required extension entry points");
_glfwTerminateEGL();
return GLFW_FALSE;
}
EGLDeviceEXT devices[16];
EGLint num_devices;
if (!eglQueryDevicesEXT(sizeof(devices) / sizeof(devices[0]), devices, &num_devices)) {
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to get EGL devices: %s",
getEGLErrorString(eglGetError()));
_glfwTerminateEGL();
return GLFW_FALSE;
}
if (_glfw.hints.deviceIndex >= num_devices)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Invalid device index: %d",
_glfw.hints.deviceIndex);
_glfwTerminateEGL();
return GLFW_FALSE;
}
_glfw.egl.display = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, devices[_glfw.hints.deviceIndex], NULL);
#else
_glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY); _glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
#endif
if (_glfw.egl.display == EGL_NO_DISPLAY) if (_glfw.egl.display == EGL_NO_DISPLAY)
{ {
_glfwInputError(GLFW_API_UNAVAILABLE, _glfwInputError(GLFW_API_UNAVAILABLE,
@ -446,13 +506,6 @@ void _glfwTerminateEGL(void)
} }
} }
#define setAttrib(a, v) \
{ \
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \
attribs[index++] = v; \
}
// Create the OpenGL or OpenGL ES context // Create the OpenGL or OpenGL ES context
// //
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
@ -573,10 +626,21 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
} }
} }
#if defined(_GLFW_EGLHEADLESS)
setAttrib(EGL_CONTEXT_MAJOR_VERSION, ctxconfig->major);
setAttrib(EGL_CONTEXT_MINOR_VERSION, ctxconfig->minor);
setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT);
#endif
setAttrib(EGL_NONE, EGL_NONE); setAttrib(EGL_NONE, EGL_NONE);
#if defined(_GLFW_EGLHEADLESS)
window->context.egl.handle = eglCreateContext(_glfw.egl.display,
config, share, NULL);
#else
window->context.egl.handle = eglCreateContext(_glfw.egl.display, window->context.egl.handle = eglCreateContext(_glfw.egl.display,
config, share, attribs); config, share, attribs);
#endif
if (window->context.egl.handle == EGL_NO_CONTEXT) if (window->context.egl.handle == EGL_NO_CONTEXT)
{ {
@ -586,6 +650,18 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
#if defined(_GLFW_EGLHEADLESS)
// Set up attributes for surface creation
{
int width, height;
_glfwPlatformGetFramebufferSize(window, &width, &height);
int index = 0;
setAttrib(EGL_WIDTH, width);
setAttrib(EGL_HEIGHT, height);
setAttrib(EGL_NONE, EGL_NONE);
}
window->context.egl.surface = eglCreatePbufferSurface(_glfw.egl.display, config, attribs);
#else
// Set up attributes for surface creation // Set up attributes for surface creation
{ {
int index = 0; int index = 0;
@ -598,12 +674,12 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
setAttrib(EGL_NONE, EGL_NONE); setAttrib(EGL_NONE, EGL_NONE);
} }
window->context.egl.surface = window->context.egl.surface =
eglCreateWindowSurface(_glfw.egl.display, eglCreateWindowSurface(_glfw.egl.display,
config, config,
_GLFW_EGL_NATIVE_WINDOW, _GLFW_EGL_NATIVE_WINDOW,
attribs); attribs);
#endif
if (window->context.egl.surface == EGL_NO_SURFACE) if (window->context.egl.surface == EGL_NO_SURFACE)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
@ -656,8 +732,12 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
_GLFW_OPENGL_LIBRARY, _GLFW_OPENGL_LIBRARY,
#elif defined(_GLFW_WIN32) #elif defined(_GLFW_WIN32)
#elif defined(_GLFW_COCOA) #elif defined(_GLFW_COCOA)
#else
#if defined(_GLFW_EGLHEADLESS)
"libOpenGL.so.0",
#else #else
"libGL.so.1", "libGL.so.1",
#endif
#endif #endif
NULL NULL
}; };

View File

@ -43,6 +43,11 @@ typedef Window EGLNativeWindowType;
#define EGLAPIENTRY #define EGLAPIENTRY
typedef struct wl_display* EGLNativeDisplayType; typedef struct wl_display* EGLNativeDisplayType;
typedef struct wl_egl_window* EGLNativeWindowType; typedef struct wl_egl_window* EGLNativeWindowType;
#elif defined(_GLFW_EGLHEADLESS)
#define EGLAPIENTRY
typedef void* EGLNativeDisplayType;
typedef void* EGLNativeWindowType;
typedef void *EGLDeviceEXT;
#else #else
#error "No supported EGL platform selected" #error "No supported EGL platform selected"
#endif #endif
@ -67,6 +72,7 @@ typedef struct wl_egl_window* EGLNativeWindowType;
#define EGL_SURFACE_TYPE 0x3033 #define EGL_SURFACE_TYPE 0x3033
#define EGL_WINDOW_BIT 0x0004 #define EGL_WINDOW_BIT 0x0004
#define EGL_RENDERABLE_TYPE 0x3040 #define EGL_RENDERABLE_TYPE 0x3040
#define EGL_PBUFFER_BIT 0x0001
#define EGL_OPENGL_ES_BIT 0x0001 #define EGL_OPENGL_ES_BIT 0x0001
#define EGL_OPENGL_ES2_BIT 0x0004 #define EGL_OPENGL_ES2_BIT 0x0004
#define EGL_OPENGL_BIT 0x0008 #define EGL_OPENGL_BIT 0x0008
@ -87,9 +93,13 @@ typedef struct wl_egl_window* EGLNativeWindowType;
#define EGL_NO_DISPLAY ((EGLDisplay) 0) #define EGL_NO_DISPLAY ((EGLDisplay) 0)
#define EGL_NO_CONTEXT ((EGLContext) 0) #define EGL_NO_CONTEXT ((EGLContext) 0)
#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType) 0) #define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType) 0)
#define EGL_HEIGHT 0x3056
#define EGL_WIDTH 0x3057
#define EGL_PLATFORM_DEVICE_EXT 0x313F
#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 #define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 #define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001
#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002 #define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001 #define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31bd #define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31bd
@ -97,8 +107,11 @@ typedef struct wl_egl_window* EGLNativeWindowType;
#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31bf #define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31bf
#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004 #define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098 #define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
#define EGL_CONTEXT_MAJOR_VERSION 0x3098
#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30fb #define EGL_CONTEXT_MINOR_VERSION_KHR 0x30fb
#define EGL_CONTEXT_MINOR_VERSION 0x30FB
#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30fd #define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30fd
#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD
#define EGL_CONTEXT_FLAGS_KHR 0x30fc #define EGL_CONTEXT_FLAGS_KHR 0x30fc
#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3 #define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3
#define EGL_GL_COLORSPACE_KHR 0x309d #define EGL_GL_COLORSPACE_KHR 0x309d
@ -127,6 +140,11 @@ typedef EGLContext (EGLAPIENTRY * PFN_eglCreateContext)(EGLDisplay,EGLConfig,EGL
typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroySurface)(EGLDisplay,EGLSurface); typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroySurface)(EGLDisplay,EGLSurface);
typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext); typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext);
typedef EGLSurface (EGLAPIENTRY * PFN_eglCreateWindowSurface)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*); typedef EGLSurface (EGLAPIENTRY * PFN_eglCreateWindowSurface)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
#if defined(_GLFW_EGLHEADLESS)
typedef EGLSurface (EGLAPIENTRY * PFN_eglCreatePbufferSurface)(EGLDisplay,EGLConfig,const EGLint*);
typedef EGLSurface (EGLAPIENTRY * PFN_eglQueryDevicesEXT)(EGLint,EGLDeviceEXT*,EGLint*);
typedef EGLSurface (EGLAPIENTRY * PFN_eglGetPlatformDisplayEXT)(EGLenum,EGLNativeDisplayType,const EGLint*);
#endif
typedef EGLBoolean (EGLAPIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLSurface,EGLContext); typedef EGLBoolean (EGLAPIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface); typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface);
typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint); typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint);
@ -143,6 +161,11 @@ typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*);
#define eglDestroySurface _glfw.egl.DestroySurface #define eglDestroySurface _glfw.egl.DestroySurface
#define eglDestroyContext _glfw.egl.DestroyContext #define eglDestroyContext _glfw.egl.DestroyContext
#define eglCreateWindowSurface _glfw.egl.CreateWindowSurface #define eglCreateWindowSurface _glfw.egl.CreateWindowSurface
#if defined(_GLFW_EGLHEADLESS)
#define eglCreatePbufferSurface _glfw.egl.CreatePbufferSurface
#define eglQueryDevicesEXT _glfw.egl.QueryDevicesEXT
#define eglGetPlatformDisplayEXT _glfw.egl.GetPlatformDisplayEXT
#endif
#define eglMakeCurrent _glfw.egl.MakeCurrent #define eglMakeCurrent _glfw.egl.MakeCurrent
#define eglSwapBuffers _glfw.egl.SwapBuffers #define eglSwapBuffers _glfw.egl.SwapBuffers
#define eglSwapInterval _glfw.egl.SwapInterval #define eglSwapInterval _glfw.egl.SwapInterval
@ -192,6 +215,11 @@ typedef struct _GLFWlibraryEGL
PFN_eglDestroySurface DestroySurface; PFN_eglDestroySurface DestroySurface;
PFN_eglDestroyContext DestroyContext; PFN_eglDestroyContext DestroyContext;
PFN_eglCreateWindowSurface CreateWindowSurface; PFN_eglCreateWindowSurface CreateWindowSurface;
#if defined(_GLFW_EGLHEADLESS)
PFN_eglCreatePbufferSurface CreatePbufferSurface;
PFN_eglQueryDevicesEXT QueryDevicesEXT;
PFN_eglGetPlatformDisplayEXT GetPlatformDisplayEXT;
#endif
PFN_eglMakeCurrent MakeCurrent; PFN_eglMakeCurrent MakeCurrent;
PFN_eglSwapBuffers SwapBuffers; PFN_eglSwapBuffers SwapBuffers;
PFN_eglSwapInterval SwapInterval; PFN_eglSwapInterval SwapInterval;

View File

@ -44,6 +44,8 @@
#cmakedefine _GLFW_WAYLAND #cmakedefine _GLFW_WAYLAND
// Define this to 1 if building GLFW for OSMesa // Define this to 1 if building GLFW for OSMesa
#cmakedefine _GLFW_OSMESA #cmakedefine _GLFW_OSMESA
// Define this to 1 if building GLFW for EGLHeadless
#cmakedefine _GLFW_EGLHEADLESS
// 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

@ -189,6 +189,8 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
#include "wl_platform.h" #include "wl_platform.h"
#elif defined(_GLFW_OSMESA) #elif defined(_GLFW_OSMESA)
#include "null_platform.h" #include "null_platform.h"
#elif defined(_GLFW_EGLHEADLESS)
#include "null_platform.h"
#else #else
#error "No supported window creation API selected" #error "No supported window creation API selected"
#endif #endif
@ -523,6 +525,7 @@ struct _GLFWlibrary
_GLFWwndconfig window; _GLFWwndconfig window;
_GLFWctxconfig context; _GLFWctxconfig context;
int refreshRate; int refreshRate;
int deviceIndex;
} hints; } hints;
_GLFWerror* errorListHead; _GLFWerror* errorListHead;

View File

@ -42,11 +42,23 @@ int _glfwPlatformInit(void)
void _glfwPlatformTerminate(void) void _glfwPlatformTerminate(void)
{ {
#if defined(_GLFW_OSMESA)
_glfwTerminateOSMesa(); _glfwTerminateOSMesa();
#elif defined(_GLFW_EGLHEADLESS)
_glfwTerminateEGL();
#else
#error "No supported context selected"
#endif
} }
const char* _glfwPlatformGetVersionString(void) const char* _glfwPlatformGetVersionString(void)
{ {
#if defined(_GLFW_OSMESA)
return _GLFW_VERSION_NUMBER " null OSMesa"; return _GLFW_VERSION_NUMBER " null OSMesa";
#elif defined(_GLFW_EGLHEADLESS)
return _GLFW_VERSION_NUMBER " null EGL Headless";
#else
#error "No supported context selected"
#endif
} }

View File

@ -34,10 +34,22 @@
#define _GLFW_PLATFORM_CURSOR_STATE struct { int dummyCursor; } #define _GLFW_PLATFORM_CURSOR_STATE struct { int dummyCursor; }
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE struct { int dummyLibraryWindow; } #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE struct { int dummyLibraryWindow; }
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE struct { int dummyLibraryContext; } #define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE struct { int dummyLibraryContext; }
#if !defined(_GLFW_EGLHEADLESS)
#define _GLFW_EGL_CONTEXT_STATE struct { int dummyEGLContext; } #define _GLFW_EGL_CONTEXT_STATE struct { int dummyEGLContext; }
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE struct { int dummyEGLLibraryContext; } #define _GLFW_EGL_LIBRARY_CONTEXT_STATE struct { int dummyEGLLibraryContext; }
#endif
#if !defined(_GLFW_OSMESA)
#define _GLFW_OSMESA_CONTEXT_STATE struct { int dummyOSMesaContext; }
#define _GLFW_OSMESA_LIBRARY_CONTEXT_STATE struct { int dummyOSMesaLibraryContext; }
#endif
#if defined(_GLFW_OSMESA)
#include "osmesa_context.h" #include "osmesa_context.h"
#elif defined(_GLFW_EGLHEADLESS)
#include "egl_context.h"
#else
#error "No supported context selected"
#endif
#include "posix_time.h" #include "posix_time.h"
#include "posix_thread.h" #include "posix_thread.h"
#include "null_joystick.h" #include "null_joystick.h"

View File

@ -54,6 +54,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (ctxconfig->client != GLFW_NO_API) if (ctxconfig->client != GLFW_NO_API)
{ {
#if defined(_GLFW_OSMESA)
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API || if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API ||
ctxconfig->source == GLFW_OSMESA_CONTEXT_API) ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
{ {
@ -64,9 +65,25 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
} }
else else
{ {
_glfwInputError(GLFW_API_UNAVAILABLE, "Null: EGL not available"); _glfwInputError(GLFW_API_UNAVAILABLE, "Null: context not available");
return GLFW_FALSE; return GLFW_FALSE;
} }
#elif defined(_GLFW_EGLHEADLESS)
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
{
if (!_glfwInitEGL())
return GLFW_FALSE;
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
else
{
_glfwInputError(GLFW_API_UNAVAILABLE, "Null: context not available");
return GLFW_FALSE;
}
#else
#error "No supported context selected"
#endif
} }
return GLFW_TRUE; return GLFW_TRUE;

View File

@ -281,6 +281,8 @@ void glfwDefaultWindowHints(void)
// The default is to select the highest available refresh rate // The default is to select the highest available refresh rate
_glfw.hints.refreshRate = GLFW_DONT_CARE; _glfw.hints.refreshRate = GLFW_DONT_CARE;
_glfw.hints.deviceIndex = 0;
// The default is to use full Retina resolution framebuffers // The default is to use full Retina resolution framebuffers
_glfw.hints.window.ns.retina = GLFW_TRUE; _glfw.hints.window.ns.retina = GLFW_TRUE;
} }
@ -411,6 +413,9 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_REFRESH_RATE: case GLFW_REFRESH_RATE:
_glfw.hints.refreshRate = value; _glfw.hints.refreshRate = value;
return; return;
case GLFW_EGL_HEADLESS_DEVICE_INDEX:
_glfw.hints.deviceIndex = value;
return;
} }
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint); _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);