@ -82,18 +82,30 @@ bool extensionSupported(const char* const extensions, Containers::ArrayView<cons
# endif
# endif
WindowlessEglContext : : WindowlessEglContext ( const Configuration & configuration , GLContext * const magnumContext ) {
WindowlessEglContext : : WindowlessEglContext ( const Configuration & configuration , GLContext * const magnumContext ) {
# ifndef MAGNUM_TARGET_WEBGL
/* The user provided a shared context, use the associated display
directly . We don ' t call eglInitialize ( ) in this case either - - the
context we share with already did that on the provided display */
if ( configuration . sharedContext ( ) ! = EGL_NO_CONTEXT & & configuration . sharedDisplay ( ) ! = EGL_NO_DISPLAY ) {
_display = configuration . sharedDisplay ( ) ;
_sharedContext = true ;
} else
# endif
/* Otherwise find the display and initialize EGL */
{
# ifndef MAGNUM_TARGET_WEBGL
# ifndef MAGNUM_TARGET_WEBGL
/* If relevant extensions are supported, try to find some display using
/* If relevant extensions are supported, try to find some display using
those APIs , as that works reliably also when running headless . This
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
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 ,
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
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 . */
version parsing from a string . Not feeling like doing that today ,
no . */
const char * const extensions = eglQueryString ( EGL_NO_DISPLAY , EGL_EXTENSIONS ) ;
const char * const extensions = eglQueryString ( EGL_NO_DISPLAY , EGL_EXTENSIONS ) ;
if ( extensions & &
if ( extensions & &
/* eglQueryDevicesEXT(). NVidia exposes only EGL_EXT_device_base, which
/* eglQueryDevicesEXT(). NVidia exposes only EGL_EXT_device_base,
is an older version of EGL_EXT_device_enumeration before it got
which is an older version of EGL_EXT_device_enumeration before
split to that and EGL_EXT_device_query , so test for both . */
it got split to that and EGL_EXT_device_query , so test for both . */
( extensionSupported ( extensions , " EGL_EXT_device_enumeration " ) | | extensionSupported ( extensions , " EGL_EXT_device_base " ) ) & &
( extensionSupported ( extensions , " EGL_EXT_device_enumeration " ) | | extensionSupported ( extensions , " EGL_EXT_device_base " ) ) & &
/* eglGetPlatformDisplayEXT() */
/* eglGetPlatformDisplayEXT() */
@ -106,9 +118,9 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
/* When libEGL_nvidia.so is present on a system w/o a NV GPU,
/* When libEGL_nvidia.so is present on a system w/o a NV GPU,
eglQueryDevicesEXT ( ) fails there with EGL_BAD_ALLOC , but that is
eglQueryDevicesEXT ( ) fails there with EGL_BAD_ALLOC , but that is
never propagated to the glvnd wrapper . Enable debug output if
never propagated to the glvnd wrapper . Enable debug output if
- - magnum - gpu - validation is enabled because otherwise it ' s fucking
- - magnum - gpu - validation is enabled because otherwise it ' s
hard to discover what ' s to blame ( lost > 3 hours already ) . See class
fucking hard to discover what ' s to blame ( lost > 3 hours
docs for more info and a workaround . */
already ) . See class docs for more info and a workaround . */
if ( extensionSupported ( extensions , " EGL_KHR_debug " ) & & magnumContext & & ( magnumContext - > internalFlags ( ) & GL : : Context : : InternalFlag : : GpuValidation ) ) {
if ( extensionSupported ( extensions , " EGL_KHR_debug " ) & & magnumContext & & ( magnumContext - > internalFlags ( ) & GL : : Context : : InternalFlag : : GpuValidation ) ) {
auto eglDebugMessageControl = reinterpret_cast < EGLint ( * ) ( EGLDEBUGPROCKHR , const EGLAttrib * ) > ( eglGetProcAddress ( " eglDebugMessageControlKHR " ) ) ;
auto eglDebugMessageControl = reinterpret_cast < EGLint ( * ) ( EGLDEBUGPROCKHR , const EGLAttrib * ) > ( eglGetProcAddress ( " eglDebugMessageControlKHR " ) ) ;
const EGLAttrib debugAttribs [ ] = {
const EGLAttrib debugAttribs [ ] = {
@ -145,8 +157,8 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
Debug { } < < " Platform::WindowlessEglApplication: found " < < count < < " EGL devices, choosing device " < < configuration . device ( ) ;
Debug { } < < " Platform::WindowlessEglApplication: found " < < count < < " EGL devices, choosing device " < < configuration . device ( ) ;
}
}
/* Assuming the same thing won't suddenly start failing when called the
/* Assuming the same thing won't suddenly start failing when called
second time */
the second time */
Containers : : Array < EGLDeviceEXT > devices { configuration . device ( ) + 1 } ;
Containers : : Array < EGLDeviceEXT > devices { configuration . device ( ) + 1 } ;
CORRADE_INTERNAL_ASSERT_OUTPUT ( eglQueryDevices ( configuration . device ( ) + 1 , devices , & count ) ) ;
CORRADE_INTERNAL_ASSERT_OUTPUT ( eglQueryDevices ( configuration . device ( ) + 1 , devices , & count ) ) ;
@ -154,10 +166,10 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
Error { } < < " Platform::WindowlessEglApplication::tryCreateContext(): cannot get platform display for a device: " < < Implementation : : eglErrorString ( eglGetError ( ) ) ;
Error { } < < " Platform::WindowlessEglApplication::tryCreateContext(): cannot get platform display for a device: " < < Implementation : : eglErrorString ( eglGetError ( ) ) ;
return ;
return ;
}
}
} else
}
# endif
/* Otherwise initialize the classic way. WebGL doesn't have any of the
/* Otherwise initialize the classic way. WebGL doesn't have any of the
above , so no need to compile that at all . */
above , so no need to compile that at all . */
# endif
{
{
# ifndef MAGNUM_TARGET_WEBGL
# ifndef MAGNUM_TARGET_WEBGL
if ( configuration . device ( ) ! = 0 ) {
if ( configuration . device ( ) ! = 0 ) {
@ -176,6 +188,7 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
Error ( ) < < " Platform::WindowlessEglApplication::tryCreateContext(): cannot initialize EGL: " < < Implementation : : eglErrorString ( eglGetError ( ) ) ;
Error ( ) < < " Platform::WindowlessEglApplication::tryCreateContext(): cannot initialize EGL: " < < Implementation : : eglErrorString ( eglGetError ( ) ) ;
return ;
return ;
}
}
}
const EGLenum api =
const EGLenum api =
# ifndef MAGNUM_TARGET_GLES
# ifndef MAGNUM_TARGET_GLES
@ -299,7 +312,15 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G
# endif
# endif
}
}
WindowlessEglContext : : WindowlessEglContext ( WindowlessEglContext & & other ) : _display { other . _display } , _context { other . _context } {
WindowlessEglContext : : WindowlessEglContext ( WindowlessEglContext & & other ) :
# ifndef MAGNUM_TARGET_WEBGL
_sharedContext { other . _sharedContext } ,
# endif
_display { other . _display } , _context { other . _context }
{
# ifndef MAGNUM_TARGET_WEBGL
other . _sharedContext = false ;
# endif
other . _display = { } ;
other . _display = { } ;
other . _context = { } ;
other . _context = { } ;
}
}
@ -309,11 +330,23 @@ WindowlessEglContext::~WindowlessEglContext() {
# if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL)
# if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL)
if ( _surface ) eglDestroySurface ( _display , _surface ) ;
if ( _surface ) eglDestroySurface ( _display , _surface ) ;
# endif
# endif
if ( _display ) eglTerminate ( _display ) ;
/* Don't terminate EGL if we're a shared context as it would kill all
others as well . In case of a shared context it ' s expected that the
first instance of WindowlessEglContext in the shared chain is destroyed
last , calling eglTerminate ( ) after all others are gone . */
if (
# ifndef MAGNUM_TARGET_WEBGL
! _sharedContext & &
# endif
_display ) eglTerminate ( _display ) ;
}
}
WindowlessEglContext & WindowlessEglContext : : operator = ( WindowlessEglContext & & other ) {
WindowlessEglContext & WindowlessEglContext : : operator = ( WindowlessEglContext & & other ) {
using std : : swap ;
using std : : swap ;
# ifndef MAGNUM_TARGET_WEBGL
swap ( other . _sharedContext , _sharedContext ) ;
# endif
swap ( other . _display , _display ) ;
swap ( other . _display , _display ) ;
swap ( other . _context , _context ) ;
swap ( other . _context , _context ) ;
return * this ;
return * this ;
@ -390,6 +423,16 @@ bool WindowlessEglApplication::tryCreateContext(const Configuration& configurati
return true ;
return true ;
}
}
# ifndef MAGNUM_TARGET_WEBGL
auto WindowlessEglContext : : Configuration : : setSharedContext ( EGLDisplay display , EGLContext context ) - > Configuration & {
CORRADE_ASSERT ( ( context = = EGL_NO_CONTEXT ) = = ( display = = EGL_NO_DISPLAY ) ,
" Platform::WindowlessEglContext::Configuration::setSharedContext(): either both the context and the display have to be valid or both null " , * this ) ;
_sharedDisplay = display ;
_sharedContext = context ;
return * this ;
}
# endif
WindowlessEglApplication : : ~ WindowlessEglApplication ( ) = default ;
WindowlessEglApplication : : ~ WindowlessEglApplication ( ) = default ;
} }
} }