EGL fails to fall back to DRI2 when DRI3 is enabled but not available
Submitted by rez..@..SD.org
Assigned to mes..@..op.org
Link to original bug (#100627)
Description
DRI2 will be available but DRI3 may or may not depending which kernel and drivers are running. When Mesa is compiled with DRI3 support enabled and run on a kernel with only DRI2 support, applications using GLX work fine (modulo scary messages), but applications that use EGL fail. The cause appears to be insufficient checking during init in libEGL.
The GLX init code has separate dri3_create_screen and dri2_create_screen functions which are called from the respective init function. When the former bails with "libGL error: Version 7 or imageFromFds image extension not found\nlibGL error: failed to load driver: r600", libGL then tries the DRI2 path and succeeds. As an aside, it would be nice if the first message was only shown if LIBGL_DEBUG is set, and the second should indicate that DRI3 init has failed but DRI2 will be attempted instead of saying the driver failed to load (which is a source of spurious bug reports).
The EGL path on the other hand only has a dri2_create_screen function which is called from both dri2_initialize_x11_dri2 and dri2_initialize_x11_dri3. Thus the init path succeeds for DRI3 even though it cannot work, so the application ultimately fails because the first detectable error is after we are out of the init routines and it's too late to attempt a fallback to DRI2. Setting LIBGL_DRI3_DISABLE allows applications using EGL to function correctly, so there is a work-around until the initialization can be fixed to check availability of DRI3 support as is done in libGL.
Example of failure running mesa EGL demos:
% LIBGL_DEBUG=verbose EGL_LOG_LEVEL=debug MESA_DEBUG=1 eglgears_x11
libEGL debug: Native platform type: x11 (autodetected)
libEGL debug: added egl_dri2 to module array
libGL: Can't open configuration file /home/user/.drirc: No such file or directory.
libEGL debug: DRI2: dlopen(/usr/local/lib/dri/r600_dri.so)
libEGL debug: found extension `DRI_Core'
libEGL info: found extension DRI_Core version 1
libEGL debug: found extension `DRI_IMAGE_DRIVER'
libEGL info: found extension DRI_IMAGE_DRIVER version 1
libEGL debug: found extension `DRI_DRI2'
libEGL debug: found extension `DRI_ConfigOptions'
libEGL debug: found extension `DRI2_Fence'
libGL: Can't open configuration file /home/user/.drirc: No such file or directory.
libGL: Can't open configuration file /home/user/.drirc: No such file or directory.
libEGL debug: found extension `DRI_TexBuffer'
libEGL info: found extension DRI_TexBuffer version 2
libEGL debug: found extension `DRI2_Flush'
libEGL info: found extension DRI2_Flush version 4
libEGL debug: found extension `DRI_IMAGE'
libEGL info: found extension DRI_IMAGE version 12
libEGL debug: found extension `DRI_RENDERER_QUERY'
libEGL debug: found extension `DRI_CONFIG_QUERY'
libEGL debug: found extension `DRI2_Throttle'
libEGL debug: found extension `DRI2_Fence'
libEGL debug: found extension `DRI2_Interop'
libEGL debug: found extension `DRI_TexBuffer'
libEGL debug: found extension `DRI2_Flush'
libEGL debug: found extension `DRI_IMAGE'
libEGL debug: found extension `DRI_RENDERER_QUERY'
libEGL info: found extension DRI_RENDERER_QUERY version 1
libEGL debug: found extension `DRI_CONFIG_QUERY'
libEGL info: found extension DRI_CONFIG_QUERY version 1
libEGL debug: found extension `DRI2_Throttle'
libEGL debug: found extension `DRI2_Fence'
libEGL info: found extension DRI2_Fence version 2
libEGL debug: found extension `DRI2_Interop'
libEGL info: found extension DRI2_Interop version 1
libEGL debug: did not find optional extension DRI_Robustness version 1
libEGL info: Using DRI3
libEGL debug: the best driver is DRI2
EGL_VERSION = 1.4 (DRI2)
zsh: segmentation fault (core dumped)
As can be seen, libEGL runs right through the DRI3 init and then crashes when it tries to draw without having a surface. The backtrace differs according to the driver in use. This is just an example from my machine:
(lldb) bt
* thread #1
* frame #0: r600_dri.so`_debug_assert_fail(expr="surface", file="state_tracker/st_atom_framebuffer.c", line=61, function="update_framebuffer_size") at u_debug.c:321
frame #1: r600_dri.so`update_framebuffer_size(framebuffer=0x000000080a845028, surface=0x0000000000000000) at st_atom_framebuffer.c:61
frame #2: r600_dri.so`update_framebuffer_state(st=0x000000080a843000) at st_atom_framebuffer.c:181
frame #3: r600_dri.so`st_validate_state(st=0x000000080a843000, pipeline=ST_PIPELINE_RENDER) at st_atom.c:219
frame #4: r600_dri.so`st_Clear(ctx=0x000000080a85ff00, mask=18) at st_cb_clear.c:409
frame #5: r600_dri.so`_mesa_Clear(mask=16640) at clear.c:224
frame #6: 0x0000000000401fde eglgears_x11`___lldb_unnamed_symbol6$$eglgears_x11 + 14
frame #7: 0x0000000000403a37 eglgears_x11`___lldb_unnamed_symbol30$$eglgears_x11 + 295
frame #8: 0x0000000000401e97 eglgears_x11`___lldb_unnamed_symbol3$$eglgears_x11 + 423
frame #9: 0x0000000000401bef eglgears_x11`___lldb_unnamed_symbol1$$eglgears_x11 + 383
Version: 17.0