From a51f31238162e4899134f0571782b754190200f9 Mon Sep 17 00:00:00 2001 From: Christopher Hesse <48501609+cshesse@users.noreply.github.com> Date: Sun, 8 Dec 2019 21:04:55 -0800 Subject: [PATCH] device index --- docs/window.dox | 6 ++++++ include/GLFW/glfw3.h | 6 +++++- src/egl_context.c | 41 +++++++++++++++++++++++++++++++++++++---- src/egl_context.h | 11 ++++++++--- src/internal.h | 1 + src/window.c | 5 +++++ 6 files changed, 62 insertions(+), 8 deletions(-) diff --git a/docs/window.dox b/docs/window.dox index 868c6c21f..266f8c3b9 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -503,6 +503,12 @@ ASCII encoded class and instance parts of the ICCCM `WM_CLASS` window property. 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 Window hint | Default value | Supported values diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 8b5b87dd1..7b39555c0 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1011,9 +1011,13 @@ extern "C" { */ #define GLFW_X11_CLASS_NAME 0x00024001 /*! @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 +/*! @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 /*! @} */ diff --git a/src/egl_context.c b/src/egl_context.c index 04e69018e..965a8fbf7 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -375,8 +375,6 @@ GLFWbool _glfwInitEGL(void) #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_dlsym(_glfw.egl.handle, "eglMakeCurrent"); @@ -402,7 +400,6 @@ GLFWbool _glfwInitEGL(void) !_glfw.egl.CreateWindowSurface || #if defined(_GLFW_EGLHEADLESS) !_glfw.egl.CreatePbufferSurface || - !_glfw.egl.ChooseConfig || #endif !_glfw.egl.MakeCurrent || !_glfw.egl.SwapBuffers || @@ -418,7 +415,43 @@ GLFWbool _glfwInitEGL(void) } #if defined(_GLFW_EGLHEADLESS) - _glfw.egl.display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + _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); #endif diff --git a/src/egl_context.h b/src/egl_context.h index 4604d96ba..9c11ecdfb 100644 --- a/src/egl_context.h +++ b/src/egl_context.h @@ -47,6 +47,7 @@ typedef struct wl_egl_window* EGLNativeWindowType; #define EGLAPIENTRY typedef void* EGLNativeDisplayType; typedef void* EGLNativeWindowType; +typedef void *EGLDeviceEXT; #else #error "No supported EGL platform selected" #endif @@ -94,6 +95,7 @@ typedef void* EGLNativeWindowType; #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_CORE_PROFILE_BIT_KHR 0x00000001 @@ -140,7 +142,8 @@ typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext); 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*); +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_eglSwapBuffers)(EGLDisplay,EGLSurface); @@ -160,7 +163,8 @@ typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*); #define eglCreateWindowSurface _glfw.egl.CreateWindowSurface #if defined(_GLFW_EGLHEADLESS) #define eglCreatePbufferSurface _glfw.egl.CreatePbufferSurface -#define eglChooseConfig _glfw.egl.ChooseConfig +#define eglQueryDevicesEXT _glfw.egl.QueryDevicesEXT +#define eglGetPlatformDisplayEXT _glfw.egl.GetPlatformDisplayEXT #endif #define eglMakeCurrent _glfw.egl.MakeCurrent #define eglSwapBuffers _glfw.egl.SwapBuffers @@ -213,7 +217,8 @@ typedef struct _GLFWlibraryEGL PFN_eglCreateWindowSurface CreateWindowSurface; #if defined(_GLFW_EGLHEADLESS) PFN_eglCreatePbufferSurface CreatePbufferSurface; - PFN_eglChooseConfig ChooseConfig; + PFN_eglQueryDevicesEXT QueryDevicesEXT; + PFN_eglGetPlatformDisplayEXT GetPlatformDisplayEXT; #endif PFN_eglMakeCurrent MakeCurrent; PFN_eglSwapBuffers SwapBuffers; diff --git a/src/internal.h b/src/internal.h index 6388db3e1..4f3516e65 100644 --- a/src/internal.h +++ b/src/internal.h @@ -525,6 +525,7 @@ struct _GLFWlibrary _GLFWwndconfig window; _GLFWctxconfig context; int refreshRate; + int deviceIndex; } hints; _GLFWerror* errorListHead; diff --git a/src/window.c b/src/window.c index bb5ba9567..61e2b74fc 100644 --- a/src/window.c +++ b/src/window.c @@ -281,6 +281,8 @@ void glfwDefaultWindowHints(void) // The default is to select the highest available refresh rate _glfw.hints.refreshRate = GLFW_DONT_CARE; + _glfw.hints.deviceIndex = 0; + // The default is to use full Retina resolution framebuffers _glfw.hints.window.ns.retina = GLFW_TRUE; } @@ -411,6 +413,9 @@ GLFWAPI void glfwWindowHint(int hint, int value) case GLFW_REFRESH_RATE: _glfw.hints.refreshRate = value; return; + case GLFW_EGL_HEADLESS_DEVICE_INDEX: + _glfw.hints.deviceIndex = value; + return; } _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);