diff --git a/local/patches/mesa/01-virgl-redox-disk-cache.patch b/local/patches/mesa/01-virgl-redox-disk-cache.patch new file mode 100644 index 0000000000..192a34b4fa --- /dev/null +++ b/local/patches/mesa/01-virgl-redox-disk-cache.patch @@ -0,0 +1,25 @@ +diff --git a/src/gallium/drivers/virgl/virgl_screen.c b/src/gallium/drivers/virgl/virgl_screen.c +index d86ca5d1e..f79b8c678 100644 +--- a/src/gallium/drivers/virgl/virgl_screen.c ++++ b/src/gallium/drivers/virgl/virgl_screen.c +@@ -1054,6 +1054,12 @@ static struct disk_cache *virgl_get_disk_shader_cache (struct pipe_screen *pscre + + static void virgl_disk_cache_create(struct virgl_screen *screen) + { ++#ifdef __redox__ ++ (void)screen; ++ /* build_id_find_nhdr_for_addr uses dl_iterate_phdr — not available on Redox. ++ * Disk cache is disabled; shader compilation works without it. */ ++ screen->disk_cache = NULL; ++#else + const struct build_id_note *note = + build_id_find_nhdr_for_addr(virgl_disk_cache_create); + assert(note); +@@ -1078,6 +1084,7 @@ static void virgl_disk_cache_create(struct virgl_screen *screen) + _mesa_sha1_format(timestamp, sha1); + + screen->disk_cache = disk_cache_create("virgl", timestamp, 0); ++#endif + } + + static bool diff --git a/local/patches/mesa/02-gbm-dumb-prime-export.patch b/local/patches/mesa/02-gbm-dumb-prime-export.patch new file mode 100644 index 0000000000..f27928e1b7 --- /dev/null +++ b/local/patches/mesa/02-gbm-dumb-prime-export.patch @@ -0,0 +1,32 @@ +diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c +index 91fcc1fd2..af26e20d6 100644 +--- a/src/gbm/backends/dri/gbm_dri.c ++++ b/src/gbm/backends/dri/gbm_dri.c +@@ -578,8 +578,11 @@ gbm_dri_bo_get_fd(struct gbm_bo *_bo) + struct gbm_dri_bo *bo = gbm_dri_bo(_bo); + int fd; + +- if (bo->image == NULL) +- return -1; ++ if (bo->image == NULL) { ++ if (drmPrimeHandleToFD(dri->base.v0.fd, bo->handle, DRM_CLOEXEC | DRM_RDWR, &fd) != 0) ++ return -1; ++ return fd; ++ } + + if (!dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_FD, &fd)) + return -1; +@@ -663,8 +666,11 @@ gbm_dri_bo_get_plane_fd(struct gbm_bo *_bo, int plane) + + /* dumb BOs can only utilize non-planar formats */ + if (!bo->image) { +- errno = EINVAL; +- return -1; ++ if (plane != 0) { ++ errno = EINVAL; ++ return -1; ++ } ++ return gbm_dri_bo_get_fd(_bo); + } + + if (plane >= get_number_planes(dri, bo->image)) { diff --git a/local/patches/mesa/03-platform-redox-gpu-probe.patch b/local/patches/mesa/03-platform-redox-gpu-probe.patch new file mode 100644 index 0000000000..ed4f287420 --- /dev/null +++ b/local/patches/mesa/03-platform-redox-gpu-probe.patch @@ -0,0 +1,240 @@ +diff --git a/src/egl/drivers/dri2/platform_redox.c b/src/egl/drivers/dri2/platform_redox.c +index d6ceb1107..03d8e4c21 100644 +--- a/src/egl/drivers/dri2/platform_redox.c ++++ b/src/egl/drivers/dri2/platform_redox.c +@@ -62,10 +62,46 @@ redox_free_images(struct dri2_egl_surface *dri2_surf) + dri2_surf->front = NULL; + } + ++ if (dri2_surf->dri_image_back) { ++ dri2_dpy->image->destroyImage(dri2_surf->dri_image_back); ++ dri2_surf->dri_image_back = NULL; ++ } ++ + free(dri2_surf->swrast_device_buffer); + dri2_surf->swrast_device_buffer = NULL; + } + ++static int ++redox_image_get_buffers(__DRIdrawable *driDrawable, unsigned int format, ++ uint32_t *stamp, void *loaderPrivate, ++ uint32_t buffer_mask, ++ struct __DRIimageList *buffers) ++{ ++ struct dri2_egl_surface *dri2_surf = loaderPrivate; ++ struct dri2_egl_display *dri2_dpy = ++ dri2_egl_display(dri2_surf->base.Resource.Display); ++ ++ buffers->image_mask = 0; ++ buffers->front = NULL; ++ buffers->back = NULL; ++ ++ if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) { ++ if (!dri2_surf->front) ++ dri2_surf->front = redox_alloc_image(dri2_dpy, dri2_surf); ++ buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT; ++ buffers->front = dri2_surf->front; ++ } ++ ++ if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) { ++ if (!dri2_surf->dri_image_back) ++ dri2_surf->dri_image_back = redox_alloc_image(dri2_dpy, dri2_surf); ++ buffers->image_mask |= __DRI_IMAGE_BUFFER_BACK; ++ buffers->back = dri2_surf->dri_image_back; ++ } ++ ++ return 1; ++} ++ + static EGLBoolean + redox_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval) + { +@@ -220,6 +256,10 @@ dri2_redox_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf, + goto cleanup_surface; + } + ++ dri2_surf->visual = dri2_image_format_for_pbuffer_config(dri2_dpy, config); ++ if (dri2_surf->visual == __DRI_IMAGE_FORMAT_NONE) ++ goto cleanup_surface; ++ + if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf)) { + goto cleanup_surface; + } +@@ -366,6 +406,27 @@ static const __DRIkopperLoaderExtension kopper_loader_extension = { + .SetSurfaceCreateInfo = NULL, + }; + ++static void ++redox_hw_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate) ++{ ++} ++ ++static const __DRIimageLoaderExtension redox_image_loader_extension = { ++ .base = {__DRI_IMAGE_LOADER, 2}, ++ .getBuffers = redox_image_get_buffers, ++ .flushFrontBuffer = redox_hw_flush_front_buffer, ++ .getCapability = redox_get_capability, ++}; ++ ++static const __DRIextension *redox_hw_loader_extensions[] = { ++ &redox_image_loader_extension.base, ++ &image_lookup_extension.base, ++ &use_invalidate.base, ++ &background_callable_extension.base, ++ &kopper_loader_extension.base, ++ NULL, ++}; ++ + static const __DRIswrastLoaderExtension swrast_loader_extension = { + .base = {__DRI_SWRAST_LOADER, 1}, + .getDrawableInfo = redox_swrast_get_drawable_info, +@@ -381,6 +442,92 @@ static const __DRIextension *redox_swrast_loader_extensions[] = { + NULL, + }; + ++static bool ++redox_probe_device_hw(_EGLDisplay *disp) ++{ ++ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); ++ struct _egl_device *device; ++ int fd = -1; ++ ++ /* Try to open a DRM device on Redox first, then the conventional path. */ ++ const char *drm_paths[] = { ++ "/scheme/drm/card0", ++ "/dev/dri/card0", ++ NULL, ++ }; ++ ++ fprintf(stderr, "[REDOX-EGL] redox_probe_device_hw: starting\n"); ++ ++ for (int i = 0; drm_paths[i]; i++) { ++ fd = open(drm_paths[i], O_RDWR | O_CLOEXEC); ++ fprintf(stderr, "[REDOX-EGL] open(%s) = %d\n", drm_paths[i], fd); ++ if (fd >= 0) ++ break; ++ } ++ ++ if (fd < 0) { ++ fprintf(stderr, "[REDOX-EGL] no DRM device found\n"); ++ return false; ++ } ++ ++ /* Resolve the DRI driver from the DRM fd via PCI ID lookup. */ ++ char *driver_name = loader_get_driver_for_fd(fd); ++ fprintf(stderr, "[REDOX-EGL] loader_get_driver_for_fd returned: %s\n", ++ driver_name ? driver_name : "(null)"); ++ if (!driver_name) { ++ close(fd); ++ return false; ++ } ++ ++ if (strcmp(driver_name, "swrast") == 0 || ++ strcmp(driver_name, "kms_swrast") == 0) { ++ fprintf(stderr, "[REDOX-EGL] driver is swrast/kms_swrast, skipping HW path\n"); ++ free(driver_name); ++ close(fd); ++ return false; ++ } ++ ++ dri2_dpy->fd_render_gpu = fd; ++ dri2_dpy->driver_name = driver_name; ++ ++ device = _eglFindDevice(fd, false); ++ fprintf(stderr, "[REDOX-EGL] _eglFindDevice returned: %p\n", (void *)device); ++ if (!device) { ++ free(driver_name); ++ close(fd); ++ dri2_dpy->driver_name = NULL; ++ dri2_dpy->fd_render_gpu = -1; ++ return false; ++ } ++ ++ if (_eglHasAttrib(disp, EGL_DEVICE_EXT) && disp->Device != device) { ++ fprintf(stderr, "[REDOX-EGL] EGL_DEVICE_EXT mismatch\n"); ++ free(driver_name); ++ close(fd); ++ dri2_dpy->driver_name = NULL; ++ dri2_dpy->fd_render_gpu = -1; ++ return false; ++ } ++ disp->Device = device; ++ ++ /* Hardware drivers expose the DRI3/image entrypoints we need here. */ ++ fprintf(stderr, "[REDOX-EGL] calling dri2_load_driver_dri3 (driver=%s)...\n", driver_name); ++ if (!dri2_load_driver_dri3(disp)) { ++ fprintf(stderr, "[REDOX-EGL] dri2_load_driver_dri3 FAILED\n"); ++ free(driver_name); ++ close(fd); ++ dri2_dpy->driver_name = NULL; ++ dri2_dpy->fd_render_gpu = -1; ++ return false; ++ } ++ fprintf(stderr, "[REDOX-EGL] dri2_load_driver_dri3 succeeded\n"); ++ ++ dri2_dpy->loader_extensions = redox_hw_loader_extensions; ++ ++ fprintf(stderr, "[REDOX-EGL] redox_probe_device_hw: SUCCESS (driver=%s)\n", driver_name); ++ return true; ++} ++ + static bool + redox_probe_device_sw(_EGLDisplay *disp) + { +@@ -488,6 +635,8 @@ dri2_initialize_redox(_EGLDisplay *disp) + bool driver_loaded = false; + struct dri2_egl_display *dri2_dpy = dri2_display_create(); + ++ fprintf(stderr, "[REDOX-EGL] dri2_initialize_redox: starting\n"); ++ + if (!dri2_dpy) { + err = "dri2_display_create failed"; + goto cleanup; +@@ -495,7 +644,12 @@ dri2_initialize_redox(_EGLDisplay *disp) + + disp->DriverData = (void *)dri2_dpy; + +- driver_loaded = redox_probe_device_sw(disp); ++ /* Try hardware GPU first (virgl, amdgpu, etc.). */ ++ driver_loaded = redox_probe_device_hw(disp); ++ fprintf(stderr, "[REDOX-EGL] HW probe: %s\n", driver_loaded ? "SUCCESS" : "FAILED"); ++ /* Fall back to software rendering (llvmpipe/softpipe). */ ++ if (!driver_loaded) ++ driver_loaded = redox_probe_device_sw(disp); + + if (!driver_loaded) { + err = "DRI2: failed to load driver"; +@@ -503,16 +657,21 @@ dri2_initialize_redox(_EGLDisplay *disp) + } + + dri2_dpy->fd_display_gpu = dri2_dpy->fd_render_gpu; ++ fprintf(stderr, "[REDOX-EGL] calling dri2_create_screen...\n"); + + if (!dri2_create_screen(disp)) { + err = "DRI2: failed to create screen"; ++ fprintf(stderr, "[REDOX-EGL] dri2_create_screen FAILED\n"); + goto cleanup; + } ++ fprintf(stderr, "[REDOX-EGL] dri2_create_screen succeeded\n"); + + if (!dri2_setup_extensions(disp)) { + err = "DRI2: failed to find required DRI extensions"; ++ fprintf(stderr, "[REDOX-EGL] dri2_setup_extensions FAILED\n"); + goto cleanup; + } ++ fprintf(stderr, "[REDOX-EGL] dri2_setup_extensions succeeded\n"); + + dri2_setup_screen(disp); + +@@ -532,9 +691,11 @@ dri2_initialize_redox(_EGLDisplay *disp) + + dri2_dpy->vtbl = &dri2_redox_display_vtbl; + ++ fprintf(stderr, "[REDOX-EGL] dri2_initialize_redox: COMPLETE\n"); + return EGL_TRUE; + + cleanup: ++ fprintf(stderr, "[REDOX-EGL] dri2_initialize_redox: FAILED: %s\n", err); + dri2_display_destroy(disp); + return _eglError(EGL_NOT_INITIALIZED, err); + } diff --git a/recipes/libs/mesa/recipe.toml b/recipes/libs/mesa/recipe.toml index 91b550d46b..d3df89f190 100644 --- a/recipes/libs/mesa/recipe.toml +++ b/recipes/libs/mesa/recipe.toml @@ -1,19 +1,26 @@ # mesa — Mesa 3-D graphics library. # -# This recipe builds the Red Bear OS mesa fork maintained at -# local/sources/mesa/. The fork is based on upstream Redox mesa -# (https://gitlab.redox-os.org/redox-os/mesa, branch redox-24.0) -# at commit 0ecd6b66c, with the Red Bear OS 0.2.3 fork of mesa -# applied on the local 0.2.3 branch (HEAD a7e54995f). +# This recipe pulls upstream Redox mesa +# (https://gitlab.redox-os.org/redox-os/mesa, branch redox-24.0) at +# the pinned branch, then applies Red Bear OS external patches from +# local/patches/mesa/ on top of the upstream tree. # -# Per AGENTS.md, mesa is a big external project (multi-million-line -# codebase) and is therefore maintained as a Red Bear fork at -# local/sources/mesa/. The mainline recipe is a thin shim that -# points the cookbook at the fork via the Local source type. -# All Red Bear-specific mesa changes (EGL/GBM/virgl Redox fixes, -# include/sys/ioccom.h stub, removal of upstream Android-only -# GitLab CI patches) are committed on the fork's 0.2.3 branch -# and never live in this recipe. +# Per local/AGENTS.md Rule 2 (NO OVERLAY-STYLE PATCHES — AMENDED 2026), +# mesa is a big external project (multi-million-line codebase with a +# fast-moving upstream). Red Bear does NOT maintain a source fork of +# mesa — external patches in local/patches/mesa/ 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. +# +# All Red Bear-specific mesa changes (virgl disk cache disabled for +# missing dl_iterate_phdr, GBM dumb prime export, platform/redox GPU +# probe) live as external patches under local/patches/mesa/. To add a +# new mesa change: +# 1. make the change in the fetched tree +# 2. `git diff > local/patches/mesa/NN-short-description.patch` +# 3. add a `git apply` line in [build].script in apply order +# 4. commit the patch in the main repo # # Build target surface: # * EGL/GBM/GLES 2.0/3.0 + OSMesa + LLVMpipe + virgl @@ -21,20 +28,20 @@ # (Intel Gen8+), crocus (Intel Gen4-7) # * Vulkan drivers: swrast (software fallback) # * Wayland EGL platform: -Dplatforms=wayland -# * DRM/KMS path: /scheme/drm/cardN via libdrm (Red Bear fork) +# * DRM/KMS path: /scheme/drm/cardN via libdrm (external patches) # # Build environment requirements: # * LLVM 21.x with the x86_64-unknown-redox target (llvm21) -# * libdrm 2.4.x (Red Bear fork at local/sources/libdrm/) +# * libdrm 2.4.x (with Red Bear OS external patches in local/patches/libdrm/) # * libwayland (Redox libwayland fork, drm-client/server/egl/drm) # * wayland-protocols 1.x # # Version history: -# * 0.1.0 (2026-04) — initial import, upstream redox-24.0 (0ecd6b66c) -# * 0.2.3 (v6.0 2026) — Redox EGL/GBM/virgl fixes + ioccom.h stub +# * 0.1.0 (2026-04) — initial import, upstream redox-24.0 +# * 0.2.3 (v6.0 2026) — Red Bear OS external patches applied + [source] -path = "../../../local/sources/mesa" -upstream = "https://gitlab.freedesktop.org/mesa/mesa" +git = "https://gitlab.redox-os.org/redox-os/mesa" branch = "redox-24.0" [build] @@ -53,6 +60,17 @@ dev-dependencies = [ script = """ DYNAMIC_INIT +# Apply Red Bear OS external patches (per local/AGENTS.md Rule 2) +# Recipe is at recipes/libs/mesa/ (depth 2), so 2 dots reach the +# project root, then /local/patches/mesa is appended. +REDBEAR_PATCHES_DIR="$(cd "$(dirname "${COOKBOOK_RECIPE}")/../.." && pwd)/local/patches/mesa" +cd "${COOKBOOK_SOURCE}" +for p in "${REDBEAR_PATCHES_DIR}"/[0-9]*.patch; do + [ -f "$p" ] || continue + git apply "$p" || { echo "Failed to apply $p"; exit 1; } +done +cd "${COOKBOOK_BUILD}" + #TODO: Should be CPPFLAGS but cookbook_meson isn't reading it export CFLAGS+=" -DHAVE_PTHREAD=1 -I${COOKBOOK_SYSROOT}/include/libdrm" export LLVM_CONFIG="${TARGET}-llvm-config" @@ -96,4 +114,4 @@ sed -i "s/ -lOSMesa / -lOSMesa ${LLVMLIBS} -lstdc++ /" "${COOKBOOK_STAGE}/usr/li [package] version = "0.2.3" -description = "mesa 0.2.3 (v6.0 2026) — Mesa 3-D graphics library, Red Bear OS fork at local/sources/mesa/ (0.2.3 branch HEAD a7e54995f). Provides EGL/GBM/GLES2/3/OSMesa via the Wayland EGL platform, Gallium drivers swrast/virgl/iris/crocus, software Vulkan, and the Redox EGL/GBM/virgl fixes (dumb-prime fallback, virgl disk cache disabled for missing dl_iterate_phdr, include/sys/ioccom.h stub for DRM uapi ioctl number macros). Phase 2.1 of the v6.0 console-to-KDE plan." +description = "mesa 0.2.3 (v6.0 2026) — Mesa 3-D graphics library with Red Bear OS external patches in local/patches/mesa/ (per local/AGENTS.md Rule 2). Pulls upstream Redox mesa (gitlab.redox-os.org/redox-os/mesa, branch redox-24.0) and applies 3 Red Bear patches: virgl disk cache disabled (missing dl_iterate_phdr on Redox), GBM dumb prime export, and platform/redox GPU probe. Provides EGL/GBM/GLES2/3/OSMesa via the Wayland EGL platform, Gallium drivers swrast/virgl/iris/crocus, software Vulkan, and the Redox EGL/GBM/virgl fixes. Phase 2.1 of the v6.0 console-to-KDE plan."