From a4422cb6b4ccc6cbc867fddb65ad092a0ff57d12 Mon Sep 17 00:00:00 2001 From: lfdevs Date: Tue, 30 Jun 2026 18:34:00 +0800 Subject: [PATCH] egl/dri2: fix KGSL initialization for surfaceless and Wayland The KGSL fallback paths need to treat /dev/kgsl-3d0 as a non-DRM render device. The surfaceless platform previously opened the KGSL node and marked the driver as loaded without creating a DRI screen, which left dri_screen_render_gpu unset and made dri2_setup_screen() crash during eglInitialize(). Create the DRI screen before reporting the surfaceless KGSL driver as loaded, and clean up normally if screen creation fails. For the Wayland platform, avoid running the KGSL fd through DRM render node probing and loader_get_driver_for_fd(). When the KGSL fallback is used, set the display fd to the KGSL fd, select the kgsl driver directly, and skip DRM-specific render node checks. This lets both surfaceless EGL and Wayland EGL clients initialize with the freedreno KGSL driver instead of crashing or failing to create a DRI2 screen. --- src/egl/drivers/dri2/platform_surfaceless.c | 35 +++++++++---- src/egl/drivers/dri2/platform_wayland.c | 56 ++++++++++++--------- 2 files changed, 58 insertions(+), 33 deletions(-) diff --git a/src/egl/drivers/dri2/platform_surfaceless.c b/src/egl/drivers/dri2/platform_surfaceless.c index 539bf40625ad..2f25e84c492e 100644 --- a/src/egl/drivers/dri2/platform_surfaceless.c +++ b/src/egl/drivers/dri2/platform_surfaceless.c @@ -396,16 +396,31 @@ dri2_initialize_surfaceless(_EGLDisplay *disp) if (!driver_loaded && disp->Options.Kgsl) { dri2_dpy->fd_render_gpu = loader_open_device("/dev/kgsl-3d0"); - dri2_dpy->driver_name = strdup("kgsl"); - dri2_detect_swrast_kopper(disp); - driver_loaded = true; - if (driver_loaded) { - dri2_dpy->loader_extensions = image_loader_extensions; - } else { - free(dri2_dpy->driver_name); - dri2_dpy->driver_name = NULL; - close(dri2_dpy->fd_render_gpu); - dri2_dpy->fd_render_gpu = -1; + if (dri2_dpy->fd_render_gpu >= 0) { + dri2_dpy->fd_display_gpu = dri2_dpy->fd_render_gpu; + dri2_dpy->driver_name = strdup("kgsl"); + + if (dri2_dpy->driver_name) { + dri2_detect_swrast_kopper(disp); + dri2_dpy->loader_extensions = image_loader_extensions; + + /* KGSL is not enumerated as an EGLDevice, but it still needs a + * DRI screen before dri2_setup_screen() reads screen caps. + */ + if (dri2_create_screen(disp)) { + driver_loaded = true; + } else { + _eglLog(_EGL_WARNING, "DRI2: failed to create kgsl screen"); + } + } + + if (!driver_loaded) { + free(dri2_dpy->driver_name); + dri2_dpy->driver_name = NULL; + close(dri2_dpy->fd_render_gpu); + dri2_dpy->fd_display_gpu = -1; + dri2_dpy->fd_render_gpu = -1; + } } } diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c index 76bd241f4bb0..ade0b9744e1a 100644 --- a/src/egl/drivers/dri2/platform_wayland.c +++ b/src/egl/drivers/dri2/platform_wayland.c @@ -2664,6 +2664,7 @@ static EGLBoolean dri2_initialize_wayland_drm(_EGLDisplay *disp) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + bool using_kgsl = false; if (dri2_wl_formats_init(&dri2_dpy->formats) < 0) goto cleanup; @@ -2698,10 +2699,12 @@ dri2_initialize_wayland_drm(_EGLDisplay *disp) goto cleanup; if (!dri2_initialize_wayland_drm_extensions(dri2_dpy)) { - if (disp->Options.Kgsl) + if (disp->Options.Kgsl) { dri2_dpy->fd_render_gpu = loader_open_device("/dev/kgsl-3d0"); - else + using_kgsl = dri2_dpy->fd_render_gpu != -1; + } else { goto cleanup; + } } /* On the kgsl stack the compositor advertises neither wl_drm nor a v4 @@ -2714,33 +2717,40 @@ dri2_initialize_wayland_drm(_EGLDisplay *disp) dri2_dpy->fd_render_gpu = loader_open_device("/dev/kgsl-3d0"); if (dri2_dpy->fd_render_gpu == -1) goto cleanup; + using_kgsl = true; } - loader_get_user_preferred_fd(&dri2_dpy->fd_render_gpu, - &dri2_dpy->fd_display_gpu); + if (using_kgsl) { + dri2_dpy->fd_display_gpu = dri2_dpy->fd_render_gpu; + dri2_dpy->is_render_node = false; + dri2_dpy->driver_name = strdup("kgsl"); + } else { + loader_get_user_preferred_fd(&dri2_dpy->fd_render_gpu, + &dri2_dpy->fd_display_gpu); - if (dri2_dpy->fd_render_gpu != dri2_dpy->fd_display_gpu) { - free(dri2_dpy->device_name); - dri2_dpy->device_name = - loader_get_device_name_for_fd(dri2_dpy->fd_render_gpu); - if (!dri2_dpy->device_name) { - _eglError(EGL_BAD_ALLOC, "wayland-egl: failed to get device name " - "for requested GPU"); - goto cleanup; + if (dri2_dpy->fd_render_gpu != dri2_dpy->fd_display_gpu) { + free(dri2_dpy->device_name); + dri2_dpy->device_name = + loader_get_device_name_for_fd(dri2_dpy->fd_render_gpu); + if (!dri2_dpy->device_name) { + _eglError(EGL_BAD_ALLOC, "wayland-egl: failed to get device name " + "for requested GPU"); + goto cleanup; + } } - } - /* we have to do the check now, because loader_get_user_preferred_fd - * will return a render-node when the requested gpu is different - * to the server, but also if the client asks for the same gpu than - * the server by requesting its pci-id */ - dri2_dpy->is_render_node = - drmGetNodeTypeFromFd(dri2_dpy->fd_render_gpu) == DRM_NODE_RENDER; + /* we have to do the check now, because loader_get_user_preferred_fd + * will return a render-node when the requested gpu is different + * to the server, but also if the client asks for the same gpu than + * the server by requesting its pci-id */ + dri2_dpy->is_render_node = + drmGetNodeTypeFromFd(dri2_dpy->fd_render_gpu) == DRM_NODE_RENDER; - if (disp->Options.Zink) - dri2_dpy->driver_name = strdup("zink"); - else - dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd_render_gpu); + if (disp->Options.Zink) + dri2_dpy->driver_name = strdup("zink"); + else + dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd_render_gpu); + } if (dri2_dpy->driver_name == NULL) { _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name"); goto cleanup;