diff --git a/gpkg/binutils-libs/build.sh b/gpkg/binutils-libs/build.sh index d557a4633..3e1d80c55 100644 --- a/gpkg/binutils-libs/build.sh +++ b/gpkg/binutils-libs/build.sh @@ -2,9 +2,9 @@ TERMUX_PKG_HOMEPAGE=https://www.gnu.org/software/binutils/ TERMUX_PKG_DESCRIPTION="GNU Binutils libraries" TERMUX_PKG_LICENSE="GPL-3.0" TERMUX_PKG_MAINTAINER="@termux-pacman" -TERMUX_PKG_VERSION=2.43 +TERMUX_PKG_VERSION=2.43.1 TERMUX_PKG_SRCURL=https://ftp.gnu.org/gnu/binutils/binutils-$TERMUX_PKG_VERSION.tar.xz -TERMUX_PKG_SHA256=b53606f443ac8f01d1d5fc9c39497f2af322d99e14cea5c0b4b124d630379365 +TERMUX_PKG_SHA256=13f74202a3c4c51118b797a39ea4200d3f6cfbe224da6d1d95bb938480132dfd TERMUX_PKG_DEPENDS="glibc, libjansson-glibc, libelf-glibc, zlib-glibc, zstd-glibc" TERMUX_PKG_CONFFILES="glibc/etc/gprofng.rc" TERMUX_PKG_NO_STATICSPLIT=true diff --git a/gpkg/mesa/0011-freedreno-drm-kgsl-Add-KGSL-backend-for-freedreno.patch b/gpkg/mesa/0011-freedreno-drm-kgsl-Add-KGSL-backend-for-freedreno.patch new file mode 100644 index 000000000..69297f7ac --- /dev/null +++ b/gpkg/mesa/0011-freedreno-drm-kgsl-Add-KGSL-backend-for-freedreno.patch @@ -0,0 +1,827 @@ +From d748c03e83aed1a5f0176a264e03862d94d99418 Mon Sep 17 00:00:00 2001 +From: Lucas Fryzek +Date: Mon, 13 Mar 2023 14:39:50 -0400 +Subject: [PATCH 1/2] freedreno/drm/kgsl: Add KGSL backend for freedreno + +--- + meson.build | 4 + + src/freedreno/drm/kgsl/kgsl_bo.c | 295 ++++++++++++++++++++ + src/freedreno/drm/kgsl/kgsl_device.c | 44 +++ + src/freedreno/drm/kgsl/kgsl_pipe.c | 225 +++++++++++++++ + src/freedreno/drm/kgsl/kgsl_priv.h | 54 ++++ + src/freedreno/drm/kgsl/kgsl_ringbuffer_sp.c | 119 ++++++++ + src/freedreno/drm/meson.build | 11 + + 7 files changed, 752 insertions(+) + create mode 100644 src/freedreno/drm/kgsl/kgsl_bo.c + create mode 100644 src/freedreno/drm/kgsl/kgsl_device.c + create mode 100644 src/freedreno/drm/kgsl/kgsl_pipe.c + create mode 100644 src/freedreno/drm/kgsl/kgsl_priv.h + create mode 100644 src/freedreno/drm/kgsl/kgsl_ringbuffer_sp.c + +diff --git a/meson.build b/meson.build +index 9fb4160cf54..565e24b0bc5 100644 +--- a/meson.build ++++ b/meson.build +@@ -278,6 +278,10 @@ if freedreno_kmds.length() != 0 and freedreno_kmds != [ 'msm' ] and with_freedre + endif + endif + ++if freedreno_kmds.contains('kgsl') ++ pre_args += '-DHAVE_FREEDRENO_KGSL' ++endif ++ + with_dri = false + if with_gallium and system_has_kms_drm + _glx = get_option('glx') +diff --git a/src/freedreno/drm/kgsl/kgsl_bo.c b/src/freedreno/drm/kgsl/kgsl_bo.c +new file mode 100644 +index 00000000000..d42400207ad +--- /dev/null ++++ b/src/freedreno/drm/kgsl/kgsl_bo.c +@@ -0,0 +1,295 @@ ++#include "kgsl_priv.h" ++#include "util/os_file.h" ++#include "util/os_mman.h" ++ ++#include ++ ++static uint64_t ++kgsl_bo_iova(struct fd_bo *bo) ++{ ++ struct kgsl_bo *kgsl_bo = to_kgsl_bo(bo); ++ return kgsl_bo->iova; ++} ++ ++static void ++kgsl_bo_set_name(struct fd_bo *bo, const char *fmt, va_list ap) ++{ ++ /* This function is a no op for KGSL */ ++ return; ++} ++ ++static int ++kgsl_bo_offset(struct fd_bo *bo, uint64_t *offset) ++{ ++ /* from tu_kgsl.c - offset for mmap needs to be */ ++ /* the returned alloc id shifted over 12 */ ++ *offset = bo->handle << 12; ++ return 0; ++} ++ ++static int ++kgsl_bo_madvise(struct fd_bo *bo, int willneed) ++{ ++ /* KGSL does not support this, so simply return willneed */ ++ return willneed; ++} ++ ++static int ++kgsl_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op) ++{ ++ /* only need to handle implicit sync here which is a NOP for KGSL */ ++ return 0; ++} ++ ++void ++kgsl_bo_close_handle(struct fd_bo *bo) ++{ ++ struct kgsl_bo *kgsl_bo = to_kgsl_bo(bo); ++ if (kgsl_bo->bo_type == KGSL_BO_IMPORT) { ++ close(kgsl_bo->import_fd); ++ } ++ ++ struct kgsl_gpumem_free_id req = { ++ .id = bo->handle ++ }; ++ ++ kgsl_pipe_safe_ioctl(bo->dev->fd, IOCTL_KGSL_GPUMEM_FREE_ID, &req); ++} ++ ++static void ++kgsl_bo_destroy(struct fd_bo *bo) ++{ ++ /* KGSL will immediately delete the BO when we close ++ * the handle, so wait on all fences to ensure ++ * the GPU is done using it before we destory it ++ */ ++ for (uint32_t i = 0; i < bo->nr_fences; i++) { ++ struct fd_pipe *pipe = bo->fences[i]->pipe; ++ pipe->funcs->wait(pipe, bo->fences[i], ~0); ++ } ++ ++ fd_bo_fini_common(bo); ++} ++ ++static void * ++kgsl_bo_map(struct fd_bo *bo) ++{ ++ struct kgsl_bo *kgsl_bo = to_kgsl_bo(bo); ++ if (!bo->map) { ++ if (kgsl_bo->bo_type == KGSL_BO_IMPORT) { ++ /* in `fd_bo_map` if it tries to mmap this BO. mmap logic is copied from ++ * https://android.googlesource.com/platform/hardware/libhardware/+/master/modules/gralloc/mapper.cpp#44 ++ */ ++ bo->map = os_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, kgsl_bo->import_fd, 0); ++ } else { ++ uint64_t offset; ++ int ret; ++ ++ ret = bo->funcs->offset(bo, &offset); ++ if (ret) { ++ return NULL; ++ } ++ ++ bo->map = os_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, ++ bo->dev->fd, offset); ++ if (bo->map == MAP_FAILED) { ++ ERROR_MSG("mmap failed: %s", strerror(errno)); ++ bo->map = NULL; ++ } ++ } ++ ++ if (bo->map == MAP_FAILED) { ++ ERROR_MSG("mmap failed: %s", strerror(errno)); ++ bo->map = NULL; ++ } ++ } ++ return bo->map; ++} ++ ++static int kgsl_bo_dmabuf(struct fd_bo *bo) { ++ struct kgsl_bo *kgsl_bo = to_kgsl_bo(bo); ++ return os_dupfd_cloexec(kgsl_bo->import_fd); ++} ++ ++static const struct fd_bo_funcs bo_funcs = { ++ .iova = kgsl_bo_iova, ++ .set_name = kgsl_bo_set_name, ++ .offset = kgsl_bo_offset, ++ .map = kgsl_bo_map, ++ .madvise = kgsl_bo_madvise, ++ .cpu_prep = kgsl_bo_cpu_prep, ++ .destroy = kgsl_bo_destroy, ++ .dmabuf = kgsl_bo_dmabuf, ++}; ++ ++/* Size is not used by KGSL */ ++struct fd_bo * ++kgsl_bo_from_handle(struct fd_device *dev, uint32_t size, uint32_t handle) ++{ ++ struct fd_bo *bo; ++ int ret; ++ struct kgsl_gpuobj_info req = { ++ .id = handle, ++ }; ++ ++ ret = kgsl_pipe_safe_ioctl(dev->fd, ++ IOCTL_KGSL_GPUOBJ_INFO, &req); ++ ++ if (ret) { ++ ERROR_MSG("Failed to get handle info (%s)", strerror(errno)); ++ return NULL; ++ } ++ ++ struct kgsl_bo *kgsl_bo = calloc(1, sizeof(*kgsl_bo)); ++ if (!kgsl_bo) ++ return NULL; ++ ++ bo = &kgsl_bo->base; ++ bo->dev = dev; ++ bo->size = req.size; ++ bo->handle = req.id; ++ bo->funcs = &bo_funcs; ++ ++ kgsl_bo->iova = req.gpuaddr; ++ ++ fd_bo_init_common(bo, dev); ++ ++ return bo; ++} ++ ++struct fd_bo * ++kgsl_bo_from_dmabuf(struct fd_device *dev, int fd) ++{ ++ struct fd_bo *bo; ++ struct kgsl_gpuobj_import_dma_buf import_dmabuf = { ++ .fd = fd, ++ }; ++ struct kgsl_gpuobj_import req = { ++ .priv = (uintptr_t)&import_dmabuf, ++ .priv_len = sizeof(import_dmabuf), ++ .flags = 0, ++ .type = KGSL_USER_MEM_TYPE_DMABUF, ++ }; ++ int ret; ++ ++ ret = kgsl_pipe_safe_ioctl(dev->fd, ++ IOCTL_KGSL_GPUOBJ_IMPORT, &req); ++ ++ if (ret) { ++ ERROR_MSG("Failed to import dma-buf (%s)", strerror(errno)); ++ return NULL; ++ } ++ ++ bo = fd_bo_from_handle(dev, req.id, 0); ++ ++ struct kgsl_bo *kgsl_bo = to_kgsl_bo(bo); ++ kgsl_bo->bo_type = KGSL_BO_IMPORT; ++ kgsl_bo->import_fd = os_dupfd_cloexec(fd); ++ ++ return bo; ++} ++ ++static int ++dma_heap_alloc(uint64_t size) ++{ ++ int ret; ++ int dma_heap = open("/dev/dma_heap/system", O_RDONLY); ++ ++ if (dma_heap < 0) { ++ int ion_heap = open("/dev/ion", O_RDONLY); ++ ++ if (ion_heap < 0) ++ return -1; ++ ++ struct ion_allocation_data { ++ __u64 len; ++ __u32 heap_id_mask; ++ __u32 flags; ++ __u32 fd; ++ __u32 unused; ++ } alloc_data = { ++ .len = size, ++ /* ION_HEAP_SYSTEM | ION_SYSTEM_HEAP_ID */ ++ .heap_id_mask = (1U << 0) | (1U << 25), ++ .flags = 0, /* uncached */ ++ }; ++ ++ ret = kgsl_pipe_safe_ioctl(ion_heap, _IOWR('I', 0, struct ion_allocation_data), ++ &alloc_data); ++ ++ close(ion_heap); ++ ++ if (ret) ++ return -1; ++ ++ return alloc_data.fd; ++ } else { ++ struct dma_heap_allocation_data alloc_data = { ++ .len = size, ++ .fd_flags = O_RDWR | O_CLOEXEC, ++ }; ++ ++ ret = kgsl_pipe_safe_ioctl(dma_heap, DMA_HEAP_IOCTL_ALLOC, &alloc_data); ++ ++ close(dma_heap); ++ ++ if (ret) ++ return -1; ++ ++ return alloc_data.fd; ++ } ++} ++ ++static struct fd_bo * ++kgsl_bo_new_dmabuf(struct fd_device *dev, uint32_t size) ++{ ++ int fd; ++ struct fd_bo *bo; ++ ++ fd = dma_heap_alloc(size); ++ if (fd < 0) { ++ ERROR_MSG("Failed to allocate dma-buf (%s)", strerror(errno)); ++ return NULL; ++ } ++ ++ bo = kgsl_bo_from_dmabuf(dev, fd); ++ ++ close(fd); ++ return bo; ++} ++ ++struct fd_bo * ++kgsl_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags) ++{ ++ if (flags & (FD_BO_SHARED | FD_BO_SCANOUT)) { ++ return kgsl_bo_new_dmabuf(dev, size); ++ } ++ ++ int ret; ++ struct fd_bo *bo; ++ struct kgsl_gpumem_alloc_id req = { ++ .size = size, ++ }; ++ ++ if (flags & FD_BO_GPUREADONLY) ++ req.flags |= KGSL_MEMFLAGS_GPUREADONLY; ++ ++ ret = kgsl_pipe_safe_ioctl(dev->fd, IOCTL_KGSL_GPUMEM_ALLOC_ID, &req); ++ ++ if (ret) { ++ ERROR_MSG("GPUMEM_ALLOC_ID failed (%s)", strerror(errno)); ++ return NULL; ++ } ++ ++ bo = kgsl_bo_from_handle(dev, size, req.id); ++ ++ struct kgsl_bo *kgsl_bo = to_kgsl_bo(bo); ++ kgsl_bo->bo_type = KGSL_BO_NATIVE; ++ ++ if (!bo) { ++ ERROR_MSG("Failed to allocate buffer object"); ++ return NULL; ++ } ++ ++ return bo; ++} +diff --git a/src/freedreno/drm/kgsl/kgsl_device.c b/src/freedreno/drm/kgsl/kgsl_device.c +new file mode 100644 +index 00000000000..702b6666731 +--- /dev/null ++++ b/src/freedreno/drm/kgsl/kgsl_device.c +@@ -0,0 +1,44 @@ ++#include "kgsl_priv.h" ++ ++static const struct fd_device_funcs funcs = { ++ .bo_new = kgsl_bo_new, ++ .pipe_new = kgsl_pipe_new, ++ .bo_from_handle = kgsl_bo_from_handle, ++ .bo_from_dmabuf = kgsl_bo_from_dmabuf, ++ .bo_close_handle = kgsl_bo_close_handle, ++ .destroy = kgsl_device_destroy, ++}; ++ ++struct fd_device * ++kgsl_device_new(int fd) ++{ ++ struct kgsl_device *kgsl_dev; ++ struct fd_device *dev; ++ struct kgsl_devinfo info; ++ ++ /* Try to read the device info to detect if the FD is really KGSL */ ++ if(kgsl_get_prop(fd, KGSL_PROP_DEVICE_INFO, &info, sizeof(info))) ++ return NULL; ++ ++ kgsl_dev = calloc(1, sizeof(*kgsl_dev)); ++ if (!kgsl_dev) ++ return NULL; ++ ++ dev = &kgsl_dev->base; ++ dev->funcs = &funcs; ++ dev->fd = fd; ++ dev->version = FD_VERSION_ROBUSTNESS; ++ dev->features = FD_FEATURE_DIRECT_RESET | FD_FEATURE_IMPORT_DMABUF; ++ ++ /* async submit_queue used for softpin deffered submits */ ++ util_queue_init(&dev->submit_queue, "sq", 8, 1, 0, NULL); ++ ++ dev->bo_size = sizeof(struct kgsl_bo); ++ ++ return dev; ++} ++ ++static void ++kgsl_device_destroy(struct fd_device *dev) ++{ ++} +diff --git a/src/freedreno/drm/kgsl/kgsl_pipe.c b/src/freedreno/drm/kgsl/kgsl_pipe.c +new file mode 100644 +index 00000000000..d48f186eb06 +--- /dev/null ++++ b/src/freedreno/drm/kgsl/kgsl_pipe.c +@@ -0,0 +1,225 @@ ++#include "kgsl_priv.h" ++#include "freedreno_ringbuffer_sp.h" ++ ++/* TODO this function is borrowed from turnip, can it be shared in some way? */ ++int ++kgsl_pipe_safe_ioctl(int fd, unsigned long request, void *arg) ++{ ++ int ret; ++ ++ do { ++ ret = ioctl(fd, request, arg); ++ } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); ++ ++ return ret; ++} ++ ++/* TODO this function is borrowed from turnip, can it be shared in some way? ++ * safe_ioctl is not enough as restarted waits would not adjust the timeout ++ * which could lead to waiting substantially longer than requested ++ */ ++static int ++wait_timestamp_safe(int fd, ++ unsigned int context_id, ++ unsigned int timestamp, ++ int64_t timeout_ms) ++{ ++ int64_t start_time = os_time_get_nano(); ++ struct kgsl_device_waittimestamp_ctxtid wait = { ++ .context_id = context_id, ++ .timestamp = timestamp, ++ .timeout = timeout_ms, ++ }; ++ ++ while (true) { ++ int ret = kgsl_pipe_safe_ioctl(fd, IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID, &wait); ++ ++ if (ret == -1 && (errno == EINTR || errno == EAGAIN)) { ++ int64_t current_time = os_time_get_nano(); ++ ++ /* update timeout to consider time that has passed since the start */ ++ timeout_ms -= (current_time - start_time) / 1000000; ++ if (timeout_ms <= 0) { ++ errno = ETIME; ++ return -1; ++ } ++ ++ wait.timeout = (unsigned int) timeout_ms; ++ start_time = current_time; ++ } else { ++ return ret; ++ } ++ } ++} ++ ++int ++kgsl_get_prop(int fd, unsigned int type, void *value, size_t size) ++{ ++ struct kgsl_device_getproperty getprop = { ++ .type = type, ++ .value = value, ++ .sizebytes = size, ++ }; ++ ++ return kgsl_pipe_safe_ioctl(fd, IOCTL_KGSL_DEVICE_GETPROPERTY, &getprop); ++} ++ ++static int ++kgsl_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param, ++ uint64_t *value) ++{ ++ struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); ++ switch (param) { ++ case FD_DEVICE_ID: ++ case FD_GPU_ID: ++ *value = kgsl_pipe->dev_id.gpu_id; ++ return 0; ++ case FD_GMEM_SIZE: ++ *value = kgsl_pipe->gmem_size; ++ return 0; ++ case FD_GMEM_BASE: ++ *value = kgsl_pipe->gmem_base; ++ return 0; ++ case FD_CHIP_ID: ++ *value = kgsl_pipe->dev_id.chip_id; ++ return 0; ++ case FD_NR_PRIORITIES: ++ /* Take from kgsl kmd source code, if device is a4xx or newer ++ * it has KGSL_PRIORITY_MAX_RB_LEVELS=4 priorities otherwise it just has one. ++ * https://android.googlesource.com/kernel/msm/+/refs/tags/android-13.0.0_r0.21/drivers/gpu/msm/kgsl.h#56 ++ */ ++ *value = kgsl_pipe->dev_id.gpu_id >= 400 ? 4 : 1; ++ return 0; ++ case FD_MAX_FREQ: ++ /* Explicity fault on MAX_FREQ as we don't have a way to convert ++ * timestamp values from KGSL into time values. If we use the default ++ * path an error message would be generated when this is simply an ++ * unsupported feature. ++ */ ++ return -1; ++ case FD_TIMESTAMP: ++ return -1; ++ default: ++ ERROR_MSG("invalid param id: %d", param); ++ return -1; ++ } ++} ++ ++static int ++kgsl_pipe_set_param(struct fd_pipe *pipe, uint32_t param, uint64_t value) ++{ ++ ERROR_MSG("kgsl_pipe_set_param not implemented"); ++ return -1; ++} ++ ++static int ++kgsl_pipe_wait(struct fd_pipe *pipe, const struct fd_fence *fence, uint64_t timeout) ++{ ++ struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); ++ return wait_timestamp_safe(pipe->dev->fd, kgsl_pipe->queue_id, fence->kfence, timeout); ++} ++ ++static void ++kgsl_pipe_destroy(struct fd_pipe *pipe) ++{ ++ struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); ++ struct kgsl_drawctxt_destroy req = { ++ .drawctxt_id = kgsl_pipe->queue_id, ++ }; ++ ++ fd_pipe_sp_ringpool_fini(pipe); ++ kgsl_pipe_safe_ioctl(pipe->dev->fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &req); ++ free(kgsl_pipe); ++} ++ ++static int ++kgsl_reset_status(struct fd_pipe *pipe, enum fd_reset_status *status) ++{ ++ struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); ++ uint32_t value = kgsl_pipe->queue_id; ++ int ret = kgsl_get_prop(pipe->dev->fd, KGSL_PROP_GPU_RESET_STAT, &value, sizeof(value)); ++ ++ if (!ret) { ++ switch (value) { ++ case KGSL_CTX_STAT_NO_ERROR: ++ *status = FD_RESET_NO_ERROR; ++ break; ++ case KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT: ++ *status = FD_RESET_GUILTY; ++ break; ++ case KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT: ++ *status = FD_RESET_INNOCENT; ++ break; ++ case KGSL_CTX_STAT_UNKNOWN_CONTEXT_RESET_EXT: ++ default: ++ *status = FD_RESET_UNKNOWN; ++ break; ++ } ++ } ++ ++ return ret; ++} ++ ++static const struct fd_pipe_funcs pipe_funcs = { ++ .ringbuffer_new_object = fd_ringbuffer_sp_new_object, ++ .submit_new = kgsl_submit_sp_new, ++ .reset_status = kgsl_reset_status, ++ .flush = fd_pipe_sp_flush, ++ .wait = kgsl_pipe_wait, ++ .get_param = kgsl_pipe_get_param, ++ .set_param = kgsl_pipe_set_param, ++ .destroy = kgsl_pipe_destroy, ++}; ++ ++struct fd_pipe *kgsl_pipe_new(struct fd_device *dev, enum fd_pipe_id id, ++ uint32_t prio) ++{ ++ struct kgsl_pipe *kgsl_pipe = NULL; ++ struct fd_pipe *pipe = NULL; ++ kgsl_pipe = calloc(1, sizeof(*kgsl_pipe)); ++ if (!kgsl_pipe) { ++ ERROR_MSG("allocation failed"); ++ goto fail; ++ } ++ ++ pipe = &kgsl_pipe->base; ++ pipe->dev = dev; ++ pipe->funcs = &pipe_funcs; ++ ++ struct kgsl_devinfo info; ++ if(kgsl_get_prop(dev->fd, KGSL_PROP_DEVICE_INFO, &info, sizeof(info))) ++ goto fail; ++ ++ uint64_t gmem_iova; ++ if(kgsl_get_prop(dev->fd, KGSL_PROP_UCHE_GMEM_VADDR, &gmem_iova, sizeof(gmem_iova))) ++ goto fail; ++ ++ kgsl_pipe->dev_id.gpu_id = ++ ((info.chip_id >> 24) & 0xff) * 100 + ++ ((info.chip_id >> 16) & 0xff) * 10 + ++ ((info.chip_id >> 8) & 0xff); ++ ++ kgsl_pipe->dev_id.chip_id = info.chip_id; ++ kgsl_pipe->gmem_size = info.gmem_sizebytes; ++ kgsl_pipe->gmem_base = gmem_iova; ++ ++ struct kgsl_drawctxt_create req = { ++ .flags = KGSL_CONTEXT_SAVE_GMEM | ++ KGSL_CONTEXT_NO_GMEM_ALLOC | ++ KGSL_CONTEXT_PREAMBLE, ++ }; ++ ++ int ret = kgsl_pipe_safe_ioctl(dev->fd, IOCTL_KGSL_DRAWCTXT_CREATE, &req); ++ if(ret) ++ goto fail; ++ ++ kgsl_pipe->queue_id = req.drawctxt_id; ++ ++ fd_pipe_sp_ringpool_init(pipe); ++ ++ return pipe; ++fail: ++ if (pipe) ++ fd_pipe_del(pipe); ++ return NULL; ++} +diff --git a/src/freedreno/drm/kgsl/kgsl_priv.h b/src/freedreno/drm/kgsl/kgsl_priv.h +new file mode 100644 +index 00000000000..ed65c952902 +--- /dev/null ++++ b/src/freedreno/drm/kgsl/kgsl_priv.h +@@ -0,0 +1,54 @@ ++#ifndef KGSL_PRIV_H ++#define KGSL_PRIV_H ++#include "freedreno_priv.h" ++ ++/* TODO the KGSL kernel interface should probably be moved */ ++/* into someplace common that both turnip and freedreno can use */ ++#include "../../vulkan/msm_kgsl.h" ++ ++int kgsl_get_prop(int fd, unsigned int type, void *value, size_t size); ++ ++struct kgsl_device { ++ struct fd_device base; ++}; ++FD_DEFINE_CAST(fd_device, kgsl_device); ++ ++struct fd_device *kgsl_device_new(int fd); ++static void kgsl_device_destroy(struct fd_device *dev); ++ ++struct kgsl_pipe { ++ struct fd_pipe base; ++ ++ struct fd_dev_id dev_id; ++ ++ uint32_t gmem_size; ++ uint64_t gmem_base; ++ uint32_t queue_id; ++}; ++FD_DEFINE_CAST(fd_pipe, kgsl_pipe); ++ ++struct fd_pipe *kgsl_pipe_new(struct fd_device *dev, enum fd_pipe_id id, ++ uint32_t prio); ++int kgsl_pipe_safe_ioctl(int fd, unsigned long request, void *arg); ++struct fd_submit *kgsl_submit_sp_new(struct fd_pipe *pipe); ++ ++struct kgsl_bo { ++ struct fd_bo base; ++ const char *name; ++ uint64_t iova; ++ uint32_t queue_id; ++ int import_fd; // fd for imported buffers ++ ++ enum { ++ KGSL_BO_NATIVE, ++ KGSL_BO_IMPORT, ++ } bo_type; ++}; ++FD_DEFINE_CAST(fd_bo, kgsl_bo); ++ ++struct fd_bo *kgsl_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags); ++struct fd_bo *kgsl_bo_from_dmabuf(struct fd_device *dev, int fd); ++struct fd_bo *kgsl_bo_from_handle(struct fd_device *dev, uint32_t size, uint32_t handle); ++void kgsl_bo_close_handle(struct fd_bo *bo); ++ ++#endif +diff --git a/src/freedreno/drm/kgsl/kgsl_ringbuffer_sp.c b/src/freedreno/drm/kgsl/kgsl_ringbuffer_sp.c +new file mode 100644 +index 00000000000..e8b2842ac3d +--- /dev/null ++++ b/src/freedreno/drm/kgsl/kgsl_ringbuffer_sp.c +@@ -0,0 +1,119 @@ ++#include "kgsl_priv.h" ++#include "freedreno_ringbuffer_sp.h" ++ ++static int ++timestamp_to_fd(struct fd_pipe *pipe, uint32_t timestamp) ++{ ++ int fd; ++ struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); ++ struct kgsl_timestamp_event event = { ++ .type = KGSL_TIMESTAMP_EVENT_FENCE, ++ .context_id = kgsl_pipe->queue_id, ++ .timestamp = timestamp, ++ .priv = &fd, ++ .len = sizeof(fd), ++ }; ++ ++ int ret = kgsl_pipe_safe_ioctl(pipe->dev->fd, IOCTL_KGSL_TIMESTAMP_EVENT, &event); ++ if (ret) ++ return -1; ++ ++ return fd; ++} ++ ++static int ++flush_submit_list(struct list_head *submit_list) ++{ ++ struct fd_submit_sp *fd_submit = to_fd_submit_sp(last_submit(submit_list)); ++ struct fd_pipe *pipe = fd_submit->base.pipe; ++ struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); ++ unsigned nr_cmds = 0; ++ ++ ++ MESA_TRACE_FUNC(); ++ ++ foreach_submit (submit, submit_list) { ++ assert(submit->pipe == &kgsl_pipe->base); ++ nr_cmds += to_fd_ringbuffer_sp(submit->primary)->u.nr_cmds; ++ } ++ ++ struct kgsl_command_object cmds[nr_cmds]; ++ unsigned cmd_idx = 0; ++ foreach_submit_safe (submit, submit_list) { ++ struct fd_ringbuffer_sp *deferred_primary = ++ to_fd_ringbuffer_sp(submit->primary); ++ ++ for (unsigned i = 0; i < deferred_primary->u.nr_cmds; i++) { ++ struct fd_bo *ring_bo = deferred_primary->u.cmds[i].ring_bo; ++ ++ cmds[cmd_idx++] = (struct kgsl_command_object) { ++ .offset = 0, ++ .gpuaddr = ring_bo->iova + submit_offset(ring_bo, deferred_primary->offset), ++ .size = deferred_primary->u.cmds[i].size, ++ .flags = KGSL_CMDLIST_IB, ++ .id = ring_bo->handle, ++ }; ++ } ++ ++ if (submit == last_submit(submit_list)) { ++ DEBUG_MSG("merged %u submits", cmd_idx); ++ break; ++ } ++ ++ list_del(&submit->node); ++ fd_submit_del(submit); ++ } ++ ++ struct kgsl_cmd_syncpoint_fence sync_fence = { ++ .fd = fd_submit->in_fence_fd, ++ }; ++ ++ struct kgsl_command_syncpoint sync = { ++ .type = KGSL_CMD_SYNCPOINT_TYPE_FENCE, ++ .size = sizeof(sync_fence), ++ .priv = (uintptr_t) &sync_fence, ++ }; ++ ++ ++ struct kgsl_gpu_command req = { ++ .flags = KGSL_CMDBATCH_SUBMIT_IB_LIST, ++ .context_id = kgsl_pipe->queue_id, ++ .cmdlist = (uintptr_t) cmds, ++ .numcmds = cmd_idx, ++ .cmdsize = sizeof(struct kgsl_command_object), ++ .synclist = (uintptr_t) &sync, ++ .syncsize = sizeof(struct kgsl_command_syncpoint), ++ .numsyncs = sync_fence.fd != -1 ? 1 : 0, ++ }; ++ ++ int ret = kgsl_pipe_safe_ioctl(pipe->dev->fd, IOCTL_KGSL_GPU_COMMAND, &req); ++ ++ if (ret) { ++ ERROR_MSG("submit failed %d (%s)", ret, strerror(errno)); ++ goto fail; ++ } ++ ++ fd_submit->out_fence->kfence = req.timestamp; ++ ++ if (fd_submit->out_fence->use_fence_fd) { ++ int fd = timestamp_to_fd(pipe, req.timestamp); ++ if (fd < 0) { ++ ERROR_MSG("Failed to create sync file for timestamp (%s)", strerror(errno)); ++ goto fail; ++ } ++ ++ fd_submit->out_fence->fence_fd = fd; ++ } ++ ++ if (fd_submit->in_fence_fd != -1) ++ close(fd_submit->in_fence_fd); ++ ++fail: ++ return ret; ++} ++ ++struct fd_submit * ++kgsl_submit_sp_new(struct fd_pipe *pipe) ++{ ++ return fd_submit_sp_new(pipe, flush_submit_list); ++} +diff --git a/src/freedreno/drm/meson.build b/src/freedreno/drm/meson.build +index ffaf6c902e2..24e6b960b1f 100644 +--- a/src/freedreno/drm/meson.build ++++ b/src/freedreno/drm/meson.build +@@ -62,6 +62,17 @@ if freedreno_kmds.contains('virtio') + ] + endif + ++libfreedreno_kgsl_files = files( ++ 'kgsl/kgsl_device.c', ++ 'kgsl/kgsl_bo.c', ++ 'kgsl/kgsl_pipe.c', ++ 'kgsl/kgsl_ringbuffer_sp.c', ++) ++ ++if freedreno_kmds.contains('kgsl') ++ libfreedreno_drm_files += libfreedreno_kgsl_files ++endif ++ + libfreedreno_drm = static_library( + 'freedreno_drm', + [ +-- +2.46.0 + diff --git a/gpkg/mesa/0012-freedreno-drm-Add-more-APIs-to-per-backend-API.patch b/gpkg/mesa/0012-freedreno-drm-Add-more-APIs-to-per-backend-API.patch new file mode 100644 index 000000000..71f5de6f9 --- /dev/null +++ b/gpkg/mesa/0012-freedreno-drm-Add-more-APIs-to-per-backend-API.patch @@ -0,0 +1,266 @@ +From 57893e7b96505c1ca8c30970e8b801f86f910ffe Mon Sep 17 00:00:00 2001 +From: Lucas Fryzek +Date: Mon, 27 Feb 2023 14:50:39 -0500 +Subject: [PATCH 2/2] freedreno/drm: Add more APIs to per backend API + +Add bo_map, bo_from_dmabuf, and bo_close_handle to the per backend +APIs for freedreno/drm. These changes are required to implement +a KGSL backend as part of freedreno/drm. +--- + src/freedreno/drm/freedreno_device.c | 36 +++++++++++++------ + src/freedreno/drm/freedreno_drmif.h | 15 ++++++++ + src/freedreno/drm/freedreno_pipe.c | 6 ++++ + src/freedreno/drm/freedreno_priv.h | 2 ++ + .../drivers/freedreno/freedreno_context.c | 30 ++++++++++++---- + .../drivers/freedreno/freedreno_screen.c | 5 +++ + 6 files changed, 77 insertions(+), 17 deletions(-) + +diff --git a/src/freedreno/drm/freedreno_device.c b/src/freedreno/drm/freedreno_device.c +index ce95c9f5e0a..0d0998eb265 100644 +--- a/src/freedreno/drm/freedreno_device.c ++++ b/src/freedreno/drm/freedreno_device.c +@@ -41,6 +41,9 @@ struct fd_device *msm_device_new(int fd, drmVersionPtr version); + #ifdef HAVE_FREEDRENO_VIRTIO + struct fd_device *virtio_device_new(int fd, drmVersionPtr version); + #endif ++#ifdef HAVE_FREEDRENO_KGSL ++struct fd_device *kgsl_device_new(int fd); ++#endif + + uint64_t os_page_size = 4096; + +@@ -48,19 +51,20 @@ struct fd_device * + fd_device_new(int fd) + { + struct fd_device *dev = NULL; +- drmVersionPtr version; ++ drmVersionPtr version = NULL; + bool use_heap = false; ++ bool support_use_heap = true; + + os_get_page_size(&os_page_size); + ++#ifdef HAVE_LIBDRM + /* figure out if we are kgsl or msm drm driver: */ + version = drmGetVersion(fd); +- if (!version) { +- ERROR_MSG("cannot get version: %s", strerror(errno)); +- return NULL; +- } ++ if (!version) ++ DEBUG_MSG("cannot get version: %s", strerror(errno)); ++#endif + +- if (!strcmp(version->name, "msm")) { ++ if (version && !strcmp(version->name, "msm")) { + DEBUG_MSG("msm DRM device"); + if (version->version_major != 1) { + ERROR_MSG("unsupported version: %u.%u.%u", version->version_major, +@@ -70,7 +74,7 @@ fd_device_new(int fd) + + dev = msm_device_new(fd, version); + #ifdef HAVE_FREEDRENO_VIRTIO +- } else if (!strcmp(version->name, "virtio_gpu")) { ++ } else if (version && !strcmp(version->name, "virtio_gpu")) { + DEBUG_MSG("virtio_gpu DRM device"); + dev = virtio_device_new(fd, version); + /* Only devices that support a hypervisor are a6xx+, so avoid the +@@ -78,10 +82,14 @@ fd_device_new(int fd) + */ + use_heap = true; + #endif +-#if HAVE_FREEDRENO_KGSL +- } else if (!strcmp(version->name, "kgsl")) { +- DEBUG_MSG("kgsl DRM device"); ++#ifdef HAVE_FREEDRENO_KGSL ++ } else { ++ /* If drm driver not detected assume this is KGSL */ + dev = kgsl_device_new(fd); ++ /* Userspace fences are not supported with KGSL */ ++ support_use_heap = false; ++ if (dev) ++ goto out; + #endif + } + +@@ -129,7 +137,7 @@ out: + fd_pipe_del(pipe); + } + +- if (use_heap) { ++ if (support_use_heap && use_heap) { + dev->ring_heap = fd_bo_heap_new(dev, RING_FLAGS); + dev->default_heap = fd_bo_heap_new(dev, 0); + } +@@ -248,6 +256,12 @@ fd_dbg(void) + return debug_get_option_libgl(); + } + ++uint32_t ++fd_get_features(struct fd_device *dev) ++{ ++ return dev->features; ++} ++ + bool + fd_has_syncobj(struct fd_device *dev) + { +diff --git a/src/freedreno/drm/freedreno_drmif.h b/src/freedreno/drm/freedreno_drmif.h +index dd073f201c2..3a5d852d082 100644 +--- a/src/freedreno/drm/freedreno_drmif.h ++++ b/src/freedreno/drm/freedreno_drmif.h +@@ -67,6 +67,13 @@ enum fd_param_id { + FD_VA_SIZE, /* GPU virtual address size */ + }; + ++enum fd_reset_status { ++ FD_RESET_NO_ERROR, ++ FD_RESET_GUILTY, ++ FD_RESET_INNOCENT, ++ FD_RESET_UNKNOWN, ++}; ++ + /** + * Helper for fence/seqno comparisions which deals properly with rollover. + * Returns true if fence 'a' is before fence 'b' +@@ -197,8 +204,15 @@ enum fd_version { + }; + enum fd_version fd_device_version(struct fd_device *dev); + ++enum fd_features { ++ FD_FEATURE_DIRECT_RESET = 1, ++ FD_FEATURE_IMPORT_DMABUF = 2, ++}; ++ ++uint32_t fd_get_features(struct fd_device *dev); + bool fd_has_syncobj(struct fd_device *dev); + ++ + /* pipe functions: + */ + +@@ -218,6 +232,7 @@ int fd_pipe_wait(struct fd_pipe *pipe, const struct fd_fence *fence); + /* timeout in nanosec */ + int fd_pipe_wait_timeout(struct fd_pipe *pipe, const struct fd_fence *fence, + uint64_t timeout); ++int fd_pipe_get_reset_status(struct fd_pipe *pipe, enum fd_reset_status *status); + + /* buffer-object functions: + */ +diff --git a/src/freedreno/drm/freedreno_pipe.c b/src/freedreno/drm/freedreno_pipe.c +index 362e6966376..ea14976545e 100644 +--- a/src/freedreno/drm/freedreno_pipe.c ++++ b/src/freedreno/drm/freedreno_pipe.c +@@ -225,6 +225,12 @@ fd_pipe_emit_fence(struct fd_pipe *pipe, struct fd_ringbuffer *ring) + return fence; + } + ++int ++fd_pipe_get_reset_status(struct fd_pipe *pipe, enum fd_reset_status *status) ++{ ++ return pipe->funcs->reset_status(pipe, status); ++} ++ + struct fd_fence * + fd_fence_new(struct fd_pipe *pipe, bool use_fence_fd) + { +diff --git a/src/freedreno/drm/freedreno_priv.h b/src/freedreno/drm/freedreno_priv.h +index b2e7604026b..e5ec8442ea5 100644 +--- a/src/freedreno/drm/freedreno_priv.h ++++ b/src/freedreno/drm/freedreno_priv.h +@@ -209,6 +209,7 @@ struct fd_device { + int fd; + enum fd_version version; + int32_t refcnt; ++ uint32_t features; + + /* tables to keep track of bo's, to avoid "evil-twin" fd_bo objects: + * +@@ -312,6 +313,7 @@ struct fd_pipe_funcs { + struct fd_ringbuffer *(*ringbuffer_new_object)(struct fd_pipe *pipe, + uint32_t size); + struct fd_submit *(*submit_new)(struct fd_pipe *pipe); ++ int (*reset_status)(struct fd_pipe *pipe, enum fd_reset_status *status); + + /** + * Flush any deferred submits (if deferred submits are supported by +diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c +index ea2a45a2a3c..35c3488ede1 100644 +--- a/src/gallium/drivers/freedreno/freedreno_context.c ++++ b/src/gallium/drivers/freedreno/freedreno_context.c +@@ -497,6 +497,22 @@ fd_get_device_reset_status(struct pipe_context *pctx) + return status; + } + ++static enum pipe_reset_status ++fd_get_device_reset_status_direct(struct pipe_context *pctx) ++{ ++ struct fd_context *ctx = fd_context(pctx); ++ enum pipe_reset_status status_list[] = { ++ [FD_RESET_NO_ERROR] = PIPE_NO_RESET, ++ [FD_RESET_GUILTY] = PIPE_GUILTY_CONTEXT_RESET, ++ [FD_RESET_INNOCENT] = PIPE_INNOCENT_CONTEXT_RESET, ++ [FD_RESET_UNKNOWN] = PIPE_UNKNOWN_CONTEXT_RESET, ++ }; ++ enum fd_reset_status fd_status; ++ ASSERTED int ret = fd_pipe_get_reset_status(ctx->pipe, &fd_status); ++ assert(!ret); ++ return status_list[fd_status]; ++} ++ + static void + fd_trace_record_ts(struct u_trace *ut, void *cs, void *timestamps, + unsigned idx, uint32_t flags) +@@ -662,11 +678,6 @@ fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen, + + ctx->in_fence_fd = -1; + +- if (fd_device_version(screen->dev) >= FD_VERSION_ROBUSTNESS) { +- ctx->context_reset_count = fd_get_reset_count(ctx, true); +- ctx->global_reset_count = fd_get_reset_count(ctx, false); +- } +- + simple_mtx_init(&ctx->gmem_lock, mtx_plain); + + /* need some sane default in case gallium frontends don't +@@ -681,13 +692,20 @@ fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen, + pctx->flush = fd_context_flush; + pctx->emit_string_marker = fd_emit_string_marker; + pctx->set_debug_callback = fd_set_debug_callback; +- pctx->get_device_reset_status = fd_get_device_reset_status; + pctx->create_fence_fd = fd_create_pipe_fence_fd; + pctx->fence_server_sync = fd_pipe_fence_server_sync; + pctx->fence_server_signal = fd_pipe_fence_server_signal; + pctx->texture_barrier = fd_texture_barrier; + pctx->memory_barrier = fd_memory_barrier; + ++ if (fd_get_features(screen->dev) & FD_FEATURE_DIRECT_RESET) { ++ pctx->get_device_reset_status = fd_get_device_reset_status_direct; ++ } else if(fd_device_version(screen->dev) >= FD_VERSION_ROBUSTNESS) { ++ ctx->context_reset_count = fd_get_reset_count(ctx, true); ++ ctx->global_reset_count = fd_get_reset_count(ctx, false); ++ pctx->get_device_reset_status = fd_get_device_reset_status; ++ } ++ + pctx->stream_uploader = u_upload_create_default(pctx); + if (!pctx->stream_uploader) + goto fail; +diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c +index 64a28e955f4..51f1b61b9da 100644 +--- a/src/gallium/drivers/freedreno/freedreno_screen.c ++++ b/src/gallium/drivers/freedreno/freedreno_screen.c +@@ -629,6 +629,11 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) + return 0; + case PIPE_CAP_THROTTLE: + return screen->driconf.enable_throttling; ++ case PIPE_CAP_DMABUF: ++ if (fd_get_features(screen->dev) & FD_FEATURE_IMPORT_DMABUF) ++ return DRM_PRIME_CAP_IMPORT; ++ /* Fallthough to default case */ ++ FALLTHROUGH; + default: + return u_pipe_screen_get_param_defaults(pscreen, param); + } +-- +2.46.0 + diff --git a/gpkg/mesa/0013-fix-bad-syscall.patch b/gpkg/mesa/0013-fix-bad-syscall.patch new file mode 100644 index 000000000..43f9327ed --- /dev/null +++ b/gpkg/mesa/0013-fix-bad-syscall.patch @@ -0,0 +1,13 @@ +diff --git a/src/util/os_file.c b/src/util/os_file.c +index 425c8378c05..1146ee4f538 100644 +--- a/src/util/os_file.c ++++ b/src/util/os_file.c +@@ -224,6 +224,8 @@ typedef void *kvaddr_t; + + #endif /* DETECT_OS_DRAGONFLY || DETECT_OS_FREEBSD */ + ++#undef SYS_kcmp ++ + int + os_same_file_description(int fd1, int fd2) + { diff --git a/gpkg/mesa/0014-freedreno-HACK-GL_ARB_timer_query.patch b/gpkg/mesa/0014-freedreno-HACK-GL_ARB_timer_query.patch new file mode 100644 index 000000000..3aa1b5210 --- /dev/null +++ b/gpkg/mesa/0014-freedreno-HACK-GL_ARB_timer_query.patch @@ -0,0 +1,14 @@ +diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c +index 1c6401aa968..cf45d1def86 100644 +--- a/src/gallium/drivers/freedreno/freedreno_screen.c ++++ b/src/gallium/drivers/freedreno/freedreno_screen.c +@@ -587,8 +587,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) + case PIPE_CAP_QUERY_TIMESTAMP: + case PIPE_CAP_QUERY_TIME_ELAPSED: + /* only a4xx, requires new enough kernel so we know max_freq: */ +- return (screen->max_freq > 0) && +- (is_a4xx(screen) || is_a5xx(screen) || is_a6xx(screen)); ++ return (is_a4xx(screen) || is_a5xx(screen) || is_a6xx(screen)); + case PIPE_CAP_TIMER_RESOLUTION: + return ticks_to_ns(1); + case PIPE_CAP_QUERY_BUFFER_OBJECT: diff --git a/gpkg/mesa/0015-termux-x11-kgsl.patch b/gpkg/mesa/0015-termux-x11-kgsl.patch new file mode 100644 index 000000000..a5aeb2bd0 --- /dev/null +++ b/gpkg/mesa/0015-termux-x11-kgsl.patch @@ -0,0 +1,332 @@ +diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c +index 5857acbcdf3..04a97d0ea59 100644 +--- a/src/egl/drivers/dri2/egl_dri2.c ++++ b/src/egl/drivers/dri2/egl_dri2.c +@@ -994,6 +994,9 @@ dri2_setup_device(_EGLDisplay *disp, EGLBoolean software) + /* If we're not software, we need a DRM node FD */ + assert(software || dri2_dpy->fd_render_gpu >= 0); + ++ if (disp->Options.Kgsl) ++ software = true; ++ + /* fd_render_gpu is what we got from WSI, so might actually be a lie and + * not a render node... */ + if (software) { +diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c +index 39827bbed40..85d7d0267b3 100644 +--- a/src/egl/drivers/dri2/platform_drm.c ++++ b/src/egl/drivers/dri2/platform_drm.c +@@ -586,6 +586,9 @@ dri2_initialize_drm(_EGLDisplay *disp) + + dri2_dpy->fd_display_gpu = + loader_open_device(drm->nodes[DRM_NODE_PRIMARY]); ++ } else if (disp->Options.Kgsl) { ++ dri2_dpy->fd_render_gpu = dri2_dpy->fd_display_gpu = ++ loader_open_device("/dev/kgsl-3d0"); + } else { + _EGLDevice *dev_list = _eglGlobal.DeviceList; + drmDevicePtr drm; +@@ -626,6 +629,8 @@ dri2_initialize_drm(_EGLDisplay *disp) + if (!dri2_dpy->gbm_dri->software) { + dri2_dpy->fd_render_gpu = + get_fd_render_gpu_drm(dri2_dpy->gbm_dri, dri2_dpy->fd_display_gpu); ++ if (dri2_dpy->fd_render_gpu < 0 && disp->Options.Kgsl) ++ dri2_dpy->fd_render_gpu = dri2_dpy->fd_display_gpu; + if (dri2_dpy->fd_render_gpu < 0) { + err = "DRI2: failed to get compatible render device"; + goto cleanup; +diff --git a/src/egl/drivers/dri2/platform_surfaceless.c b/src/egl/drivers/dri2/platform_surfaceless.c +index 2f6e54bd8e0..d895173cefd 100644 +--- a/src/egl/drivers/dri2/platform_surfaceless.c ++++ b/src/egl/drivers/dri2/platform_surfaceless.c +@@ -339,6 +339,20 @@ dri2_initialize_surfaceless(_EGLDisplay *disp) + driver_loaded = surfaceless_probe_device_sw(disp); + } + ++ if (!driver_loaded && disp->Options.Kgsl) { ++ dri2_dpy->fd_render_gpu = loader_open_device("/dev/kgsl-3d0"); ++ dri2_dpy->driver_name = strdup("kgsl"); ++ driver_loaded = dri2_load_driver(disp); ++ 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 (!driver_loaded) { + err = "DRI2: failed to load driver"; + goto cleanup; +diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c +index 18817ad73d1..1d9c6157287 100644 +--- a/src/egl/drivers/dri2/platform_wayland.c ++++ b/src/egl/drivers/dri2/platform_wayland.c +@@ -2264,8 +2264,12 @@ dri2_initialize_wayland_drm(_EGLDisplay *disp) + if (roundtrip(dri2_dpy) < 0) + goto cleanup; + +- if (!dri2_initialize_wayland_drm_extensions(dri2_dpy)) +- goto cleanup; ++ if (!dri2_initialize_wayland_drm_extensions(dri2_dpy)) { ++ if (disp->Options.Kgsl) ++ dri2_dpy->fd_render_gpu = loader_open_device("/dev/kgsl-3d0"); ++ else ++ goto cleanup; ++ } + + loader_get_user_preferred_fd(&dri2_dpy->fd_render_gpu, + &dri2_dpy->fd_display_gpu); +diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c +index b4ffaad498d..b630390a086 100644 +--- a/src/egl/main/eglapi.c ++++ b/src/egl/main/eglapi.c +@@ -687,6 +687,7 @@ eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) + + const char *env = os_get_option("MESA_LOADER_DRIVER_OVERRIDE"); + disp->Options.Zink = env && !strcmp(env, "zink"); ++ disp->Options.Kgsl = env && !strcmp(env, "kgsl"); + + const char *gallium_hud_env = os_get_option("GALLIUM_HUD"); + disp->Options.GalliumHudWarn = +diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h +index 479b26d5f26..ba63a3f69af 100644 +--- a/src/egl/main/egldisplay.h ++++ b/src/egl/main/egldisplay.h +@@ -199,6 +199,7 @@ struct _egl_display { + + /* options that affect how the driver initializes the display */ + struct { ++ EGLBoolean Kgsl; /**< Use kgsl only */ + EGLBoolean Zink; /**< Use kopper only */ + EGLBoolean FallbackZink; /**< True if zink is tried as fallback */ + EGLBoolean ForceSoftware; /**< Use software path only */ +diff --git a/src/loader/loader.c b/src/loader/loader.c +index e9eb4d8b796..a90b4a3df45 100644 +--- a/src/loader/loader.c ++++ b/src/loader/loader.c +@@ -647,6 +647,10 @@ loader_get_linux_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) + bool + loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) + { ++ const char *env = getenv("MESA_LOADER_DRIVER_OVERRIDE"); ++ if (env && !strcmp(env, "kgsl")) ++ return false; ++ + #ifdef __linux__ + /* Implementation without causing full enumeration of DRM devices. */ + if (loader_get_linux_pci_id_for_fd(fd, vendor_id, chip_id)) +diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c +index 6375143e290..dbfbd726c40 100644 +--- a/src/loader/loader_dri3_helper.c ++++ b/src/loader/loader_dri3_helper.c +@@ -26,14 +26,13 @@ + #include + #include + +-#include + #include + #include + #include +-#include + + #include + ++#include + #include "loader_dri_helper.h" + #include "loader_dri3_helper.h" + #include "util/macros.h" +@@ -239,13 +238,11 @@ loader_dri3_blit_image(struct loader_dri3_drawable *draw, + static inline void + dri3_fence_reset(xcb_connection_t *c, struct loader_dri3_buffer *buffer) + { +- xshmfence_reset(buffer->shm_fence); + } + + static inline void + dri3_fence_set(struct loader_dri3_buffer *buffer) + { +- xshmfence_trigger(buffer->shm_fence); + } + + static inline void +@@ -259,7 +256,6 @@ dri3_fence_await(xcb_connection_t *c, struct loader_dri3_drawable *draw, + struct loader_dri3_buffer *buffer) + { + xcb_flush(c); +- xshmfence_await(buffer->shm_fence); + if (draw) { + mtx_lock(&draw->mtx); + dri3_flush_present_events(draw); +@@ -335,8 +331,6 @@ dri3_free_render_buffer(struct loader_dri3_drawable *draw, + + if (buffer->own_pixmap) + xcb_free_pixmap(draw->conn, buffer->pixmap); +- xcb_sync_destroy_fence(draw->conn, buffer->sync_fence); +- xshmfence_unmap_shm(buffer->shm_fence); + draw->ext->image->destroyImage(buffer->image); + if (buffer->linear_buffer) + draw->ext->image->destroyImage(buffer->linear_buffer); +@@ -1141,26 +1135,7 @@ loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw, + back->busy = 1; + back->last_swap = draw->send_sbc; + +- if (!draw->region) { +- draw->region = xcb_generate_id(draw->conn); +- xcb_xfixes_create_region(draw->conn, draw->region, 0, NULL); +- } +- + xcb_xfixes_region_t region = 0; +- xcb_rectangle_t xcb_rects[64]; +- +- if (n_rects > 0 && n_rects <= ARRAY_SIZE(xcb_rects)) { +- for (int i = 0; i < n_rects; i++) { +- const int *rect = &rects[i * 4]; +- xcb_rects[i].x = rect[0]; +- xcb_rects[i].y = draw->height - rect[1] - rect[3]; +- xcb_rects[i].width = rect[2]; +- xcb_rects[i].height = rect[3]; +- } +- +- region = draw->region; +- xcb_xfixes_set_region(draw->conn, region, n_rects, xcb_rects); +- } + + xcb_present_pixmap(draw->conn, + draw->drawable, +@@ -1292,6 +1267,10 @@ loader_dri3_open(xcb_connection_t *conn, + int fd; + const xcb_query_extension_reply_t *extension; + ++ const char *env = getenv("MESA_LOADER_DRIVER_OVERRIDE"); ++ if (env && !strcmp(env, "kgsl")) ++ return loader_open_device("/dev/kgsl-3d0"); ++ + xcb_prefetch_extension_data(conn, &xcb_dri3_id); + extension = xcb_get_extension_data(conn, &xcb_dri3_id); + if (!(extension && extension->present)) +@@ -1439,27 +1418,13 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int fourcc, + __DRIimage *pixmap_buffer = NULL, *linear_buffer_display_gpu = NULL; + int format = loader_fourcc_to_image_format(fourcc); + xcb_pixmap_t pixmap; +- xcb_sync_fence_t sync_fence; +- struct xshmfence *shm_fence; +- int buffer_fds[4], fence_fd; ++ int buffer_fds[4]; + int num_planes = 0; + uint64_t *modifiers = NULL; + uint32_t count = 0; + int i, mod; + int ret; + +- /* Create an xshmfence object and +- * prepare to send that to the X server +- */ +- +- fence_fd = xshmfence_alloc_shm(); +- if (fence_fd < 0) +- return NULL; +- +- shm_fence = xshmfence_map_shm(fence_fd); +- if (shm_fence == NULL) +- goto no_shm_fence; +- + /* Allocate the image from the driver + */ + buffer = calloc(1, sizeof *buffer); +@@ -1658,7 +1623,7 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int fourcc, + buffer->strides[2], buffer->offsets[2], + buffer->strides[3], buffer->offsets[3], + depth, buffer->cpp * 8, +- buffer->modifier, ++ buffer->modifier ? buffer->modifier : 1274, + buffer_fds); + } else + #endif +@@ -1672,16 +1637,8 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int fourcc, + buffer_fds[0]); + } + +- xcb_dri3_fence_from_fd(draw->conn, +- pixmap, +- (sync_fence = xcb_generate_id(draw->conn)), +- false, +- fence_fd); +- + buffer->pixmap = pixmap; + buffer->own_pixmap = true; +- buffer->sync_fence = sync_fence; +- buffer->shm_fence = shm_fence; + buffer->width = width; + buffer->height = height; + +@@ -1703,9 +1660,6 @@ no_linear_buffer: + no_image: + free(buffer); + no_buffer: +- xshmfence_unmap_shm(shm_fence); +-no_shm_fence: +- close(fence_fd); + return NULL; + } + +@@ -1935,11 +1889,8 @@ dri3_get_pixmap_buffer(__DRIdrawable *driDrawable, unsigned int fourcc, + int buf_id = loader_dri3_pixmap_buf_id(buffer_type); + struct loader_dri3_buffer *buffer = draw->buffers[buf_id]; + xcb_drawable_t pixmap; +- xcb_sync_fence_t sync_fence; +- struct xshmfence *shm_fence; + int width; + int height; +- int fence_fd; + __DRIscreen *cur_screen; + + if (buffer) +@@ -1951,15 +1902,6 @@ dri3_get_pixmap_buffer(__DRIdrawable *driDrawable, unsigned int fourcc, + if (!buffer) + goto no_buffer; + +- fence_fd = xshmfence_alloc_shm(); +- if (fence_fd < 0) +- goto no_fence; +- shm_fence = xshmfence_map_shm(fence_fd); +- if (shm_fence == NULL) { +- close (fence_fd); +- goto no_fence; +- } +- + /* Get the currently-bound screen or revert to using the drawable's screen if + * no contexts are currently bound. The latter case is at least necessary for + * obs-studio, when using Window Capture (Xcomposite) as a Source. +@@ -1969,11 +1911,6 @@ dri3_get_pixmap_buffer(__DRIdrawable *driDrawable, unsigned int fourcc, + cur_screen = draw->dri_screen_render_gpu; + } + +- xcb_dri3_fence_from_fd(draw->conn, +- pixmap, +- (sync_fence = xcb_generate_id(draw->conn)), +- false, +- fence_fd); + #ifdef HAVE_DRI3_MODIFIERS + if (draw->multiplanes_available && + draw->ext->image->base.version >= 15 && +@@ -2019,17 +1956,12 @@ dri3_get_pixmap_buffer(__DRIdrawable *driDrawable, unsigned int fourcc, + buffer->own_pixmap = false; + buffer->width = width; + buffer->height = height; +- buffer->shm_fence = shm_fence; +- buffer->sync_fence = sync_fence; + + dri3_set_render_buffer(draw, buf_id, buffer); + + return buffer; + + no_image: +- xcb_sync_destroy_fence(draw->conn, sync_fence); +- xshmfence_unmap_shm(shm_fence); +-no_fence: + free(buffer); + no_buffer: + return NULL; diff --git a/gpkg/mesa/build.sh b/gpkg/mesa/build.sh index 341e08c20..4f9f4568f 100644 --- a/gpkg/mesa/build.sh +++ b/gpkg/mesa/build.sh @@ -3,13 +3,13 @@ TERMUX_PKG_DESCRIPTION="An open-source implementation of the OpenGL specificatio TERMUX_PKG_LICENSE="MIT" TERMUX_PKG_LICENSE_FILE="docs/license.rst" TERMUX_PKG_MAINTAINER="@termux-pacman" -TERMUX_PKG_VERSION="24.1.4" +TERMUX_PKG_VERSION="24.2.4" TERMUX_PKG_SRCURL=https://archive.mesa3d.org/mesa-${TERMUX_PKG_VERSION}.tar.xz -TERMUX_PKG_SHA256=7cf7c6f665263ad0122889c1d4b076654c1eedea7a2f38c69c8c51579937ade1 +TERMUX_PKG_SHA256=5ea42a8bb6d58aec9754c9f553b1e413f67c09403741f8e2786c3f9e63d3461a TERMUX_PKG_DEPENDS="libglvnd-glibc, gcc-libs-glibc, libdrm-glibc, libllvm-glibc, libexpat-glibc, zlib-glibc, zstd-glibc, libx11-glibc, libxcb-glibc, libxext-glibc, libxfixes-glibc, libxshmfence-glibc, libxxf86vm-glibc, libwayland-glibc, libvdpau-glibc, libomxil-bellagio-glibc, libva-glibc, libxml2-glibc, libelf-glibc, libbz2-glibc, libclc-glibc" TERMUX_PKG_SUGGESTS="mesa-dev-glibc" TERMUX_PKG_BUILD_DEPENDS="llvm-glibc, libwayland-protocols-glibc, xorgproto-glibc, glslang-glibc" -TERMUX_PKG_PYTHON_COMMON_DEPS="mako, setuptools" +TERMUX_PKG_PYTHON_COMMON_DEPS="mako, setuptools, pyyaml" # disabling libunwind, microsoft-clc and valgrind will improve performance TERMUX_PKG_EXTRA_CONFIGURE_ARGS=" @@ -18,7 +18,7 @@ TERMUX_PKG_EXTRA_CONFIGURE_ARGS=" -D dri3=enabled -D egl=enabled -D gallium-opencl=icd --D gallium-drivers=freedreno,swrast,virgl,zink,r600,radeonsi,nouveau,lima,panfrost,kmsro +-D gallium-drivers=freedreno,swrast,virgl,zink,r600,radeonsi,nouveau,lima,panfrost -D gallium-extra-hud=true -D gallium-nine=true -D gallium-va=enabled diff --git a/gpkg/mesa/gallium-targets-dri-meson-build.patch b/gpkg/mesa/gallium-targets-dri-meson-build.patch deleted file mode 100644 index ba8e81fa0..000000000 --- a/gpkg/mesa/gallium-targets-dri-meson-build.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- src/src/gallium/targets/dri/meson.build 2024-07-03 17:51:12.000000000 +0300 -+++ src/src/gallium/targets/dri/meson.build.patch 2024-07-14 00:07:59.742357536 +0300 -@@ -143,7 +143,7 @@ - 'devenv_@0@'.format(d), - input : libgallium_dri, - output : d, -- command : [prog_ln, '-f', '@INPUT@', '@OUTPUT@'], -+ command : [prog_ln, '-fs', '@INPUT@', '@OUTPUT@'], - build_by_default : true, - ) - endforeach diff --git a/gpkg/python/build.sh b/gpkg/python/build.sh index a4e34b9bc..470424d85 100644 --- a/gpkg/python/build.sh +++ b/gpkg/python/build.sh @@ -3,13 +3,12 @@ TERMUX_PKG_DESCRIPTION="The Python programming language" TERMUX_PKG_LICENSE="custom" TERMUX_PKG_LICENSE_FILE="LICENSE" TERMUX_PKG_MAINTAINER="@termux-pacman" -TERMUX_PKG_VERSION=3.12.6 -TERMUX_PKG_REVISION=1 +TERMUX_PKG_VERSION=3.12.7 _MAJOR_VERSION="${TERMUX_PKG_VERSION%.*}" _SETUPTOOLS_VERSION=69.5.1 TERMUX_PKG_SRCURL=(https://www.python.org/ftp/python/${TERMUX_PKG_VERSION%rc*}/Python-${TERMUX_PKG_VERSION}.tar.xz https://github.com/pypa/setuptools/archive/refs/tags/v${_SETUPTOOLS_VERSION}.tar.gz) -TERMUX_PKG_SHA256=(1999658298cf2fb837dffed8ff3c033ef0c98ef20cf73c5d5f66bed5ab89697c +TERMUX_PKG_SHA256=(24887b92e2afd4a2ac602419ad4b596372f67ac9b077190f459aba390faf5550 2cf4ea407b1325c2c85862d13eb31f9b57098b0ae7f94e2258aea4e634f6534f) TERMUX_PKG_DEPENDS="libbz2-glibc, libexpat-glibc, gdbm-glibc, libffi-glibc, libnsl-glibc, libxcrypt-glibc, openssl-glibc, zlib-glibc" TERMUX_PKG_BUILD_DEPENDS="sqlite-glibc, mpdecimal-glibc, llvm-glibc" diff --git a/gpkg/vulkan-headers/build.sh b/gpkg/vulkan-headers/build.sh index 35447aeb4..078eddeda 100644 --- a/gpkg/vulkan-headers/build.sh +++ b/gpkg/vulkan-headers/build.sh @@ -2,7 +2,7 @@ TERMUX_PKG_HOMEPAGE=https://github.com/KhronosGroup/Vulkan-Headers TERMUX_PKG_DESCRIPTION="Vulkan Header files and API registry" TERMUX_PKG_LICENSE="Apache-2.0" TERMUX_PKG_MAINTAINER="@termux-pacman" -TERMUX_PKG_VERSION="1.3.296" +TERMUX_PKG_VERSION="1.3.297" TERMUX_PKG_SRCURL=https://github.com/KhronosGroup/Vulkan-Headers/archive/v${TERMUX_PKG_VERSION}.tar.gz -TERMUX_PKG_SHA256=e204e0b3c19f622d197df945737f5db913d6621830999b8578d34e80a7c90585 +TERMUX_PKG_SHA256=1d679e2edc43cb7ad818b81dea960e374f1d6dd082325eb9b4c6113e76263c02 TERMUX_PKG_PLATFORM_INDEPENDENT=true