@ -156,7 +156,7 @@ out:
free ( formats ) ;
free ( formats ) ;
}
}
struct wlr_egl * wlr_ egl_create_with_drm_fd ( int drm_f d) {
static struct wlr_egl * egl_create( vo id) {
struct wlr_egl * egl = calloc ( 1 , sizeof ( struct wlr_egl ) ) ;
struct wlr_egl * egl = calloc ( 1 , sizeof ( struct wlr_egl ) ) ;
if ( egl = = NULL ) {
if ( egl = = NULL ) {
wlr_log_errno ( WLR_ERROR , " Allocation failed " ) ;
wlr_log_errno ( WLR_ERROR , " Allocation failed " ) ;
@ -172,11 +172,7 @@ struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) {
}
}
return NULL ;
return NULL ;
}
}
wlr_log ( WLR_INFO , " Supported EGL client extensions: %s " , client_exts_str ) ;
if ( ! check_egl_ext ( client_exts_str , " EGL_KHR_platform_gbm " ) ) {
wlr_log ( WLR_ERROR , " EGL_KHR_platform_gbm not supported " ) ;
return NULL ;
}
if ( ! check_egl_ext ( client_exts_str , " EGL_EXT_platform_base " ) ) {
if ( ! check_egl_ext ( client_exts_str , " EGL_EXT_platform_base " ) ) {
wlr_log ( WLR_ERROR , " EGL_EXT_platform_base not supported " ) ;
wlr_log ( WLR_ERROR , " EGL_EXT_platform_base not supported " ) ;
@ -185,6 +181,24 @@ struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) {
load_egl_proc ( & egl - > procs . eglGetPlatformDisplayEXT ,
load_egl_proc ( & egl - > procs . eglGetPlatformDisplayEXT ,
" eglGetPlatformDisplayEXT " ) ;
" eglGetPlatformDisplayEXT " ) ;
egl - > exts . KHR_platform_gbm = check_egl_ext ( client_exts_str ,
" EGL_KHR_platform_gbm " ) ;
egl - > exts . EXT_platform_device = check_egl_ext ( client_exts_str ,
" EGL_EXT_platform_device " ) ;
if ( check_egl_ext ( client_exts_str , " EGL_EXT_device_enumeration " ) ) {
load_egl_proc ( & egl - > procs . eglQueryDevicesEXT , " eglQueryDevicesEXT " ) ;
}
if ( check_egl_ext ( client_exts_str , " EGL_EXT_device_query " ) ) {
egl - > exts . EXT_device_query = true ;
load_egl_proc ( & egl - > procs . eglQueryDeviceStringEXT ,
" eglQueryDeviceStringEXT " ) ;
load_egl_proc ( & egl - > procs . eglQueryDisplayAttribEXT ,
" eglQueryDisplayAttribEXT " ) ;
}
if ( check_egl_ext ( client_exts_str , " EGL_KHR_debug " ) ) {
if ( check_egl_ext ( client_exts_str , " EGL_KHR_debug " ) ) {
load_egl_proc ( & egl - > procs . eglDebugMessageControlKHR ,
load_egl_proc ( & egl - > procs . eglDebugMessageControlKHR ,
" eglDebugMessageControlKHR " ) ;
" eglDebugMessageControlKHR " ) ;
@ -201,32 +215,31 @@ struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) {
if ( eglBindAPI ( EGL_OPENGL_ES_API ) = = EGL_FALSE ) {
if ( eglBindAPI ( EGL_OPENGL_ES_API ) = = EGL_FALSE ) {
wlr_log ( WLR_ERROR , " Failed to bind to the OpenGL ES API " ) ;
wlr_log ( WLR_ERROR , " Failed to bind to the OpenGL ES API " ) ;
goto error ;
return NULL ;
}
}
egl - > gbm_device = gbm_create_device ( drm_fd ) ;
return egl ;
if ( ! egl - > gbm_device ) {
}
wlr_log ( WLR_ERROR , " Failed to create GBM device " ) ;
goto error ;
}
egl - > display = egl - > procs . eglGetPlatformDisplayEXT ( EGL_PLATFORM_GBM_KHR ,
static bool egl_init ( struct wlr_egl * egl , EGLenum platform ,
egl - > gbm_device , NULL ) ;
void * remote_display ) {
egl - > display = egl - > procs . eglGetPlatformDisplayEXT ( platform ,
remote_display , NULL ) ;
if ( egl - > display = = EGL_NO_DISPLAY ) {
if ( egl - > display = = EGL_NO_DISPLAY ) {
wlr_log ( WLR_ERROR , " Failed to create EGL display " ) ;
wlr_log ( WLR_ERROR , " Failed to create EGL display " ) ;
goto error ;
return false ;
}
}
EGLint major , minor ;
EGLint major , minor ;
if ( eglInitialize ( egl - > display , & major , & minor ) = = EGL_FALSE ) {
if ( eglInitialize ( egl - > display , & major , & minor ) = = EGL_FALSE ) {
wlr_log ( WLR_ERROR , " Failed to initialize EGL " ) ;
wlr_log ( WLR_ERROR , " Failed to initialize EGL " ) ;
goto error ;
return false ;
}
}
const char * display_exts_str = eglQueryString ( egl - > display , EGL_EXTENSIONS ) ;
const char * display_exts_str = eglQueryString ( egl - > display , EGL_EXTENSIONS ) ;
if ( display_exts_str = = NULL ) {
if ( display_exts_str = = NULL ) {
wlr_log ( WLR_ERROR , " Failed to query EGL display extensions " ) ;
wlr_log ( WLR_ERROR , " Failed to query EGL display extensions " ) ;
return NULL ;
return false ;
}
}
if ( check_egl_ext ( display_exts_str , " EGL_KHR_image_base " ) ) {
if ( check_egl_ext ( display_exts_str , " EGL_KHR_image_base " ) ) {
@ -247,17 +260,12 @@ struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) {
}
}
const char * device_exts_str = NULL , * driver_name = NULL ;
const char * device_exts_str = NULL , * driver_name = NULL ;
if ( check_egl_ext ( client_exts_str , " EGL_EXT_device_query " ) ) {
if ( egl - > exts . EXT_device_query ) {
load_egl_proc ( & egl - > procs . eglQueryDisplayAttribEXT ,
" eglQueryDisplayAttribEXT " ) ;
load_egl_proc ( & egl - > procs . eglQueryDeviceStringEXT ,
" eglQueryDeviceStringEXT " ) ;
EGLAttrib device_attrib ;
EGLAttrib device_attrib ;
if ( ! egl - > procs . eglQueryDisplayAttribEXT ( egl - > display ,
if ( ! egl - > procs . eglQueryDisplayAttribEXT ( egl - > display ,
EGL_DEVICE_EXT , & device_attrib ) ) {
EGL_DEVICE_EXT , & device_attrib ) ) {
wlr_log ( WLR_ERROR , " eglQueryDisplayAttribEXT(EGL_DEVICE_EXT) failed " ) ;
wlr_log ( WLR_ERROR , " eglQueryDisplayAttribEXT(EGL_DEVICE_EXT) failed " ) ;
goto error ;
return false ;
}
}
egl - > device = ( EGLDeviceEXT ) device_attrib ;
egl - > device = ( EGLDeviceEXT ) device_attrib ;
@ -265,7 +273,7 @@ struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) {
egl - > procs . eglQueryDeviceStringEXT ( egl - > device , EGL_EXTENSIONS ) ;
egl - > procs . eglQueryDeviceStringEXT ( egl - > device , EGL_EXTENSIONS ) ;
if ( device_exts_str = = NULL ) {
if ( device_exts_str = = NULL ) {
wlr_log ( WLR_ERROR , " eglQueryDeviceStringEXT(EGL_EXTENSIONS) failed " ) ;
wlr_log ( WLR_ERROR , " eglQueryDeviceStringEXT(EGL_EXTENSIONS) failed " ) ;
goto error ;
return false ;
}
}
if ( check_egl_ext ( device_exts_str , " EGL_MESA_device_software " ) ) {
if ( check_egl_ext ( device_exts_str , " EGL_MESA_device_software " ) ) {
@ -276,7 +284,7 @@ struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) {
wlr_log ( WLR_ERROR , " Software rendering detected, please use "
wlr_log ( WLR_ERROR , " Software rendering detected, please use "
" the WLR_RENDERER_ALLOW_SOFTWARE environment variable "
" the WLR_RENDERER_ALLOW_SOFTWARE environment variable "
" to proceed " ) ;
" to proceed " ) ;
goto error ;
return false ;
}
}
}
}
@ -297,21 +305,19 @@ struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) {
! check_egl_ext ( display_exts_str , " EGL_MESA_configless_context " ) ) {
! check_egl_ext ( display_exts_str , " EGL_MESA_configless_context " ) ) {
wlr_log ( WLR_ERROR , " EGL_KHR_no_config_context or "
wlr_log ( WLR_ERROR , " EGL_KHR_no_config_context or "
" EGL_MESA_configless_context not supported " ) ;
" EGL_MESA_configless_context not supported " ) ;
goto error ;
return false ;
}
}
if ( ! check_egl_ext ( display_exts_str , " EGL_KHR_surfaceless_context " ) ) {
if ( ! check_egl_ext ( display_exts_str , " EGL_KHR_surfaceless_context " ) ) {
wlr_log ( WLR_ERROR ,
wlr_log ( WLR_ERROR , " EGL_KHR_surfaceless_context not supported " ) ;
" EGL_KHR_surfaceless_context not supported " ) ;
return false ;
goto error ;
}
}
wlr_log ( WLR_INFO , " Using EGL %d.%d " , ( int ) major , ( int ) minor ) ;
wlr_log ( WLR_INFO , " Supported EGL client extensions: %s " , client_exts_str ) ;
wlr_log ( WLR_INFO , " Supported EGL display extensions: %s " , display_exts_str ) ;
wlr_log ( WLR_INFO , " Supported EGL display extensions: %s " , display_exts_str ) ;
if ( device_exts_str ! = NULL ) {
if ( device_exts_str ! = NULL ) {
wlr_log ( WLR_INFO , " Supported EGL device extensions: %s " , device_exts_str ) ;
wlr_log ( WLR_INFO , " Supported EGL device extensions: %s " , device_exts_str ) ;
}
}
wlr_log ( WLR_INFO , " Using EGL %d.%d " , ( int ) major , ( int ) minor ) ;
wlr_log ( WLR_INFO , " EGL vendor: %s " , eglQueryString ( egl - > display , EGL_VENDOR ) ) ;
wlr_log ( WLR_INFO , " EGL vendor: %s " , eglQueryString ( egl - > display , EGL_VENDOR ) ) ;
if ( driver_name ! = NULL ) {
if ( driver_name ! = NULL ) {
wlr_log ( WLR_INFO , " EGL driver name: %s " , driver_name ) ;
wlr_log ( WLR_INFO , " EGL driver name: %s " , driver_name ) ;
@ -345,7 +351,7 @@ struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) {
EGL_NO_CONTEXT , attribs ) ;
EGL_NO_CONTEXT , attribs ) ;
if ( egl - > context = = EGL_NO_CONTEXT ) {
if ( egl - > context = = EGL_NO_CONTEXT ) {
wlr_log ( WLR_ERROR , " Failed to create EGL context " ) ;
wlr_log ( WLR_ERROR , " Failed to create EGL context " ) ;
goto error ;
return false ;
}
}
if ( request_high_priority ) {
if ( request_high_priority ) {
@ -359,13 +365,112 @@ struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) {
}
}
}
}
return egl ;
return true ;
}
static bool device_has_name ( const drmDevice * device , const char * name ) ;
static EGLDeviceEXT get_egl_device_from_drm_fd ( struct wlr_egl * egl ,
int drm_fd ) {
if ( egl - > procs . eglQueryDevicesEXT = = NULL ) {
wlr_log ( WLR_DEBUG , " EGL_EXT_device_enumeration not supported " ) ;
return EGL_NO_DEVICE_EXT ;
}
EGLint nb_devices = 0 ;
if ( ! egl - > procs . eglQueryDevicesEXT ( 0 , NULL , & nb_devices ) ) {
wlr_log ( WLR_ERROR , " Failed to query EGL devices " ) ;
return EGL_NO_DEVICE_EXT ;
}
EGLDeviceEXT * devices = calloc ( nb_devices , sizeof ( EGLDeviceEXT ) ) ;
if ( devices = = NULL ) {
wlr_log_errno ( WLR_ERROR , " Failed to allocate EGL device list " ) ;
return EGL_NO_DEVICE_EXT ;
}
if ( ! egl - > procs . eglQueryDevicesEXT ( nb_devices , devices , & nb_devices ) ) {
wlr_log ( WLR_ERROR , " Failed to query EGL devices " ) ;
return EGL_NO_DEVICE_EXT ;
}
drmDevice * device = NULL ;
int ret = drmGetDevice ( drm_fd , & device ) ;
if ( ret < 0 ) {
wlr_log ( WLR_ERROR , " Failed to get DRM device: %s " , strerror ( - ret ) ) ;
return EGL_NO_DEVICE_EXT ;
}
EGLDeviceEXT egl_device = NULL ;
for ( int i = 0 ; i < nb_devices ; i + + ) {
const char * egl_device_name = egl - > procs . eglQueryDeviceStringEXT (
devices [ i ] , EGL_DRM_DEVICE_FILE_EXT ) ;
if ( egl_device_name = = NULL ) {
continue ;
}
if ( device_has_name ( device , egl_device_name ) ) {
wlr_log ( WLR_DEBUG , " Using EGL device %s " , egl_device_name ) ;
egl_device = devices [ i ] ;
break ;
}
}
free ( devices ) ;
return egl_device ;
}
struct wlr_egl * wlr_egl_create_with_drm_fd ( int drm_fd ) {
struct wlr_egl * egl = egl_create ( ) ;
if ( egl = = NULL ) {
wlr_log ( WLR_ERROR , " Failed to create EGL context " ) ;
return NULL ;
}
if ( egl - > exts . EXT_platform_device ) {
/*
* Search for the EGL device matching the DRM fd using the
* EXT_device_enumeration extension .
*/
EGLDeviceEXT egl_device = get_egl_device_from_drm_fd ( egl , drm_fd ) ;
if ( egl_device ! = EGL_NO_DEVICE_EXT ) {
if ( egl_init ( egl , EGL_PLATFORM_DEVICE_EXT , egl_device ) ) {
wlr_log ( WLR_DEBUG , " Using EGL_PLATFORM_DEVICE_EXT " ) ;
return egl ;
}
goto error ;
}
/* Falls back on GBM in case the device was not found */
} else {
wlr_log ( WLR_DEBUG , " EXT_platform_device not supported " ) ;
}
if ( egl - > exts . KHR_platform_gbm ) {
egl - > gbm_device = gbm_create_device ( drm_fd ) ;
if ( ! egl - > gbm_device ) {
wlr_log ( WLR_ERROR , " Failed to create GBM device " ) ;
goto error ;
}
if ( egl_init ( egl , EGL_PLATFORM_GBM_KHR , egl - > gbm_device ) ) {
wlr_log ( WLR_DEBUG , " Using EGL_PLATFORM_GBM_KHR " ) ;
return egl ;
}
gbm_device_destroy ( egl - > gbm_device ) ;
} else {
wlr_log ( WLR_DEBUG , " KHR_platform_gbm not supported " ) ;
}
error :
error :
eglMakeCurrent ( EGL_NO_DISPLAY , EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT ) ;
wlr_log( WLR_ERROR , " Failed to initialize EGL context " ) ;
if ( egl - > display ) {
if ( egl - > display ) {
eglMakeCurrent ( egl - > display , EGL_NO_SURFACE , EGL_NO_SURFACE ,
EGL_NO_CONTEXT ) ;
eglTerminate ( egl - > display ) ;
eglTerminate ( egl - > display ) ;
}
}
free ( egl ) ;
eglReleaseThread ( ) ;
eglReleaseThread ( ) ;
return NULL ;
return NULL ;
}
}