egl headless

This commit is contained in:
Christopher Hesse 2019-12-08 19:49:04 -08:00
parent 7dbdd2e6a5
commit 0408ee93f1
9 changed files with 170 additions and 15 deletions

View File

@ -28,8 +28,10 @@ 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_OSMESA "Use OSMesa for offscreen context creation" OFF cmake_dependent_option(GLFW_USE_EGLHEADLESS "Use EGL for offscreen context creation" OFF
"UNIX" OFF) "UNIX" OFF)
cmake_dependent_option(GLFW_USE_OSMESA "Use OSMesa for offscreen context creation" 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
"WIN32" OFF) "WIN32" OFF)
cmake_dependent_option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF cmake_dependent_option(GLFW_USE_WAYLAND "Use Wayland for window creation" 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

@ -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
// //
@ -91,6 +98,33 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* desired, const _GLFWfbconfig* desired,
EGLConfig* result) EGLConfig* result)
{ {
#if defined(_GLFW_EGLHEADLESS)
{
EGLint attribs[40];
int index = 0;
setAttrib(EGL_SURFACE_TYPE, EGL_PBUFFER_BIT);
setAttrib(EGL_BLUE_SIZE, 8);
setAttrib(EGL_GREEN_SIZE, 8);
setAttrib(EGL_RED_SIZE, 8);
setAttrib(EGL_DEPTH_SIZE, 8);
if (ctxconfig->client == GLFW_OPENGL_ES_API)
{
setAttrib(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT);
}
else
{
setAttrib(EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT);
}
setAttrib(EGL_NONE, EGL_NONE);
int num_configs;
if (!eglChooseConfig(_glfw.egl.display, attribs, result, 1, &num_configs) || num_configs == 0) {
return GLFW_FALSE;
}
return GLFW_TRUE;
}
#else
EGLConfig* nativeConfigs; EGLConfig* nativeConfigs;
_GLFWfbconfig* usableConfigs; _GLFWfbconfig* usableConfigs;
const _GLFWfbconfig* closest; const _GLFWfbconfig* closest;
@ -186,6 +220,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
free(usableConfigs); free(usableConfigs);
return closest != NULL; return closest != NULL;
#endif
} }
static void makeContextCurrentEGL(_GLFWwindow* window) static void makeContextCurrentEGL(_GLFWwindow* window)
@ -239,13 +274,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 +395,12 @@ 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");
_glfw.egl.ChooseConfig = (PFN_eglChooseConfig)
_glfw_dlsym(_glfw.egl.handle, "eglChooseConfig");
#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 +423,10 @@ 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 ||
!_glfw.egl.ChooseConfig ||
#endif
!_glfw.egl.MakeCurrent || !_glfw.egl.MakeCurrent ||
!_glfw.egl.SwapBuffers || !_glfw.egl.SwapBuffers ||
!_glfw.egl.SwapInterval || !_glfw.egl.SwapInterval ||
@ -394,7 +440,11 @@ GLFWbool _glfwInitEGL(void)
return GLFW_FALSE; return GLFW_FALSE;
} }
#if defined(_GLFW_EGLHEADLESS)
_glfw.egl.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
#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 +496,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,
@ -462,7 +505,6 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
EGLint attribs[40]; EGLint attribs[40];
EGLConfig config; EGLConfig config;
EGLContext share = NULL; EGLContext share = NULL;
int index = 0;
if (!_glfw.egl.display) if (!_glfw.egl.display)
{ {
@ -501,6 +543,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
} }
} }
int index = 0;
if (_glfw.egl.KHR_create_context) if (_glfw.egl.KHR_create_context)
{ {
int mask = 0, flags = 0; int mask = 0, flags = 0;
@ -573,10 +616,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 +640,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 +664,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 +722,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,10 @@ 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;
#else #else
#error "No supported EGL platform selected" #error "No supported EGL platform selected"
#endif #endif
@ -67,6 +71,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 +92,12 @@ 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_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 +105,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 +138,10 @@ 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 EGLBoolean (EGLAPIENTRY * PFN_eglChooseConfig)(EGLDisplay,const EGLint*,EGLConfig,EGLint,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 +158,10 @@ 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 eglChooseConfig _glfw.egl.ChooseConfig
#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 +211,10 @@ 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_eglChooseConfig ChooseConfig;
#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

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; }
#define _GLFW_EGL_CONTEXT_STATE struct { int dummyEGLContext; } #if !defined(_GLFW_EGLHEADLESS)
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE struct { int dummyEGLLibraryContext; } #define _GLFW_EGL_CONTEXT_STATE struct { int dummyEGLContext; }
#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
#include "osmesa_context.h" #if defined(_GLFW_OSMESA)
#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;