From 5f5eec1c49d0834251dfbc36e6c84af3f4da3fef Mon Sep 17 00:00:00 2001 From: Admin Pupkin Date: Tue, 9 Jun 2026 23:24:01 +0300 Subject: [PATCH] libdrm: migrate to upstream git + external patches (Rule 2 policy fix, v6.0 2026) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per local/AGENTS.md Rule 2 (NO OVERLAY-STYLE PATCHES — AMENDED 2026), big external projects must NOT have source forks in local/sources/. libdrm's Red Bear edits now live as external patches in local/patches/libdrm/, matching the established pipewire and wireplumber migration pattern (commits 8ff9da2ff, 722f0c452). The 5 patches were recovered from git history (commit 89d1306c8^ — the migration that deleted them) and renamed to the modern Rule 2 NN-prefix naming for lexical-order application: 01-drm-ioctl-bridge.patch (P1 from old series, 278 lines) 02-ioctl-response-sizes.patch (P1 from old series, 30 lines) 03-drm-get-pci-info.patch (P2 from old series, 153 lines) 04-drm-get-version-driver-name.patch (P3 from old series, 34 lines) 05-drmGetDeviceFromDevId-redox.patch (P4 from old series, 68 lines) These patches add the Redox-side ioctl/ioctl-com and scheme: dispatch path needed by redox-drm and Mesa radeonsi/iris. The recipe now points at upstream libdrm 2.4.125 (https://gitlab.freedesktop.org/mesa/libdrm, tag libdrm-2.4.125) and applies the patches via a [source].script hook (the cookbook's "Optional script to run to prepare the source" field) with a REDBEAR_PATCHES_DIR computed from COOKBOOK_RECIPE. Fixes the broken state where the recipe referenced the now-deleted local/sources/libdrm/ fork. --- .../patches/libdrm/01-drm-ioctl-bridge.patch | 278 ++++++++++++++++++ .../libdrm/02-ioctl-response-sizes.patch | 30 ++ .../patches/libdrm/03-drm-get-pci-info.patch | 153 ++++++++++ .../04-drm-get-version-driver-name.patch | 34 +++ .../05-drmGetDeviceFromDevId-redox.patch | 68 +++++ local/recipes/libs/libdrm/recipe.toml | 88 ++++-- 6 files changed, 632 insertions(+), 19 deletions(-) create mode 100644 local/patches/libdrm/01-drm-ioctl-bridge.patch create mode 100644 local/patches/libdrm/02-ioctl-response-sizes.patch create mode 100644 local/patches/libdrm/03-drm-get-pci-info.patch create mode 100644 local/patches/libdrm/04-drm-get-version-driver-name.patch create mode 100644 local/patches/libdrm/05-drmGetDeviceFromDevId-redox.patch diff --git a/local/patches/libdrm/01-drm-ioctl-bridge.patch b/local/patches/libdrm/01-drm-ioctl-bridge.patch new file mode 100644 index 0000000000..e583b98b74 --- /dev/null +++ b/local/patches/libdrm/01-drm-ioctl-bridge.patch @@ -0,0 +1,278 @@ +--- a/xf86drm.c ++++ b/xf86drm.c +@@ -91,6 +91,7 @@ + #include "xf86drm_redox.h" + #include "libdrm_macros.h" + #include "drm_fourcc.h" ++#include "virtgpu_drm.h" + + #include "util_math.h" + +@@ -813,6 +814,50 @@ + return REDOX_DRM_IOCTL_MODE_DESTROY_DUMB; + case 0xAF: + return REDOX_DRM_IOCTL_MODE_RMFB; ++ /* VirtGPU ioctls (NR 0x41-0x4B) */ ++ case 0x41: ++ return REDOX_DRM_IOCTL_VIRTGPU_MAP; ++ case 0x42: ++ return REDOX_DRM_IOCTL_VIRTGPU_EXECBUFFER; ++ case 0x43: ++ return REDOX_DRM_IOCTL_VIRTGPU_GETPARAM; ++ case 0x44: ++ return REDOX_DRM_IOCTL_VIRTGPU_RESOURCE_CREATE; ++ case 0x45: ++ return REDOX_DRM_IOCTL_VIRTGPU_RESOURCE_INFO; ++ case 0x46: ++ return REDOX_DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST; ++ case 0x47: ++ return REDOX_DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST; ++ case 0x48: ++ return REDOX_DRM_IOCTL_VIRTGPU_WAIT; ++ case 0x49: ++ return REDOX_DRM_IOCTL_VIRTGPU_GET_CAPS; ++ case 0x4A: ++ return REDOX_DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB; ++ case 0x4B: ++ return REDOX_DRM_IOCTL_VIRTGPU_CONTEXT_INIT; ++ /* Additional standard DRM ioctls */ ++ case 0x00: ++ return REDOX_DRM_IOCTL_VERSION; ++ case 0xA0: ++ return REDOX_DRM_IOCTL_MODE_GETRESOURCES; ++ case 0xA1: ++ return REDOX_DRM_IOCTL_MODE_GETCRTC; ++ case 0xA2: ++ return REDOX_DRM_IOCTL_MODE_SETCRTC; ++ case 0xA3: ++ return REDOX_DRM_IOCTL_MODE_GETCONNECTOR; ++ case 0xA4: ++ return REDOX_DRM_IOCTL_MODE_PAGE_FLIP; ++ case 0xA8: ++ return REDOX_DRM_IOCTL_MODE_CREATE_DUMB; ++ case 0xAC: ++ return REDOX_DRM_IOCTL_MODE_ADDFB; ++ case 0x2B: ++ return REDOX_DRM_IOCTL_PRIME_HANDLE_TO_FD; ++ case 0x2C: ++ return REDOX_DRM_IOCTL_PRIME_FD_TO_HANDLE; + default: + return 0; + } +@@ -908,7 +953,19 @@ + static size_t redox_drm_expected_response_size(unsigned long linux_nr, size_t arg_size) + { + switch (linux_nr) { ++ case 0x00: /* VERSION */ + case 0x0C: ++ case 0x2B: /* PRIME_HANDLE_TO_FD */ ++ case 0x2C: /* PRIME_FD_TO_HANDLE */ ++ case 0x41: /* VIRTGPU_MAP */ ++ case 0x43: /* VIRTGPU_GETPARAM */ ++ case 0x44: /* VIRTGPU_RESOURCE_CREATE */ ++ case 0x45: /* VIRTGPU_RESOURCE_INFO */ ++ case 0xA0: /* MODE_GETRESOURCES */ ++ case 0xA1: /* MODE_GETCRTC */ ++ case 0xA3: /* MODE_GETCONNECTOR */ ++ case 0xA8: /* MODE_CREATE_DUMB */ ++ case 0xAC: /* MODE_ADDFB */ + case 0xA6: + case 0xB3: + return arg_size; +@@ -927,6 +984,41 @@ + if (request_code == 0) { + errno = ENOTTY; + return -1; ++ } ++ ++ if (linux_nr == 0x42) { /* VIRTGPU_EXECBUFFER */ ++ struct drm_virtgpu_execbuffer *eb = arg; ++ size_t total = arg_size + eb->size; ++ uint8_t *buf = drmMalloc((int)total); ++ int ret; ++ ++ if (!buf) ++ return -1; ++ ++ memcpy(buf, arg, arg_size); ++ if (eb->size > 0 && eb->command) ++ memcpy(buf + arg_size, (void *)(uintptr_t)eb->command, eb->size); ++ ++ ret = redox_drm_exchange(fd, request_code, buf, total, NULL, 0, NULL); ++ drmFree(buf); ++ return ret; ++ } ++ ++ if (linux_nr == 0x49) { /* VIRTGPU_GET_CAPS */ ++ struct drm_virtgpu_get_caps *gc = arg; ++ void *resp; ++ size_t resp_size; ++ int ret; ++ ++ ret = redox_drm_exchange_alloc(fd, request_code, arg, arg_size, &resp, &resp_size); ++ if (ret == 0 && resp && resp_size > 0) { ++ size_t copy = resp_size < gc->size ? resp_size : gc->size; ++ ++ memcpy((void *)(uintptr_t)gc->addr, resp, copy); ++ drmFree(resp); ++ } ++ ++ return ret; + } + + if (redox_drm_exchange(fd, request_code, +--- a/xf86drm_redox.h ++++ b/xf86drm_redox.h +@@ -28,6 +28,17 @@ + #define REDOX_DRM_IOCTL_GEM_CLOSE (REDOX_DRM_IOCTL_BASE + 27) + #define REDOX_DRM_IOCTL_PRIME_HANDLE_TO_FD (REDOX_DRM_IOCTL_BASE + 29) + #define REDOX_DRM_IOCTL_PRIME_FD_TO_HANDLE (REDOX_DRM_IOCTL_BASE + 30) ++#define REDOX_DRM_IOCTL_VIRTGPU_MAP (REDOX_DRM_IOCTL_BASE + 31) ++#define REDOX_DRM_IOCTL_VIRTGPU_EXECBUFFER (REDOX_DRM_IOCTL_BASE + 32) ++#define REDOX_DRM_IOCTL_VIRTGPU_GETPARAM (REDOX_DRM_IOCTL_BASE + 33) ++#define REDOX_DRM_IOCTL_VIRTGPU_RESOURCE_CREATE (REDOX_DRM_IOCTL_BASE + 34) ++#define REDOX_DRM_IOCTL_VIRTGPU_RESOURCE_INFO (REDOX_DRM_IOCTL_BASE + 35) ++#define REDOX_DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST (REDOX_DRM_IOCTL_BASE + 36) ++#define REDOX_DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST (REDOX_DRM_IOCTL_BASE + 37) ++#define REDOX_DRM_IOCTL_VIRTGPU_WAIT (REDOX_DRM_IOCTL_BASE + 38) ++#define REDOX_DRM_IOCTL_VIRTGPU_GET_CAPS (REDOX_DRM_IOCTL_BASE + 39) ++#define REDOX_DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB (REDOX_DRM_IOCTL_BASE + 40) ++#define REDOX_DRM_IOCTL_VIRTGPU_CONTEXT_INIT (REDOX_DRM_IOCTL_BASE + 41) + + struct redox_drm_resources_wire { + uint32_t connector_count; +--- /dev/null ++++ b/virtgpu_drm.h +@@ -0,0 +1,132 @@ ++#ifndef _VIRTGPU_DRM_H_ ++#define _VIRTGPU_DRM_H_ ++ ++#include ++ ++#define DRM_VIRTGPU_MAP 0x41 ++#define DRM_VIRTGPU_EXECBUFFER 0x42 ++#define DRM_VIRTGPU_GETPARAM 0x43 ++#define DRM_VIRTGPU_RESOURCE_CREATE 0x44 ++#define DRM_VIRTGPU_RESOURCE_INFO 0x45 ++#define DRM_VIRTGPU_TRANSFER_FROM_HOST 0x46 ++#define DRM_VIRTGPU_TRANSFER_TO_HOST 0x47 ++#define DRM_VIRTGPU_WAIT 0x48 ++#define DRM_VIRTGPU_GET_CAPS 0x49 ++#define DRM_VIRTGPU_RESOURCE_CREATE_BLOB 0x4A ++#define DRM_VIRTGPU_CONTEXT_INIT 0x4B ++ ++#define drm_virtgpu_resource_create drm_virtgpu_resource_create_3d ++#define drm_virtgpu_3d_transfer_to_host drm_virtgpu_transfer_to_host ++#define drm_virtgpu_3d_transfer_from_host drm_virtgpu_transfer_from_host ++#define drm_virtgpu_3d_wait drm_virtgpu_wait_3d ++#define ctx_set_params_ptr ctx_set_params ++#define resource_id res_handle ++ ++struct drm_virtgpu_3d_box { ++ uint32_t x; ++ uint32_t y; ++ uint32_t z; ++ uint32_t w; ++ uint32_t h; ++ uint32_t d; ++}; ++ ++struct drm_virtgpu_execbuffer { ++ uint32_t flags; ++ uint32_t size; ++ uint64_t command; ++ uint64_t bo_handles; ++ uint32_t num_bo_handles; ++ int32_t fence_fd; ++ uint32_t ring_idx; ++ uint32_t syncobj_stride; ++ uint32_t num_in_syncobjs; ++ uint32_t num_out_syncobjs; ++ uint64_t in_syncobjs; ++ uint64_t out_syncobjs; ++}; ++ ++struct drm_virtgpu_getparam { ++ uint64_t param; ++ uint64_t value; ++}; ++ ++struct drm_virtgpu_resource_create_3d { ++ uint32_t target; ++ uint32_t format; ++ uint32_t bind; ++ uint32_t width; ++ uint32_t height; ++ uint32_t depth; ++ uint32_t array_size; ++ uint32_t last_level; ++ uint32_t nr_samples; ++ uint32_t flags; ++ uint32_t bo_handle; ++ uint32_t res_handle; ++ uint32_t size; ++ uint32_t stride; ++}; ++ ++struct drm_virtgpu_resource_info { ++ uint32_t bo_handle; ++ uint32_t res_handle; ++ uint32_t size; ++ uint32_t blob_mem; ++}; ++ ++struct drm_virtgpu_transfer_to_host { ++ uint32_t bo_handle; ++ struct drm_virtgpu_3d_box box; ++ uint32_t level; ++ uint32_t offset; ++ uint32_t stride; ++ uint32_t layer_stride; ++}; ++ ++struct drm_virtgpu_transfer_from_host { ++ uint32_t bo_handle; ++ struct drm_virtgpu_3d_box box; ++ uint32_t level; ++ uint32_t offset; ++ uint32_t stride; ++ uint32_t layer_stride; ++}; ++ ++struct drm_virtgpu_wait_3d { ++ uint32_t handle; ++ uint32_t flags; ++}; ++ ++struct drm_virtgpu_get_caps { ++ uint32_t cap_set_id; ++ uint32_t cap_set_ver; ++ uint64_t addr; ++ uint32_t size; ++ uint32_t pad; ++}; ++ ++struct drm_virtgpu_resource_create_blob { ++ uint32_t blob_mem; ++ uint32_t blob_flags; ++ uint32_t bo_handle; ++ uint32_t res_handle; ++ uint64_t size; ++ uint32_t pad; ++ uint32_t cmd_size; ++ uint64_t cmd; ++ uint64_t blob_id; ++}; ++ ++struct drm_virtgpu_context_set_param { ++ uint64_t param; ++ uint64_t value; ++}; ++ ++struct drm_virtgpu_context_init { ++ uint32_t num_params; ++ uint32_t pad; ++ uint64_t ctx_set_params; ++}; ++ ++#endif diff --git a/local/patches/libdrm/02-ioctl-response-sizes.patch b/local/patches/libdrm/02-ioctl-response-sizes.patch new file mode 100644 index 0000000000..7572134154 --- /dev/null +++ b/local/patches/libdrm/02-ioctl-response-sizes.patch @@ -0,0 +1,30 @@ +diff --git a/local/recipes/libs/libdrm/source/xf86drm.c b/local/recipes/libs/libdrm/source/xf86drm.c +index 0379aafd7e..2d3fcd6d3b 100644 +--- a/local/recipes/libs/libdrm/source/xf86drm.c ++++ b/local/recipes/libs/libdrm/source/xf86drm.c +@@ -1653,6 +1653,10 @@ static size_t redox_drm_expected_response_size(unsigned long linux_nr, size_t ar + case 0xA9: + case 0xAA: + case 0xAC: ++ case 0xB2: ++ case 0xB4: ++ case 0xBD: ++ case 0xBE: + case 0xB8: + case 0xB9: + case 0xB3: +@@ -4482,7 +4486,13 @@ drm_public int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, + return -errno; + } + +- *prime_fd = response.fd; ++ char path[64]; ++ snprintf(path, sizeof(path), "card0/dmabuf/%d", response.fd); ++ int real_fd = openat(fd, path, O_RDWR | O_CLOEXEC); ++ if (real_fd < 0) { ++ return -errno; ++ } ++ *prime_fd = real_fd; + return 0; + #else + struct drm_prime_handle args; diff --git a/local/patches/libdrm/03-drm-get-pci-info.patch b/local/patches/libdrm/03-drm-get-pci-info.patch new file mode 100644 index 0000000000..87945d07b1 --- /dev/null +++ b/local/patches/libdrm/03-drm-get-pci-info.patch @@ -0,0 +1,153 @@ +--- a/xf86drm.c ++++ b/xf86drm.c +@@ -115,7 +115,7 @@ + #define DRM_MAJOR 226 /* Linux */ + #endif + +-#if defined(__OpenBSD__) || defined(__DragonFly__) ++#if defined(__OpenBSD__) || defined(__DragonFly__) || defined(__redox__) + struct drm_pciinfo { + uint16_t domain; + uint8_t bus; +@@ -858,6 +858,9 @@ + return REDOX_DRM_IOCTL_PRIME_HANDLE_TO_FD; + case 0x2C: + return REDOX_DRM_IOCTL_PRIME_FD_TO_HANDLE; ++ /* DRM_IOCTL_GET_PCIINFO — PCI device information for driver discovery */ ++ case 0x15: ++ return REDOX_DRM_IOCTL_GET_PCI_INFO; + default: + return 0; + } +@@ -4201,6 +4204,21 @@ + return 0; + #elif defined(__FreeBSD__) + return get_sysctl_pci_bus_info(maj, min, info); ++#elif defined(__redox__) ++ int rfd = open("/scheme/drm/card0", O_RDONLY); ++ if (rfd < 0) ++ return -errno; ++ uint8_t buf[22]; ++ size_t rsize = 0; ++ int ret = redox_drm_exchange(rfd, REDOX_DRM_IOCTL_GET_PCI_INFO, NULL, 0, buf, sizeof(buf), &rsize); ++ close(rfd); ++ if (ret != 0 || rsize < 17) ++ return -EIO; ++ info->domain = buf[10] | (buf[11] << 8) | (buf[12] << 16) | (buf[13] << 24); ++ info->bus = buf[14]; ++ info->dev = buf[15]; ++ info->func = buf[16]; ++ return 0; + #else + #warning "Missing implementation of drmParsePciBusInfo" + return -EINVAL; +@@ -4410,6 +4428,23 @@ + device->revision_id = results[0].pc_revid; + + return 0; ++#elif defined(__redox__) ++ int rfd2 = open("/scheme/drm/card0", O_RDONLY); ++ if (rfd2 < 0) ++ return -errno; ++ uint8_t dbuf[22]; ++ size_t drsize = 0; ++ int dret = redox_drm_exchange(rfd2, REDOX_DRM_IOCTL_GET_PCI_INFO, NULL, 0, dbuf, sizeof(dbuf), &drsize); ++ close(rfd2); ++ if (dret != 0 || drsize < 9) ++ return -EIO; ++ device->vendor_id = dbuf[0] | (dbuf[1] << 8); ++ device->device_id = dbuf[2] | (dbuf[3] << 8); ++ device->subvendor_id = dbuf[4] | (dbuf[5] << 8); ++ device->subdevice_id = dbuf[6] | (dbuf[7] << 8); ++ if (drsize >= 9) ++ device->revision_id = dbuf[8]; ++ return 0; + #else + #warning "Missing implementation of drmParsePciDeviceInfo" + return -EINVAL; +@@ -5162,6 +5197,66 @@ + */ + drm_public int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device) + { ++#if defined(__redox__) ++ uint8_t pbuf[22]; ++ size_t prsize = 0; ++ int pret; ++ uint16_t pvendor_id, pdevice_id, psubvendor_id, psubdevice_id, pdomain; ++ uint8_t prevision_id, pbus, pdev, pfunc; ++ const char *pnode; ++ int max_node_length, i; ++ size_t extra, psize; ++ drmDevicePtr devp; ++ char *pptr; ++ ++ pret = redox_drm_exchange(fd, REDOX_DRM_IOCTL_GET_PCI_INFO, NULL, 0, ++ pbuf, sizeof(pbuf), &prsize); ++ if (pret != 0 || prsize < 17) ++ return -EIO; ++ ++ pvendor_id = pbuf[0] | (pbuf[1] << 8); ++ pdevice_id = pbuf[2] | (pbuf[3] << 8); ++ psubvendor_id = pbuf[4] | (pbuf[5] << 8); ++ psubdevice_id = pbuf[6] | (pbuf[7] << 8); ++ prevision_id = pbuf[8]; ++ pdomain = pbuf[10] | (pbuf[11] << 8) | (pbuf[12] << 16) | (pbuf[13] << 24); ++ pbus = pbuf[14]; ++ pdev = pbuf[15]; ++ pfunc = pbuf[16]; ++ ++ pnode = "/scheme/drm/card0"; ++ max_node_length = 64; ++ extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length); ++ psize = sizeof(drmDevice) + extra + sizeof(drmPciBusInfo) + sizeof(drmPciDeviceInfo); ++ devp = calloc(1, psize); ++ if (!devp) ++ return -ENOMEM; ++ ++ devp->bustype = DRM_BUS_PCI; ++ devp->available_nodes = 1 << DRM_NODE_PRIMARY; ++ pptr = (char *)devp + sizeof(drmDevice); ++ devp->nodes = (char **)pptr; ++ pptr += DRM_NODE_MAX * sizeof(void *); ++ for (i = 0; i < DRM_NODE_MAX; i++) { devp->nodes[i] = pptr; pptr += max_node_length; } ++ snprintf(devp->nodes[DRM_NODE_PRIMARY], max_node_length, "%s", pnode); ++ ++ devp->businfo.pci = (drmPciBusInfoPtr)pptr; ++ pptr += sizeof(drmPciBusInfo); ++ devp->businfo.pci->domain = pdomain; ++ devp->businfo.pci->bus = pbus; ++ devp->businfo.pci->dev = pdev; ++ devp->businfo.pci->func = pfunc; ++ ++ devp->deviceinfo.pci = (drmPciDeviceInfoPtr)pptr; ++ devp->deviceinfo.pci->vendor_id = pvendor_id; ++ devp->deviceinfo.pci->device_id = pdevice_id; ++ devp->deviceinfo.pci->subvendor_id = psubvendor_id; ++ devp->deviceinfo.pci->subdevice_id = psubdevice_id; ++ devp->deviceinfo.pci->revision_id = prevision_id; ++ ++ *device = devp; ++ return 0; ++#else + struct stat sbuf; + + if (fd == -1) +@@ -5174,6 +5269,7 @@ + return -EINVAL; + + return drmGetDeviceFromDevId(sbuf.st_rdev, flags, device); ++#endif + } + + /** +--- a/xf86drm_redox.h ++++ b/xf86drm_redox.h +@@ -40,6 +40,8 @@ + #define REDOX_DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB (REDOX_DRM_IOCTL_BASE + 40) + #define REDOX_DRM_IOCTL_VIRTGPU_CONTEXT_INIT (REDOX_DRM_IOCTL_BASE + 41) + ++#define REDOX_DRM_IOCTL_GET_PCI_INFO (REDOX_DRM_IOCTL_BASE + 0x60) ++ + struct redox_drm_resources_wire { + uint32_t connector_count; + uint32_t crtc_count; diff --git a/local/patches/libdrm/04-drm-get-version-driver-name.patch b/local/patches/libdrm/04-drm-get-version-driver-name.patch new file mode 100644 index 0000000000..83439c6e38 --- /dev/null +++ b/local/patches/libdrm/04-drm-get-version-driver-name.patch @@ -0,0 +1,34 @@ +diff --git a/xf86drm.c b/xf86drm.c +index 1b206ccd4..c3904caa3 100644 +--- a/xf86drm.c ++++ b/xf86drm.c +@@ -1774,0 +1775,23 @@ drm_public drmVersionPtr drmGetVersion(int fd) ++ ++ /* The scheme returns a NUL-terminated driver name in version.name. ++ * KWin drm_gpu.cpp dereferences version->name unconditionally ++ * (strstr checks for "i915", "amdgpu", "virtio" etc.) so it must ++ * never be NULL. ++ */ ++ version.name[sizeof(version.name) - 1] = '\0'; ++ if (version.name[0] != '\0') { ++ size_t len = strlen(version.name); ++ retval->name = drmMalloc(len + 1); ++ if (retval->name) { ++ memcpy(retval->name, version.name, len + 1); ++ retval->name_len = len; ++ } ++ } else { ++ const char fallback[] = "redox-drm"; ++ retval->name = drmMalloc(sizeof(fallback)); ++ if (retval->name) { ++ memcpy(retval->name, fallback, sizeof(fallback)); ++ retval->name_len = sizeof(fallback) - 1; ++ } ++ } ++ +diff --git a/xf86drm_redox.h b/xf86drm_redox.h +index c1abe8256..7f9d252fa 100644 +--- a/xf86drm_redox.h ++++ b/xf86drm_redox.h +@@ -140,0 +141 @@ struct redox_drm_version_wire { ++ char name[64]; diff --git a/local/patches/libdrm/05-drmGetDeviceFromDevId-redox.patch b/local/patches/libdrm/05-drmGetDeviceFromDevId-redox.patch new file mode 100644 index 0000000000..3a6c8cc80f --- /dev/null +++ b/local/patches/libdrm/05-drmGetDeviceFromDevId-redox.patch @@ -0,0 +1,68 @@ +diff --git a/xf86drm.c b/xf86drm.c +index c3904caa3..306026e8b 100644 +--- a/xf86drm.c ++++ b/xf86drm.c +@@ -4096 +4096 @@ static int drmParseSubsystemType(int maj, int min) +-#elif defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD__) ++#elif defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__redox__) +@@ -5122,0 +5123,60 @@ drm_public int drmGetDeviceFromDevId(dev_t find_rdev, uint32_t flags, drmDeviceP ++ return 0; ++#elif defined(__redox__) ++ /* On Redox there is no /dev/dri/ directory to enumerate. ++ * Instead, open /scheme/drm/card0 and query PCI info to ++ * construct a single drmDevice that serves as both primary ++ * and render node. */ ++ drmDevicePtr devp; ++ char *pptr; ++ int max_node_length = 64, i; ++ size_t extra, psize; ++ uint8_t pbuf[22]; ++ size_t prsize = 0; ++ int pret, fd; ++ ++ if (device == NULL) ++ return -EINVAL; ++ if (drm_device_validate_flags(flags)) ++ return -EINVAL; ++ ++ fd = open("/scheme/drm/card0", O_RDWR | O_CLOEXEC); ++ if (fd < 0) ++ return -errno; ++ ++ pret = redox_drm_exchange(fd, REDOX_DRM_IOCTL_GET_PCI_INFO, NULL, 0, ++ pbuf, sizeof(pbuf), &prsize); ++ close(fd); ++ if (pret != 0 || prsize < 17) ++ return -EIO; ++ ++ extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length); ++ psize = sizeof(drmDevice) + extra + sizeof(drmPciBusInfo) + sizeof(drmPciDeviceInfo); ++ devp = calloc(1, psize); ++ if (!devp) ++ return -ENOMEM; ++ ++ devp->bustype = DRM_BUS_PCI; ++ /* Advertise both PRIMARY and RENDER — same path on Redox */ ++ devp->available_nodes = (1 << DRM_NODE_PRIMARY) | (1 << DRM_NODE_RENDER); ++ pptr = (char *)devp + sizeof(drmDevice); ++ devp->nodes = (char **)pptr; ++ pptr += DRM_NODE_MAX * sizeof(void *); ++ for (i = 0; i < DRM_NODE_MAX; i++) { devp->nodes[i] = pptr; pptr += max_node_length; } ++ snprintf(devp->nodes[DRM_NODE_PRIMARY], max_node_length, "/scheme/drm/card0"); ++ snprintf(devp->nodes[DRM_NODE_RENDER], max_node_length, "/scheme/drm/card0"); ++ ++ devp->businfo.pci = (drmPciBusInfoPtr)pptr; ++ pptr += sizeof(drmPciBusInfo); ++ devp->businfo.pci->domain = pbuf[10] | (pbuf[11] << 8) | (pbuf[12] << 16) | (pbuf[13] << 24); ++ devp->businfo.pci->bus = pbuf[14]; ++ devp->businfo.pci->dev = pbuf[15]; ++ devp->businfo.pci->func = pbuf[16]; ++ ++ devp->deviceinfo.pci = (drmPciDeviceInfoPtr)pptr; ++ devp->deviceinfo.pci->vendor_id = pbuf[0] | (pbuf[1] << 8); ++ devp->deviceinfo.pci->device_id = pbuf[2] | (pbuf[3] << 8); ++ devp->deviceinfo.pci->subvendor_id = pbuf[4] | (pbuf[5] << 8); ++ devp->deviceinfo.pci->subdevice_id = pbuf[6] | (pbuf[7] << 8); ++ devp->deviceinfo.pci->revision_id = pbuf[8]; ++ ++ *device = devp; diff --git a/local/recipes/libs/libdrm/recipe.toml b/local/recipes/libs/libdrm/recipe.toml index b050119bcb..909f0b993b 100644 --- a/local/recipes/libs/libdrm/recipe.toml +++ b/local/recipes/libs/libdrm/recipe.toml @@ -1,31 +1,81 @@ # libdrm — DRM/KMS user-space library for Red Bear OS. # -# This recipe builds the Red Bear libdrm fork maintained at -# local/sources/libdrm/. The fork is based on upstream libdrm 2.4.125 -# (https://gitlab.freedesktop.org/mesa/libdrm) with the redox.patch -# series applied in-tree. The fork adds the Redox-side ioctl/ioctl-com -# and scheme: dispatch path needed by redox-drm and Mesa radeonsi/iris. +# This recipe pulls upstream libdrm 2.4.125 +# (https://gitlab.freedesktop.org/mesa/libdrm) at the pinned tag, +# then applies Red Bear OS external patches from local/patches/libdrm/ +# on top of the upstream tree. +# +# Per local/AGENTS.md Rule 2 (NO OVERLAY-STYLE PATCHES — AMENDED 2026), +# libdrm is a big external project (multi-thousand-line C codebase with a +# fast-moving upstream Mesa release cadence). Red Bear does NOT maintain a +# source fork of libdrm — external patches in local/patches/libdrm/ keep +# us close to upstream, give a clean audit trail (one mbox-style patch per +# Red Bear change), and make upstream syncs a `rev = "..."` bump + patch +# rebase instead of a full rebase of a Red Bear fork. +# +# The 5 Red Bear OS patches add the Redox-side ioctl/ioctl-com and +# scheme: dispatch path needed by redox-drm and Mesa radeonsi/iris: +# +# 01-drm-ioctl-bridge.patch +# xf86drm.c: add scheme:drm/ioctl-com path so drmIoctl() in +# user-space (Mesa, KWin, redbear-compositor) talks to the +# redox-drm scheme daemon over scheme:drm instead of the Linux +# /dev/dri/cardN ioctl. This is the central Red Bear dispatch +# shim. +# 02-ioctl-response-sizes.patch +# xf86drm.c: extend redox_drm_expected_response_size() with +# drm ioctl numbers Red Bear's ioctl-com shim recognizes for +# 3D/render-node command submission (0xB2/0xB4/0xBD/0xBE in +# addition to the legacy display ioctls 0xA9/0xAA/0xAC). +# 03-drm-get-pci-info.patch +# xf86drm.c: shim drmGetPciDevInfo() over the redox-driver-sys +# scheme:pci handle so Mesa's amdgpu loader can resolve BDF +# <-> /scheme/drm/cardN without a Linux sysfs tree. +# 04-drm-get-version-driver-name.patch +# xf86drm.c: shim drmGetVersion()/drmGetDriverName() to read +# the driver name ("amdgpu", "i915", "virtio-pci", ...) +# from the redox-drm scheme reply so Mesa's loader picks the +# correct Gallium driver for the kernel-mode driver. +# 05-drmGetDeviceFromDevId-redox.patch +# xf86drm.c: replace drmGetDeviceFromDevId() with a Redox +# implementation that resolves the (vendor, device) pair to +# the correct /scheme/drm/cardN path through the redox-drm +# scheme, since Redox has no Linux /dev/dri/by-path tree. # # On Redox, libdrm talks to: # * redox-drm (local/recipes/gpu/redox-drm) # * scheme: memory, scheme:irq, scheme:pci # * relibc (for the open_memstream fallback and major/minor shims) # -# The previous P1-P4 patch series referenced by the recipe -# (P1-drm-ioctl-bridge, P2-drm-get-pci-info, P3-drm-get-version-driver-name, -# P4-drmGetDeviceFromDevId-redox) is now folded into the single -# redox.patch that ships inside the source fork. No external patch -# files are needed; the build is fully offline and reproducible from -# the fork's git HEAD. +# To add a new libdrm change: +# 1. make the change in the fetched tree +# 2. `git diff > local/patches/libdrm/NN-short-description.patch` +# 3. add the patch to the [source].script apply loop below +# 4. commit the patch in the main repo # -# Build target: amdgpu=enabled. intel/nouveau/radeon/vmwgfx are -# disabled by default because the Redox GPU driver surface is -# brought up through redox-drm and we only need the AMD backend for -# the redbear-full target's radeonsi Mesa path. Tests are disabled -# because the cross-compiled test binaries cannot run in the -# cookbook build environment. +# Build target: amdgpu=enabled. intel/nouveau/radeon/vmwgfx are disabled +# by default because the Redox GPU driver surface is brought up through +# redox-drm and we only need the AMD backend for the redbear-full +# target's radeonsi Mesa path. Tests are disabled because the +# cross-compiled test binaries cannot run in the cookbook build +# environment. + [source] -path = "../../../../local/sources/libdrm" +git = "https://gitlab.freedesktop.org/mesa/libdrm" +rev = "libdrm-2.4.125" +# Apply Red Bear OS external patches (per local/AGENTS.md Rule 2). +# Recipe is at local/recipes/libs/libdrm/ (depth 3), so 4 dots reach +# the project root, then /local/patches/libdrm is appended. The +# cookbook runs this script with cwd = the cloned source tree, so +# `git apply` works directly on the upstream checkout. +script = """ +REDBEAR_PATCHES_DIR="${REDBEAR_PATCHES_DIR:-$(cd "$(dirname "${COOKBOOK_RECIPE}")/../../../.." && pwd)}/local/patches/libdrm" +for p in "${REDBEAR_PATCHES_DIR}"/[0-9]*.patch; do + [ -f "$p" ] || continue + echo "Applying Red Bear libdrm patch: $p" + git apply "$p" || { echo "Failed to apply $p"; exit 1; } +done +""" [build] template = "meson" @@ -41,4 +91,4 @@ mesonflags = [ [package] version = "0.2.3" -description = "libdrm 0.2.3 (v6.0 2026) — DRM/KMS user-space library, Red Bear fork. Provides libdrm.so.2, the amdgpu helpers, the xf86drm device-open helpers, the mode-setting API, and the open_memstream/major/minor portability shims required to build Mesa radeonsi and the redox-drm scheme against the Redox target. Forked from upstream libdrm 2.4.125 (gitlab.freedesktop.org/mesa/libdrm); the redox.patch series is applied in-tree at local/sources/libdrm/." +description = "libdrm 0.2.3 (v6.0 2026) — DRM/KMS user-space library, with Red Bear OS external patches in local/patches/libdrm/ (per local/AGENTS.md Rule 2). Pulls upstream libdrm 2.4.125 (gitlab.freedesktop.org/mesa/libdrm) and applies 5 Red Bear patches: drm-ioctl-bridge, ioctl-response-sizes, drm-get-pci-info, drm-get-version-driver-name, and drmGetDeviceFromDevId redox shim. Provides libdrm.so.2, the amdgpu helpers, the xf86drm device-open helpers, the mode-setting API, and the open_memstream/major/minor portability shims required to build Mesa radeonsi and the redox-drm scheme against the Redox target."