@ -25,6 +25,7 @@
# include "WindowlessEglApplication.h"
# include <cstring>
# include <string>
# include <Corrade/Utility/Assert.h>
# include <Corrade/Utility/Debug.h>
@ -38,11 +39,80 @@
# include <Corrade/Containers/ArrayView.h>
# endif
# ifndef EGL_EXT_device_base
typedef void * EGLDeviceEXT ;
# endif
# ifndef EGL_EXT_platform_device
# define EGL_PLATFORM_DEVICE_EXT 0x313F
# endif
namespace Magnum { namespace Platform {
namespace {
bool extensionSupported ( const char * const extensions , Containers : : ArrayView < const char > extension ) {
CORRADE_INTERNAL_ASSERT ( extensions ) ;
const char * pos = std : : strstr ( extensions , extension ) ;
/* Extension is supported if its string is delimited by a space or end of
the extension list . The extension . size ( ) is the whole C array including
a 0 - terminator , so subtract 1 to look at one character after . */
return pos & & ( pos [ extension . size ( ) - 1 ] = = ' ' | | pos [ extension . size ( ) - 1 ] = = ' \0 ' ) ;
}
}
WindowlessEglContext : : WindowlessEglContext ( const Configuration & configuration , GLContext * const magnumContext ) {
/* Initialize */
_display = eglGetDisplay ( EGL_DEFAULT_DISPLAY ) ;
/* If relevant extensions are supported, try to find some display using
those APIs , as that works reliably also when running headless . This
would ideally use EGL 1.5 APIs but since we still want to support
systems which either have old EGL headers or old EGL implementation ,
we ' d need to have a code path for 1.4 * and * 1.5 , plus do complicated
version parsing from a string . Not feeling like doing that today , no . */
const char * const extensions = eglQueryString ( EGL_NO_DISPLAY , EGL_EXTENSIONS ) ;
if ( extensions & &
/* eglQueryDevicesEXT() */
extensionSupported ( extensions , " EGL_EXT_device_enumeration " ) & &
/* eglGetPlatformDisplayEXT() */
extensionSupported ( extensions , " EGL_EXT_platform_base " ) & &
/* EGL_PLATFORM_DEVICE_EXT (FFS, why it has to be scattered over a
thousand extensions ? ! ) . This is supported only since Mesa 19.2 . */
extensionSupported ( extensions , " EGL_EXT_platform_device " )
) {
EGLint count ;
auto eglQueryDevices = reinterpret_cast < EGLBoolean ( * ) ( EGLint , EGLDeviceEXT * , EGLint * ) > ( eglGetProcAddress ( " eglQueryDevicesEXT " ) ) ;
if ( ! eglQueryDevices ( 0 , nullptr , & count ) ) {
Error { } < < " Platform::WindowlessEglApplication::tryCreateContext(): cannot query EGL devices: " < < Implementation : : eglErrorString ( eglGetError ( ) ) ;
return ;
}
if ( ! count ) {
Error { } < < " Platform::WindowlessEglApplication::tryCreateContext(): no EGL devices found " ;
return ;
}
if ( magnumContext & & ( magnumContext - > internalFlags ( ) > = GL : : Context : : InternalFlag : : DisplayVerboseInitializationLog ) ) {
Debug { } < < " Platform::WindowlessEglApplication: found " < < count < < " EGL devices, choosing the first one " ;
}
/* Assuming the same thing won't suddenly start failing when called the
second time */
EGLDeviceEXT device ;
CORRADE_INTERNAL_ASSERT_OUTPUT ( eglQueryDevices ( 1 , & device , & count ) ) ;
if ( ! ( _display = reinterpret_cast < EGLDisplay ( * ) ( EGLenum , void * , const EGLint * ) > ( eglGetProcAddress ( " eglGetPlatformDisplayEXT " ) ) ( EGL_PLATFORM_DEVICE_EXT , device , nullptr ) ) ) {
Error { } < < " Platform::WindowlessEglApplication::tryCreateContext(): cannot get platform display for a device: " < < Implementation : : eglErrorString ( eglGetError ( ) ) ;
return ;
}
/* Otherwise initialize the classic way */
} else if ( ! ( _display = eglGetDisplay ( EGL_DEFAULT_DISPLAY ) ) ) {
Error { } < < " Platform::WindowlessEglApplication::tryCreateContext(): cannot get default EGL display: " < < Implementation : : eglErrorString ( eglGetError ( ) ) ;
return ;
}
if ( ! eglInitialize ( _display , nullptr , nullptr ) ) {
Error ( ) < < " Platform::WindowlessEglApplication::tryCreateContext(): cannot initialize EGL: " < < Implementation : : eglErrorString ( eglGetError ( ) ) ;
return ;