This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch fix-release-build
in repository efl.

View the commit online.

commit 7c04995e569acadd67f743febd1df8afbff4b8b3
Author: Cedric BAIL <[email protected]>
AuthorDate: Tue Aug 4 22:00:29 2026 -0600

    ecore_wl2: check the drm driver before using driver specific ioctls
    
    ecore_wl2_buffer_init() probes three allocators in turn - i915, exynos
    and vc4 - and each one starts poking at the fd before establishing that
    it is talking to the driver it was written for.
    
    DRM command numbers are per-driver. DRM_IOCTL_VC4_CREATE_BO is
    DRM_COMMAND_BASE + 0x03, which on panfrost is DRM_PANFROST_MMAP_BO;
    same size, same direction, so drm_ioctl() dispatches it happily and
    panfrost gets asked to mmap a bo whose handle is really a size. On a
    Mali T860 it comes back ENOENT and the probe fails for the wrong
    reason, but nothing about that is by design - it is one matching struct
    layout away from doing something.
    
    The i915 probe is less dangerous but noisier: drm_intel_bufmgr_gem_init()
    on a panfrost render node prints
    
        DRM_IOCTL_I915_GEM_APERTURE failed: Invalid argument
        Assuming 131072kB available aperture size.
        get chip id failed: -1 [38]
        i915 does not support EXECBUFER2
    
    to stderr on every single client startup before returning NULL.
    
    Ask the kernel what driver this is via DRM_IOCTL_VERSION and skip the
    probe unless it matches. Two other things fixed while here, both of
    which made these paths fail on systems where they should have worked:
    
      - dlopen() asked for libdrm_intel.so, libdrm_exynos.so and libdrm.so.
        Those are the -dev symlinks and are frequently absent on a runtime
        only install. Use the sonames.
    
      - the render node was hardcoded to /dev/dri/renderD128. Where display
        and render are separate devices - rockchip + panfrost, sun4i + lima
        - the one we want is not necessarily the first the kernel handed
        out. Scan the 128..191 minor range, with ECORE_WL2_RENDER_NODE to
        override.
    
    Also log when no dmabuf allocator could be set up at all. Falling back
    to wl_shm is a large silent performance cliff and it was invisible.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
 src/lib/ecore_wl2/ecore_wl2_buffer.c | 79 +++++++++++++++++++++++++++++++++---
 1 file changed, 74 insertions(+), 5 deletions(-)

diff --git a/src/lib/ecore_wl2/ecore_wl2_buffer.c b/src/lib/ecore_wl2/ecore_wl2_buffer.c
index 386eff294f..937b54b52e 100644
--- a/src/lib/ecore_wl2/ecore_wl2_buffer.c
+++ b/src/lib/ecore_wl2/ecore_wl2_buffer.c
@@ -98,6 +98,32 @@ static const struct wl_buffer_listener buffer_listener =
    buffer_release
 };
 
+/* Read the driver name out of the kernel so we never aim a driver-specific
+ * ioctl at a driver that never implemented it.  DRM command numbers are
+ * per-driver: DRM_IOCTL_VC4_CREATE_BO is DRM_COMMAND_BASE + 0x03, which on
+ * panfrost is DRM_PANFROST_MMAP_BO - same size, same direction, so the
+ * kernel happily dispatches it and we get whatever that driver does with a
+ * garbage handle. */
+static Eina_Bool
+_drm_driver_is(int fd, const char *want)
+{
+   drm_version_t v;
+   char name[64];
+   Eina_Bool ret;
+
+   memset(&v, 0, sizeof(v));
+   v.name = name;
+   v.name_len = sizeof(name) - 1;
+
+   if (ioctl(fd, DRM_IOCTL_VERSION, &v)) return EINA_FALSE;
+   if (v.name_len >= (__typeof__(v.name_len))sizeof(name)) return EINA_FALSE;
+
+   name[v.name_len] = '\0';
+   ret = !strcmp(name, want);
+
+   return ret;
+}
+
 static struct wl_buffer *
 _evas_dmabuf_wl_buffer_from_dmabuf(Ecore_Wl2_Display *ewd, Ecore_Wl2_Buffer *db)
 {
@@ -223,7 +249,9 @@ _intel_buffer_manager_setup(int fd)
    Eina_Bool fail = EINA_FALSE;
    void *drm_intel_lib;
 
-   drm_intel_lib = dlopen("libdrm_intel.so", RTLD_LAZY | RTLD_GLOBAL);
+   if (!_drm_driver_is(fd, "i915")) return EINA_FALSE;
+
+   drm_intel_lib = dlopen("libdrm_intel.so.1", RTLD_LAZY | RTLD_GLOBAL);
    if (!drm_intel_lib) return EINA_FALSE;
 
    SYM(drm_intel_lib, drm_intel_bufmgr_gem_init);
@@ -326,7 +354,9 @@ _exynos_buffer_manager_setup(int fd)
    void *drm_exynos_lib;
    struct exynos_bo *bo;
 
-   drm_exynos_lib = dlopen("libdrm_exynos.so", RTLD_LAZY | RTLD_GLOBAL);
+   if (!_drm_driver_is(fd, "exynos")) return EINA_FALSE;
+
+   drm_exynos_lib = dlopen("libdrm_exynos.so.1", RTLD_LAZY | RTLD_GLOBAL);
    if (!drm_exynos_lib) return EINA_FALSE;
 
    SYM(drm_exynos_lib, exynos_device_create);
@@ -565,6 +595,8 @@ _vc4_buffer_manager_setup(int fd)
    Eina_Bool fail = EINA_FALSE;
    void *drm_lib;
 
+   if (!_drm_driver_is(fd, "vc4")) return EINA_FALSE;
+
    memset(&bo, 0, sizeof(bo));
    bo.size = 32;
    if (ioctl(fd, DRM_IOCTL_VC4_CREATE_BO, &bo)) return EINA_FALSE;
@@ -573,7 +605,7 @@ _vc4_buffer_manager_setup(int fd)
    cl.handle = bo.handle;
    ioctl(fd, DRM_IOCTL_GEM_CLOSE, &cl);
 
-   drm_lib = dlopen("libdrm.so", RTLD_LAZY | RTLD_GLOBAL);
+   drm_lib = dlopen("libdrm.so.2", RTLD_LAZY | RTLD_GLOBAL);
    if (!drm_lib) return EINA_FALSE;
 
    SYM(drm_lib, drmPrimeHandleToFD);
@@ -595,6 +627,38 @@ err:
    return EINA_FALSE;
 }
 
+/* renderD128 is only the first render node the kernel hands out; on a box
+ * with a discrete card, or where the display and render devices are
+ * separate (rockchip + panfrost, sun4i + lima, ...), the one we want may
+ * well be a higher number. */
+static int
+_render_node_open(void)
+{
+   const char *env;
+   char path[64];
+   int i, fd;
+
+   env = getenv("ECORE_WL2_RENDER_NODE");
+   if (env)
+     {
+        fd = open(env, O_RDWR | O_CLOEXEC);
+        if (fd >= 0) return fd;
+        ERR("ECORE_WL2_RENDER_NODE is set to %s, which could not be opened",
+            env);
+        return -1;
+     }
+
+   /* 128..191 is the render node minor range */
+   for (i = 128; i < 192; i++)
+     {
+        snprintf(path, sizeof(path), "/dev/dri/renderD%d", i);
+        fd = open(path, O_RDWR | O_CLOEXEC);
+        if (fd >= 0) return fd;
+     }
+
+   return -1;
+}
+
 EAPI Eina_Bool
 ecore_wl2_buffer_init(Ecore_Wl2_Display *ewd, Ecore_Wl2_Buffer_Type types)
 {
@@ -614,16 +678,21 @@ ecore_wl2_buffer_init(Ecore_Wl2_Display *ewd, Ecore_Wl2_Buffer_Type types)
 
    if (!getenv("EVAS_WAYLAND_SHM_DISABLE_DMABUF") && dmabuf)
      {
-        fd = open("/dev/dri/renderD128", O_RDWR | O_CLOEXEC);
+        fd = _render_node_open();
         if (fd < 0)
           {
-             ERR("Tried to use dmabufs, but can't find /dev/dri/renderD128 . Falling back to regular SHM");
+             ERR("Tried to use dmabufs, but found no usable render node in "
+                 "/dev/dri. Falling back to regular SHM");
              goto fallback_shm;
           }
 
         success = _intel_buffer_manager_setup(fd);
         if (!success) success = _exynos_buffer_manager_setup(fd);
         if (!success) success = _vc4_buffer_manager_setup(fd);
+
+        if (!success)
+          WRN("No dmabuf allocator available for this device, falling back "
+              "to regular SHM");
      }
 fallback_shm:
    if (!success) success = shm && _wl_shm_buffer_manager_setup(0);

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to