diff --git a/local/recipes/libs/libdrm/recipe.toml b/local/recipes/libs/libdrm/recipe.toml index 1582a49d0d..b050119bcb 100644 --- a/local/recipes/libs/libdrm/recipe.toml +++ b/local/recipes/libs/libdrm/recipe.toml @@ -1,7 +1,31 @@ +# 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. +# +# 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. +# +# 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] -tar = "https://gitlab.freedesktop.org/mesa/libdrm/-/archive/libdrm-2.4.125/libdrm-libdrm-2.4.125.tar.gz" -blake3 = "33e6448252639f4ff8a8cd30129b335c5d85356c1c93f8d77a79221003b14f66" -patches = ["redox.patch", "../../../local/patches/libdrm/P1-drm-ioctl-bridge.patch", "../../../local/patches/libdrm/P2-drm-get-pci-info.patch", "../../../local/patches/libdrm/P3-drm-get-version-driver-name.patch", "../../../local/patches/libdrm/P4-drmGetDeviceFromDevId-redox.patch"] +path = "../../../../local/sources/libdrm" [build] template = "meson" @@ -14,3 +38,7 @@ mesonflags = [ "-Dtests=false", "-Dc_args=-Wno-unused-function", ] + +[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/." diff --git a/local/recipes/libs/libdrm/redox.patch b/local/recipes/libs/libdrm/redox.patch deleted file mode 100644 index 0508c8ed20..0000000000 --- a/local/recipes/libs/libdrm/redox.patch +++ /dev/null @@ -1,1542 +0,0 @@ -diff -ruN source-old/include/drm/drm.h source/include/drm/drm.h ---- source-old/include/drm/drm.h -+++ source/include/drm/drm.h -@@ -44,7 +44,11 @@ - #else /* One of the BSDs */ - - #include -+#if defined(__redox__) -+#include -+#else - #include -+#endif - #include - typedef int8_t __s8; - typedef uint8_t __u8; -diff -ruN source-old/xf86drm.c source/xf86drm.c ---- source-old/xf86drm.c -+++ source/xf86drm.c -@@ -57,6 +57,19 @@ - #ifdef MAJOR_IN_SYSMACROS - #include - #endif -+#if defined(__redox__) -+// From musl sys/sysmacros.h -+#define major(x) \ -+ ((unsigned)( (((x)>>31>>1) & 0xfffff000) | (((x)>>8) & 0x00000fff) )) -+#define minor(x) \ -+ ((unsigned)( (((x)>>12) & 0xffffff00) | ((x) & 0x000000ff) )) -+ -+#define makedev(x,y) ( \ -+ (((x)&0xfffff000ULL) << 32) | \ -+ (((x)&0x00000fffULL) << 8) | \ -+ (((y)&0xffffff00ULL) << 12) | \ -+ (((y)&0x000000ffULL)) ) -+#endif - #if HAVE_SYS_SYSCTL_H - #include - #endif -@@ -75,6 +88,7 @@ - #endif - - #include "xf86drm.h" -+#include "xf86drm_redox.h" - #include "libdrm_macros.h" - #include "drm_fourcc.h" - -@@ -300,13 +314,18 @@ - uint64_t type = (modifier >> 52) & 0xf; - - FILE *fp; -- size_t size = 0; - char *modifier_name = NULL; - bool result = false; - -+#if defined(__redox__) -+ fprintf(stderr, "open_memstream not available on Redox\n"); -+ return NULL; -+#else -+ size_t size = 0; - fp = open_memstream(&modifier_name, &size); - if (!fp) - return NULL; -+#endif - - switch (type) { - case DRM_FORMAT_MOD_ARM_TYPE_AFBC: -@@ -407,11 +426,16 @@ - uint64_t tile_version = AMD_FMT_MOD_GET(TILE_VERSION, modifier); - FILE *fp; - char *mod_amd = NULL; -- size_t size = 0; - -+#if defined(__redox__) -+ fprintf(stderr, "open_memstream not available on Redox\n"); -+ return NULL; -+#else -+ size_t size = 0; - fp = open_memstream(&mod_amd, &size); - if (!fp) - return NULL; -+#endif - - switch (tile_version) { - case AMD_FMT_MOD_TILE_VER_GFX9: -@@ -680,18 +704,259 @@ - free(pt); - } - -+#if defined(__redox__) -+static int redox_drm_write_all(int fd, const void *buf, size_t len) -+{ -+ const uint8_t *bytes = buf; -+ size_t offset = 0; -+ -+ while (offset < len) { -+ ssize_t written = write(fd, bytes + offset, len - offset); -+ if (written < 0) { -+ if (errno == EINTR || errno == EAGAIN) -+ continue; -+ return -1; -+ } -+ if (written == 0) { -+ errno = EIO; -+ return -1; -+ } -+ offset += (size_t)written; -+ } -+ -+ return 0; -+} -+ -+static int redox_drm_read_all(int fd, void *buf, size_t len) -+{ -+ uint8_t *bytes = buf; -+ size_t offset = 0; -+ -+ while (offset < len) { -+ ssize_t read_count = read(fd, bytes + offset, len - offset); -+ if (read_count < 0) { -+ if (errno == EINTR || errno == EAGAIN) -+ continue; -+ return -1; -+ } -+ if (read_count == 0) { -+ errno = EIO; -+ return -1; -+ } -+ offset += (size_t)read_count; -+ } -+ -+ return 0; -+} -+ -+static int redox_drm_send_request(int fd, unsigned long request_code, -+ const void *payload, size_t payload_size) -+{ -+ const size_t request_word_size = sizeof(uintptr_t); -+ const size_t total_size = request_word_size + payload_size; -+ uint8_t stack_request[sizeof(uintptr_t)]; -+ uint8_t *request_bytes = stack_request; -+ uintptr_t request_word = (uintptr_t)request_code; -+ size_t i; -+ -+ if (total_size > sizeof(stack_request)) { -+ request_bytes = drmMalloc(total_size); -+ if (!request_bytes) { -+ errno = ENOMEM; -+ return -1; -+ } -+ } -+ -+ for (i = 0; i < request_word_size; ++i) -+ request_bytes[i] = (uint8_t)((request_word >> (i * 8)) & 0xffU); -+ -+ if (payload_size != 0) -+ memcpy(request_bytes + request_word_size, payload, payload_size); -+ -+ if (redox_drm_write_all(fd, request_bytes, total_size) != 0) { -+ if (request_bytes != stack_request) -+ drmFree(request_bytes); -+ return -1; -+ } -+ -+ if (request_bytes != stack_request) -+ drmFree(request_bytes); -+ -+ return 0; -+} -+ -+static int redox_drm_get_response_size(int fd, size_t *response_size) -+{ -+ stat_t st; -+ -+ if (fstat(fd, &st) != 0) -+ return -1; -+ -+ *response_size = (size_t)st.st_size; -+ return 0; -+} -+ -+unsigned long redox_translate_request(unsigned long linux_nr) -+{ -+ switch (linux_nr) { -+ case 0x0C: -+ return REDOX_DRM_IOCTL_GET_CAP; -+ case 0x0D: -+ return REDOX_DRM_IOCTL_SET_CLIENT_CAP; -+ case 0x09: -+ return REDOX_DRM_IOCTL_GEM_CLOSE; -+ case 0xA6: -+ return REDOX_DRM_IOCTL_MODE_GETENCODER; -+ case 0xB3: -+ return REDOX_DRM_IOCTL_MODE_MAP_DUMB; -+ case 0xB4: -+ return REDOX_DRM_IOCTL_MODE_DESTROY_DUMB; -+ case 0xAF: -+ return REDOX_DRM_IOCTL_MODE_RMFB; -+ default: -+ return 0; -+ } -+} -+ -+int redox_drm_exchange(int fd, unsigned long request_code, -+ const void *payload, size_t payload_size, -+ void *response, size_t response_capacity, -+ size_t *response_size) -+{ -+ uint8_t stack_buffer[64]; -+ uint8_t *response_buffer = stack_buffer; -+ size_t actual_response_size = 0; -+ -+ if (redox_drm_send_request(fd, request_code, payload, payload_size) != 0) -+ return -1; -+ -+ if (redox_drm_get_response_size(fd, &actual_response_size) != 0) -+ return -1; -+ -+ if (response_size) -+ *response_size = actual_response_size; -+ -+ if (actual_response_size == 0) -+ return 0; -+ -+ if (response && response_capacity >= actual_response_size) { -+ return redox_drm_read_all(fd, response, actual_response_size); -+ } -+ -+ if (actual_response_size > sizeof(stack_buffer)) { -+ response_buffer = drmMalloc(actual_response_size); -+ if (!response_buffer) { -+ errno = ENOMEM; -+ return -1; -+ } -+ } -+ -+ if (redox_drm_read_all(fd, response_buffer, actual_response_size) != 0) { -+ if (response_buffer != stack_buffer) -+ drmFree(response_buffer); -+ return -1; -+ } -+ -+ if (response_buffer != stack_buffer) -+ drmFree(response_buffer); -+ -+ if (response && response_capacity < actual_response_size) { -+ errno = EMSGSIZE; -+ return -1; -+ } -+ -+ return 0; -+} -+ -+int redox_drm_exchange_alloc(int fd, unsigned long request_code, -+ const void *payload, size_t payload_size, -+ void **response, size_t *response_size) -+{ -+ size_t actual_response_size = 0; -+ void *allocated_response = NULL; -+ -+ if (!response) { -+ errno = EINVAL; -+ return -1; -+ } -+ -+ if (redox_drm_send_request(fd, request_code, payload, payload_size) != 0) -+ return -1; -+ -+ if (redox_drm_get_response_size(fd, &actual_response_size) != 0) -+ return -1; -+ -+ if (actual_response_size != 0) { -+ allocated_response = drmMalloc(actual_response_size); -+ if (!allocated_response) { -+ errno = ENOMEM; -+ return -1; -+ } -+ -+ if (redox_drm_read_all(fd, allocated_response, actual_response_size) != 0) { -+ drmFree(allocated_response); -+ return -1; -+ } -+ } -+ -+ *response = allocated_response; -+ if (response_size) -+ *response_size = actual_response_size; -+ return 0; -+} -+ -+static size_t redox_drm_expected_response_size(unsigned long linux_nr, size_t arg_size) -+{ -+ switch (linux_nr) { -+ case 0x0C: -+ case 0xA6: -+ case 0xB3: -+ return arg_size; -+ default: -+ return 0; -+ } -+} -+ -+int redox_drm_simple_ioctl(int fd, unsigned long request, void *arg) -+{ -+ const unsigned long linux_nr = REDOX_LINUX_IOCTL_NR(request); -+ const unsigned long request_code = redox_translate_request(linux_nr); -+ const size_t arg_size = REDOX_LINUX_IOCTL_SIZE(request); -+ const size_t expected_response_size = redox_drm_expected_response_size(linux_nr, arg_size); -+ -+ if (request_code == 0) { -+ errno = ENOTTY; -+ return -1; -+ } -+ -+ if (redox_drm_exchange(fd, request_code, -+ arg, arg ? arg_size : 0, -+ expected_response_size ? arg : NULL, -+ expected_response_size, -+ NULL) != 0) { -+ return -1; -+ } -+ -+ return 0; -+} -+#endif -+ - /** - * Call ioctl, restarting if it is interrupted - */ - drm_public int - drmIoctl(int fd, unsigned long request, void *arg) - { -+ #if defined(__redox__) -+ return redox_drm_simple_ioctl(fd, request, arg); -+ #else - int ret; - - do { - ret = ioctl(fd, request, arg); - } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); - return ret; -+ #endif - } - - static unsigned long drmGetKeyFromFd(int fd) -@@ -823,6 +1088,21 @@ - return NULL; - } - -+static int drmGetNodePath(char *buf, size_t buf_len, int type, int minor) -+{ -+ const char *dev_name = drmGetDeviceName(type); -+ -+#if defined(__redox__) -+ if (type == DRM_NODE_RENDER) -+ return snprintf(buf, buf_len, "%s/" DRM_RENDER_MINOR_NAME, DRM_DIR_NAME); -+#endif -+ -+ if (!dev_name) -+ return -1; -+ -+ return snprintf(buf, buf_len, dev_name, DRM_DIR_NAME, minor); -+} -+ - /** - * Open the DRM device, creating it if necessary. - * -@@ -839,7 +1119,6 @@ - static int drmOpenDevice(dev_t dev, int minor, int type) - { - stat_t st; -- const char *dev_name = drmGetDeviceName(type); - char buf[DRM_NODE_NAME_MAX]; - int fd; - mode_t devmode = DRM_DEV_MODE, serv_mode; -@@ -850,10 +1129,8 @@ - gid_t group = DRM_DEV_GID; - #endif - -- if (!dev_name) -+ if (drmGetNodePath(buf, sizeof(buf), type, minor) < 0) - return -EINVAL; -- -- sprintf(buf, dev_name, DRM_DIR_NAME, minor); - drmMsg("drmOpenDevice: node name is %s\n", buf); - - if (drm_server_info && drm_server_info->get_perms) { -@@ -958,15 +1235,13 @@ - { - int fd; - char buf[DRM_NODE_NAME_MAX]; -- const char *dev_name = drmGetDeviceName(type); - - if (create) - return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type); - -- if (!dev_name) -+ if (drmGetNodePath(buf, sizeof(buf), type, minor) < 0) - return -EINVAL; - -- sprintf(buf, dev_name, DRM_DIR_NAME, minor); - if ((fd = open(buf, O_RDWR | O_CLOEXEC)) >= 0) - return fd; - return -errno; -@@ -1060,6 +1335,7 @@ - return -1; - } - -+#if !defined(__redox__) - static const char *drmGetMinorName(int type) - { - switch (type) { -@@ -1071,6 +1347,7 @@ - return NULL; - } - } -+#endif - - /** - * Open the device by bus ID. -@@ -1168,7 +1445,11 @@ - for (i = base; i < base + DRM_MAX_MINOR; i++) { - if ((fd = drmOpenMinor(i, 1, type)) >= 0) { - if ((version = drmGetVersion(fd))) { -+ #if defined(__redox__) -+ if (!version->name || !strcmp(version->name, name)) { -+ #else - if (!strcmp(version->name, name)) { -+ #endif - drmFreeVersion(version); - id = drmGetBusid(fd); - drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL"); -@@ -1321,6 +1602,7 @@ - * Used by drmGetVersion() to free the memory pointed by \p %v as well as all - * the non-null strings pointers in it. - */ -+#if !defined(__redox__) - static void drmFreeKernelVersion(drm_version_t *v) - { - if (!v) -@@ -1330,6 +1612,7 @@ - drmFree(v->desc); - drmFree(v); - } -+#endif - - - /** -@@ -1342,6 +1625,7 @@ - * Used by drmGetVersion() to translate the information returned by the ioctl - * interface in a private structure into the public structure counterpart. - */ -+#if !defined(__redox__) - static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s) - { - d->version_major = s->version_major; -@@ -1354,6 +1638,7 @@ - d->desc_len = s->desc_len; - d->desc = s->desc ? strdup(s->desc) : NULL; - } -+#endif - - - /** -@@ -1373,6 +1658,27 @@ - */ - drm_public drmVersionPtr drmGetVersion(int fd) - { -+ #if defined(__redox__) -+ drmVersionPtr retval = drmMalloc(sizeof(*retval)); -+ struct redox_drm_version_wire version; -+ -+ if (!retval) -+ return NULL; -+ -+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_VERSION, -+ NULL, 0, -+ &version, sizeof(version), -+ NULL) != 0) { -+ drmFree(retval); -+ return NULL; -+ } -+ -+ memclear(*retval); -+ retval->version_major = version.major; -+ retval->version_minor = version.minor; -+ retval->version_patchlevel = version.patch; -+ return retval; -+ #else - drmVersionPtr retval; - drm_version_t *version = drmMalloc(sizeof(*version)); - -@@ -1403,6 +1709,7 @@ - drmCopyVersion(retval, version); - drmFreeKernelVersion(version); - return retval; -+ #endif - } - - -@@ -3306,7 +3613,8 @@ - d = sbuf.st_rdev; - - for (i = 0; i < DRM_MAX_MINOR; i++) { -- snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i); -+ if (drmGetNodePath(name, sizeof(name), DRM_NODE_PRIMARY, i) < 0) -+ return NULL; - if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d) - break; - } -@@ -3366,6 +3674,23 @@ - drm_public int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, - int *prime_fd) - { -+ #if defined(__redox__) -+ struct redox_drm_prime_handle_to_fd_wire request; -+ struct redox_drm_prime_handle_to_fd_response_wire response; -+ -+ memclear(request); -+ request.handle = handle; -+ request.flags = flags; -+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_PRIME_HANDLE_TO_FD, -+ &request, sizeof(request), -+ &response, sizeof(response), -+ NULL) != 0) { -+ return -errno; -+ } -+ -+ *prime_fd = response.fd; -+ return 0; -+ #else - struct drm_prime_handle args; - int ret; - -@@ -3379,10 +3704,27 @@ - - *prime_fd = args.fd; - return 0; -+ #endif - } - - drm_public int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle) - { -+ #if defined(__redox__) -+ struct redox_drm_prime_fd_to_handle_wire request; -+ struct redox_drm_prime_fd_to_handle_response_wire response; -+ -+ memclear(request); -+ request.fd = prime_fd; -+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_PRIME_FD_TO_HANDLE, -+ &request, sizeof(request), -+ &response, sizeof(response), -+ NULL) != 0) { -+ return -errno; -+ } -+ -+ *handle = response.handle; -+ return 0; -+ #else - struct drm_prime_handle args; - int ret; - -@@ -3394,6 +3736,7 @@ - - *handle = args.handle; - return 0; -+ #endif - } - - drm_public int drmCloseBufferHandle(int fd, uint32_t handle) -@@ -3495,7 +3838,6 @@ - #else - struct stat sbuf; - char buf[PATH_MAX + 1]; -- const char *dev_name = drmGetDeviceName(type); - unsigned int maj, min; - int n; - -@@ -3508,11 +3850,10 @@ - if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode)) - return NULL; - -- if (!dev_name) -+ n = drmGetNodePath(buf, sizeof(buf), type, min); -+ if (n < 0) - return NULL; -- -- n = snprintf(buf, sizeof(buf), dev_name, DRM_DIR_NAME, min); -- if (n == -1 || n >= sizeof(buf)) -+ if ((size_t)n >= sizeof(buf)) - return NULL; - - return strdup(buf); -@@ -4877,7 +5218,6 @@ - #else - struct stat sbuf; - char node[PATH_MAX + 1]; -- const char *dev_name; - int node_type; - int maj, min, n; - -@@ -4894,12 +5234,8 @@ - if (node_type == -1) - return NULL; - -- dev_name = drmGetDeviceName(node_type); -- if (!dev_name) -- return NULL; -- -- n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min); -- if (n == -1 || n >= PATH_MAX) -+ n = drmGetNodePath(node, sizeof(node), node_type, min); -+ if (n < 0 || n >= PATH_MAX) - return NULL; - - return strdup(node); -diff -ruN source-old/xf86drm.h source/xf86drm.h ---- source-old/xf86drm.h -+++ source/xf86drm.h -@@ -47,7 +47,7 @@ - #define DRM_MAX_MINOR 64 /* deprecated */ - #endif - --#if defined(__linux__) -+#if defined(__linux__) || defined(__redox__) - - #define DRM_IOCTL_NR(n) _IOC_NR(n) - #define DRM_IOC_VOID _IOC_NONE -@@ -81,6 +81,12 @@ - #define DRM_PRIMARY_MINOR_NAME "drm" - #define DRM_CONTROL_MINOR_NAME "drmC" /* deprecated */ - #define DRM_RENDER_MINOR_NAME "drmR" -+#elif defined(__redox__) -+#define DRM_DIR_NAME "/scheme/drm" -+#define DRM_PRIMARY_MINOR_NAME "card" -+#define DRM_CONTROL_MINOR_NAME "controlD" /* deprecated */ -+#define DRM_RENDER_MINOR_NAME "renderD" -+#define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */ - #else - #define DRM_DIR_NAME "/dev/dri" - #define DRM_PRIMARY_MINOR_NAME "card" -diff -ruN source-old/xf86drmMode.c source/xf86drmMode.c ---- source-old/xf86drmMode.c -+++ source/xf86drmMode.c -@@ -50,6 +50,7 @@ - #include "libdrm_macros.h" - #include "xf86drmMode.h" - #include "xf86drm.h" -+#include "xf86drm_redox.h" - #include - #include - #include -@@ -68,6 +69,212 @@ - return ret < 0 ? -errno : ret; - } - -+static void* drmAllocCpy(char *array, int count, int entry_size); -+ -+#if defined(__redox__) -+static void redox_drm_mode_from_wire(drmModeModeInfoPtr mode, -+ const struct redox_drm_mode_wire *wire, -+ const char *name) -+{ -+ memclear(*mode); -+ mode->clock = wire->clock; -+ mode->hdisplay = wire->hdisplay; -+ mode->hsync_start = wire->hsync_start; -+ mode->hsync_end = wire->hsync_end; -+ mode->htotal = wire->htotal; -+ mode->hskew = wire->hskew; -+ mode->vdisplay = wire->vdisplay; -+ mode->vsync_start = wire->vsync_start; -+ mode->vsync_end = wire->vsync_end; -+ mode->vtotal = wire->vtotal; -+ mode->vscan = wire->vscan; -+ mode->vrefresh = wire->vrefresh; -+ mode->flags = wire->flags; -+ mode->type = wire->type; -+ if (name) { -+ size_t name_len = strlen(name); -+ if (name_len >= DRM_DISPLAY_MODE_LEN) -+ name_len = DRM_DISPLAY_MODE_LEN - 1; -+ memcpy(mode->name, name, name_len); -+ } -+} -+ -+static void redox_drm_mode_to_wire(struct redox_drm_mode_wire *wire, -+ const drmModeModeInfo *mode) -+{ -+ memclear(*wire); -+ wire->clock = mode->clock; -+ wire->hdisplay = mode->hdisplay; -+ wire->hsync_start = mode->hsync_start; -+ wire->hsync_end = mode->hsync_end; -+ wire->htotal = mode->htotal; -+ wire->hskew = mode->hskew; -+ wire->vdisplay = mode->vdisplay; -+ wire->vsync_start = mode->vsync_start; -+ wire->vsync_end = mode->vsync_end; -+ wire->vtotal = mode->vtotal; -+ wire->vscan = mode->vscan; -+ wire->vrefresh = mode->vrefresh; -+ wire->flags = mode->flags; -+ wire->type = mode->type; -+} -+ -+static int redox_drm_fetch_resources(int fd, -+ struct redox_drm_resources_wire *header, -+ uint32_t **connector_ids) -+{ -+ void *response = NULL; -+ size_t response_size = 0; -+ size_t expected_size; -+ -+ if (redox_drm_exchange_alloc(fd, REDOX_DRM_IOCTL_MODE_GETRESOURCES, -+ NULL, 0, -+ &response, &response_size) != 0) { -+ return -1; -+ } -+ -+ if (response_size < sizeof(*header)) { -+ drmFree(response); -+ errno = EPROTO; -+ return -1; -+ } -+ -+ memcpy(header, response, sizeof(*header)); -+ expected_size = sizeof(*header) + -+ ((size_t)header->connector_count * sizeof(uint32_t)); -+ if (response_size < expected_size) { -+ drmFree(response); -+ errno = EPROTO; -+ return -1; -+ } -+ -+ *connector_ids = NULL; -+ if (header->connector_count != 0) { -+ *connector_ids = drmAllocCpy((char *)response + sizeof(*header), -+ header->connector_count, sizeof(uint32_t)); -+ if (!*connector_ids) { -+ drmFree(response); -+ errno = ENOMEM; -+ return -1; -+ } -+ } -+ -+ drmFree(response); -+ return 0; -+} -+ -+static int redox_drm_parse_connector_response(const void *blob, size_t blob_size, -+ struct redox_drm_connector_wire *header, -+ drmModeModeInfoPtr *modes_out) -+{ -+ const uint8_t *bytes = blob; -+ drmModeModeInfoPtr modes = NULL; -+ size_t offset = sizeof(*header); -+ uint32_t i; -+ -+ if (blob_size < sizeof(*header)) { -+ errno = EPROTO; -+ return -1; -+ } -+ -+ memcpy(header, bytes, sizeof(*header)); -+ if (header->mode_count != 0) { -+ modes = drmMalloc(header->mode_count * sizeof(*modes)); -+ if (!modes) { -+ errno = ENOMEM; -+ return -1; -+ } -+ } -+ -+ for (i = 0; i < header->mode_count; ++i) { -+ struct redox_drm_mode_wire mode_wire; -+ const char *name; -+ size_t name_len; -+ -+ if (blob_size - offset < sizeof(mode_wire)) { -+ drmFree(modes); -+ errno = EPROTO; -+ return -1; -+ } -+ -+ memcpy(&mode_wire, bytes + offset, sizeof(mode_wire)); -+ offset += sizeof(mode_wire); -+ name = (const char *)bytes + offset; -+ name_len = strnlen(name, blob_size - offset); -+ if (offset + name_len >= blob_size) { -+ drmFree(modes); -+ errno = EPROTO; -+ return -1; -+ } -+ -+ redox_drm_mode_from_wire(&modes[i], &mode_wire, name); -+ offset += name_len + 1; -+ } -+ -+ *modes_out = modes; -+ return 0; -+} -+ -+static int redox_drm_fetch_connector(int fd, uint32_t connector_id, -+ struct redox_drm_connector_wire *header, -+ drmModeModeInfoPtr *modes_out) -+{ -+ void *response = NULL; -+ size_t response_size = 0; -+ int ret; -+ -+ if (redox_drm_exchange_alloc(fd, REDOX_DRM_IOCTL_MODE_GETCONNECTOR, -+ &connector_id, sizeof(connector_id), -+ &response, &response_size) != 0) { -+ return -1; -+ } -+ -+ ret = redox_drm_parse_connector_response(response, response_size, -+ header, modes_out); -+ drmFree(response); -+ return ret; -+} -+ -+static uint32_t redox_drm_connector_type_id(int fd, uint32_t connector_id, -+ uint32_t connector_type) -+{ -+ struct redox_drm_resources_wire resources; -+ uint32_t *connector_ids = NULL; -+ uint32_t ordinal = 0; -+ uint32_t i; -+ -+ if (redox_drm_fetch_resources(fd, &resources, &connector_ids) != 0) -+ return 0; -+ -+ for (i = 0; i < resources.connector_count; ++i) { -+ struct redox_drm_connector_wire header; -+ drmModeModeInfoPtr modes = NULL; -+ -+ if (redox_drm_fetch_connector(fd, connector_ids[i], &header, &modes) != 0) -+ break; -+ drmFree(modes); -+ -+ if (header.connector_type == connector_type) -+ ++ordinal; -+ if (header.connector_id == connector_id) -+ break; -+ } -+ -+ drmFree(connector_ids); -+ return ordinal; -+} -+ -+static int redox_drm_page_flip_unsupported(uint32_t flags) -+{ -+ if (flags & (DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_PAGE_FLIP_TARGET)) { -+ errno = EOPNOTSUPP; -+ return -1; -+ } -+ -+ return 0; -+} -+#endif -+ - /* - * Util functions - */ -@@ -153,16 +360,104 @@ - - drm_public int drmIsKMS(int fd) - { -+ #if defined(__redox__) -+ struct redox_drm_resources_wire resources; -+ uint32_t *connector_ids = NULL; -+ int is_kms; -+ -+ if (redox_drm_fetch_resources(fd, &resources, &connector_ids) != 0) -+ return 0; -+ -+ is_kms = resources.crtc_count > 0 && -+ resources.connector_count > 0 && -+ resources.encoder_count > 0; -+ drmFree(connector_ids); -+ return is_kms; -+ #else - struct drm_mode_card_res res = {0}; - - if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res) != 0) - return 0; - - return res.count_crtcs > 0 && res.count_connectors > 0 && res.count_encoders > 0; -+ #endif - } - - drm_public drmModeResPtr drmModeGetResources(int fd) - { -+ #if defined(__redox__) -+ struct redox_drm_resources_wire resources; -+ uint32_t *connector_ids = NULL; -+ drmModeResPtr r = NULL; -+ uint32_t i; -+ -+ if (redox_drm_fetch_resources(fd, &resources, &connector_ids) != 0) -+ return NULL; -+ -+ r = drmMalloc(sizeof(*r)); -+ if (!r) { -+ drmFree(connector_ids); -+ return NULL; -+ } -+ memclear(*r); -+ -+ r->count_connectors = resources.connector_count; -+ r->count_crtcs = resources.crtc_count; -+ r->count_encoders = resources.encoder_count; -+ r->connectors = connector_ids; -+ -+ if (resources.crtc_count != 0) { -+ r->crtcs = drmMalloc(resources.crtc_count * sizeof(*r->crtcs)); -+ if (!r->crtcs) -+ goto err_allocs; -+ for (i = 0; i < resources.crtc_count; ++i) -+ r->crtcs[i] = i + 1; -+ } -+ -+ if (resources.encoder_count != 0) { -+ r->encoders = drmMalloc(resources.encoder_count * sizeof(*r->encoders)); -+ if (!r->encoders) -+ goto err_allocs; -+ memset(r->encoders, 0, resources.encoder_count * sizeof(*r->encoders)); -+ } -+ -+ for (i = 0; i < resources.connector_count; ++i) { -+ struct redox_drm_connector_wire connector; -+ drmModeModeInfoPtr modes = NULL; -+ uint32_t j; -+ -+ if (redox_drm_fetch_connector(fd, connector_ids[i], &connector, &modes) != 0) -+ goto err_allocs; -+ -+ if (i < resources.encoder_count) -+ r->encoders[i] = connector.encoder_id; -+ -+ for (j = 0; j < connector.mode_count; ++j) { -+ uint32_t width = modes[j].hdisplay; -+ uint32_t height = modes[j].vdisplay; -+ if (r->min_width == 0 || width < r->min_width) -+ r->min_width = width; -+ if (width > r->max_width) -+ r->max_width = width; -+ if (r->min_height == 0 || height < r->min_height) -+ r->min_height = height; -+ if (height > r->max_height) -+ r->max_height = height; -+ } -+ drmFree(modes); -+ } -+ -+ if (resources.encoder_count > resources.connector_count) { -+ for (i = resources.connector_count; i < resources.encoder_count; ++i) -+ r->encoders[i] = 0; -+ } -+ -+ return r; -+ -+err_allocs: -+ drmModeFreeResources(r); -+ return NULL; -+ #else - struct drm_mode_card_res res, counts; - drmModeResPtr r = 0; - -@@ -253,6 +548,7 @@ - drmFree(U642VOID(res.encoder_id_ptr)); - - return r; -+ #endif - } - - -@@ -260,6 +556,26 @@ - uint8_t bpp, uint32_t pitch, uint32_t bo_handle, - uint32_t *buf_id) - { -+ #if defined(__redox__) -+ struct redox_drm_add_fb_wire wire; -+ -+ memclear(wire); -+ wire.width = width; -+ wire.height = height; -+ wire.pitch = pitch; -+ wire.bpp = bpp; -+ wire.depth = depth; -+ wire.handle = bo_handle; -+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_ADDFB, -+ &wire, sizeof(wire), -+ &wire, sizeof(wire), -+ NULL) != 0) { -+ return -errno; -+ } -+ -+ *buf_id = wire.fb_id; -+ return 0; -+ #else - struct drm_mode_fb_cmd f; - int ret; - -@@ -276,6 +592,7 @@ - - *buf_id = f.fb_id; - return 0; -+ #endif - } - - drm_public int drmModeAddFB2WithModifiers(int fd, uint32_t width, -@@ -317,7 +634,22 @@ - - drm_public int drmModeRmFB(int fd, uint32_t bufferId) - { -+ #if defined(__redox__) -+ struct redox_drm_rm_fb_wire wire; -+ -+ memclear(wire); -+ wire.fb_id = bufferId; -+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_RMFB, -+ &wire, sizeof(wire), -+ NULL, 0, -+ NULL) != 0) { -+ return -errno; -+ } -+ -+ return 0; -+ #else - return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId); -+ #endif - } - - drm_public int drmModeCloseFB(int fd, uint32_t buffer_id) -@@ -374,6 +706,40 @@ - - drm_public drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId) - { -+ #if defined(__redox__) -+ struct redox_drm_get_crtc_wire wire; -+ drmModeCrtcPtr r; -+ -+ memclear(wire); -+ wire.crtc_id = crtcId; -+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_GETCRTC, -+ &wire, sizeof(wire), -+ &wire, sizeof(wire), -+ NULL) != 0) { -+ return NULL; -+ } -+ -+ r = drmMalloc(sizeof(*r)); -+ if (!r) -+ return NULL; -+ -+ memclear(*r); -+ r->crtc_id = wire.crtc_id; -+ r->x = wire.x; -+ r->y = wire.y; -+ r->mode_valid = wire.mode_valid; -+ if (r->mode_valid) { -+ char mode_name[DRM_DISPLAY_MODE_LEN]; -+ snprintf(mode_name, sizeof(mode_name), "%ux%u@%u", -+ wire.mode.hdisplay, wire.mode.vdisplay, wire.mode.vrefresh); -+ redox_drm_mode_from_wire(&r->mode, &wire.mode, mode_name); -+ r->width = wire.mode.hdisplay; -+ r->height = wire.mode.vdisplay; -+ } -+ r->buffer_id = wire.fb_id; -+ r->gamma_size = 0; -+ return r; -+ #else - struct drm_mode_crtc crtc; - drmModeCrtcPtr r; - -@@ -402,12 +768,47 @@ - r->buffer_id = crtc.fb_id; - r->gamma_size = crtc.gamma_size; - return r; -+ #endif - } - - drm_public int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, - uint32_t x, uint32_t y, uint32_t *connectors, int count, - drmModeModeInfoPtr mode) - { -+ #if defined(__redox__) -+ struct redox_drm_set_crtc_wire wire; -+ -+ if ((x != 0 || y != 0) && bufferId != 0) { -+ errno = EOPNOTSUPP; -+ return -errno; -+ } -+ if (count < 0 || count > 8) { -+ errno = EINVAL; -+ return -errno; -+ } -+ if (bufferId != 0 && !mode) { -+ errno = EINVAL; -+ return -errno; -+ } -+ -+ memclear(wire); -+ wire.crtc_id = crtcId; -+ wire.fb_handle = bufferId; -+ wire.connector_count = count; -+ if (count > 0) -+ memcpy(wire.connectors, connectors, count * sizeof(*connectors)); -+ if (mode) -+ redox_drm_mode_to_wire(&wire.mode, mode); -+ -+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_SETCRTC, -+ &wire, sizeof(wire), -+ NULL, 0, -+ NULL) != 0) { -+ return -errno; -+ } -+ -+ return 0; -+ #else - struct drm_mode_crtc crtc; - - memclear(crtc); -@@ -423,6 +824,7 @@ - } - - return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc); -+ #endif - } - - /* -@@ -480,6 +882,30 @@ - */ - drm_public drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id) - { -+ #if defined(__redox__) -+ struct drm_mode_get_encoder enc; -+ drmModeEncoderPtr r = NULL; -+ -+ memclear(enc); -+ enc.encoder_id = encoder_id; -+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_GETENCODER, -+ &enc, sizeof(enc), -+ &enc, sizeof(enc), -+ NULL) != 0) { -+ return NULL; -+ } -+ -+ r = drmMalloc(sizeof(*r)); -+ if (!r) -+ return NULL; -+ -+ r->encoder_id = enc.encoder_id; -+ r->crtc_id = enc.crtc_id; -+ r->encoder_type = enc.encoder_type; -+ r->possible_crtcs = enc.possible_crtcs; -+ r->possible_clones = enc.possible_clones; -+ return r; -+ #else - struct drm_mode_get_encoder enc; - drmModeEncoderPtr r = NULL; - -@@ -499,6 +925,7 @@ - r->possible_clones = enc.possible_clones; - - return r; -+ #endif - } - - /* -@@ -507,6 +934,50 @@ - static drmModeConnectorPtr - _drmModeGetConnector(int fd, uint32_t connector_id, int probe) - { -+ #if defined(__redox__) -+ struct redox_drm_connector_wire conn; -+ drmModeConnectorPtr r = NULL; -+ drmModeModeInfoPtr modes = NULL; -+ -+ (void)probe; -+ if (redox_drm_fetch_connector(fd, connector_id, &conn, &modes) != 0) -+ return NULL; -+ -+ r = drmMalloc(sizeof(*r)); -+ if (!r) -+ goto err_allocs; -+ memclear(*r); -+ -+ r->connector_id = conn.connector_id; -+ r->encoder_id = conn.encoder_id; -+ r->connection = conn.connection; -+ r->mmWidth = conn.mm_width; -+ r->mmHeight = conn.mm_height; -+ r->subpixel = DRM_MODE_SUBPIXEL_UNKNOWN; -+ r->count_modes = conn.mode_count; -+ r->modes = modes; -+ r->count_props = 0; -+ r->props = NULL; -+ r->prop_values = NULL; -+ r->count_encoders = conn.encoder_id ? 1 : 0; -+ if (r->count_encoders != 0) { -+ r->encoders = drmMalloc(sizeof(*r->encoders)); -+ if (!r->encoders) -+ goto err_allocs; -+ r->encoders[0] = conn.encoder_id; -+ } -+ r->connector_type = conn.connector_type; -+ r->connector_type_id = redox_drm_connector_type_id(fd, -+ conn.connector_id, -+ conn.connector_type); -+ return r; -+ -+err_allocs: -+ drmFree(modes); -+ drmFree(r ? r->encoders : NULL); -+ drmFree(r); -+ return NULL; -+ #else - struct drm_mode_get_connector conn, counts; - drmModeConnectorPtr r = NULL; - struct drm_mode_modeinfo stack_mode; -@@ -608,6 +1079,7 @@ - drmFree(U642VOID(conn.encoders_ptr)); - - return r; -+ #endif - } - - drm_public drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id) -@@ -1100,6 +1572,27 @@ - drm_public int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, - uint32_t flags, void *user_data) - { -+ #if defined(__redox__) -+ struct redox_drm_page_flip_wire flip; -+ uint64_t sequence; -+ -+ (void)user_data; -+ if (redox_drm_page_flip_unsupported(flags) != 0) -+ return -errno; -+ -+ memclear(flip); -+ flip.fb_handle = fb_id; -+ flip.crtc_id = crtc_id; -+ flip.flags = flags; -+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_PAGE_FLIP, -+ &flip, sizeof(flip), -+ &sequence, sizeof(sequence), -+ NULL) != 0) { -+ return -errno; -+ } -+ -+ return 0; -+ #else - struct drm_mode_crtc_page_flip flip; - - memclear(flip); -@@ -1109,12 +1602,23 @@ - flip.flags = flags; - - return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip); -+ #endif - } - - drm_public int drmModePageFlipTarget(int fd, uint32_t crtc_id, uint32_t fb_id, - uint32_t flags, void *user_data, - uint32_t target_vblank) - { -+ #if defined(__redox__) -+ (void)fd; -+ (void)crtc_id; -+ (void)fb_id; -+ (void)flags; -+ (void)user_data; -+ (void)target_vblank; -+ errno = EOPNOTSUPP; -+ return -errno; -+ #else - struct drm_mode_crtc_page_flip_target flip_target; - - memclear(flip_target); -@@ -1125,6 +1629,7 @@ - flip_target.sequence = target_vblank; - - return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip_target); -+ #endif - } - - drm_public int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id, -@@ -1839,6 +2344,26 @@ - uint32_t flags, uint32_t *handle, uint32_t *pitch, - uint64_t *size) - { -+ #if defined(__redox__) -+ struct redox_drm_create_dumb_wire create; -+ -+ memclear(create); -+ create.width = width; -+ create.height = height; -+ create.bpp = bpp; -+ create.flags = flags; -+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_CREATE_DUMB, -+ &create, sizeof(create), -+ &create, sizeof(create), -+ NULL) != 0) { -+ return -errno; -+ } -+ -+ *handle = create.handle; -+ *pitch = create.pitch; -+ *size = create.size; -+ return 0; -+ #else - int ret; - struct drm_mode_create_dumb create = { - .width = width, -@@ -1855,21 +2380,52 @@ - *pitch = create.pitch; - *size = create.size; - return 0; -+ #endif - } - - drm_public int - drmModeDestroyDumbBuffer(int fd, uint32_t handle) - { -+ #if defined(__redox__) -+ struct redox_drm_destroy_dumb_wire destroy; -+ -+ memclear(destroy); -+ destroy.handle = handle; -+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_DESTROY_DUMB, -+ &destroy, sizeof(destroy), -+ NULL, 0, -+ NULL) != 0) { -+ return -errno; -+ } -+ -+ return 0; -+ #else - struct drm_mode_destroy_dumb destroy = { - .handle = handle, - }; - - return DRM_IOCTL(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy); -+ #endif - } - - drm_public int - drmModeMapDumbBuffer(int fd, uint32_t handle, uint64_t *offset) - { -+ #if defined(__redox__) -+ struct redox_drm_map_dumb_wire map; -+ -+ memclear(map); -+ map.handle = handle; -+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_MAP_DUMB, -+ &map, sizeof(map), -+ &map, sizeof(map), -+ NULL) != 0) { -+ return -errno; -+ } -+ -+ *offset = map.offset; -+ return 0; -+ #else - int ret; - struct drm_mode_map_dumb map = { - .handle = handle, -@@ -1881,4 +2437,5 @@ - - *offset = map.offset; - return 0; -+ #endif - } -diff -ruN source-old/xf86drm_redox.h source/xf86drm_redox.h ---- source-old/xf86drm_redox.h -+++ source/xf86drm_redox.h -@@ -0,0 +1,162 @@ -+#ifndef _XF86DRM_REDOX_H_ -+#define _XF86DRM_REDOX_H_ -+ -+#if defined(__redox__) -+ -+#include -+#include -+ -+#define REDOX_DRM_IOCTL_BASE 0x00A0UL -+ -+#define REDOX_LINUX_IOCTL_NR(request) ((unsigned long)((request) & 0xffUL)) -+#define REDOX_LINUX_IOCTL_SIZE(request) (((unsigned long)(request) >> 16) & 0x3fffUL) -+ -+#define REDOX_DRM_IOCTL_MODE_GETRESOURCES (REDOX_DRM_IOCTL_BASE + 0) -+#define REDOX_DRM_IOCTL_MODE_SETCRTC (REDOX_DRM_IOCTL_BASE + 2) -+#define REDOX_DRM_IOCTL_MODE_GETCRTC (REDOX_DRM_IOCTL_BASE + 3) -+#define REDOX_DRM_IOCTL_MODE_GETENCODER (REDOX_DRM_IOCTL_BASE + 6) -+#define REDOX_DRM_IOCTL_MODE_GETCONNECTOR (REDOX_DRM_IOCTL_BASE + 7) -+#define REDOX_DRM_IOCTL_MODE_PAGE_FLIP (REDOX_DRM_IOCTL_BASE + 16) -+#define REDOX_DRM_IOCTL_MODE_CREATE_DUMB (REDOX_DRM_IOCTL_BASE + 18) -+#define REDOX_DRM_IOCTL_MODE_MAP_DUMB (REDOX_DRM_IOCTL_BASE + 19) -+#define REDOX_DRM_IOCTL_MODE_DESTROY_DUMB (REDOX_DRM_IOCTL_BASE + 20) -+#define REDOX_DRM_IOCTL_MODE_ADDFB (REDOX_DRM_IOCTL_BASE + 21) -+#define REDOX_DRM_IOCTL_MODE_RMFB (REDOX_DRM_IOCTL_BASE + 22) -+#define REDOX_DRM_IOCTL_GET_CAP (REDOX_DRM_IOCTL_BASE + 23) -+#define REDOX_DRM_IOCTL_SET_CLIENT_CAP (REDOX_DRM_IOCTL_BASE + 24) -+#define REDOX_DRM_IOCTL_VERSION (REDOX_DRM_IOCTL_BASE + 25) -+#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) -+ -+struct redox_drm_resources_wire { -+ uint32_t connector_count; -+ uint32_t crtc_count; -+ uint32_t encoder_count; -+}; -+ -+struct redox_drm_connector_wire { -+ uint32_t connector_id; -+ uint32_t connection; -+ uint32_t connector_type; -+ uint32_t mm_width; -+ uint32_t mm_height; -+ uint32_t encoder_id; -+ uint32_t mode_count; -+}; -+ -+struct redox_drm_mode_wire { -+ uint32_t clock; -+ uint16_t hdisplay; -+ uint16_t hsync_start; -+ uint16_t hsync_end; -+ uint16_t htotal; -+ uint16_t hskew; -+ uint16_t vdisplay; -+ uint16_t vsync_start; -+ uint16_t vsync_end; -+ uint16_t vtotal; -+ uint16_t vscan; -+ uint32_t vrefresh; -+ uint32_t flags; -+ uint32_t type; -+}; -+ -+struct redox_drm_set_crtc_wire { -+ uint32_t crtc_id; -+ uint32_t fb_handle; -+ uint32_t connector_count; -+ uint32_t connectors[8]; -+ struct redox_drm_mode_wire mode; -+}; -+ -+struct redox_drm_page_flip_wire { -+ uint32_t crtc_id; -+ uint32_t fb_handle; -+ uint32_t flags; -+}; -+ -+struct redox_drm_create_dumb_wire { -+ uint32_t width; -+ uint32_t height; -+ uint32_t bpp; -+ uint32_t flags; -+ uint32_t pitch; -+ uint32_t reserved0; -+ uint64_t size; -+ uint32_t handle; -+ uint32_t reserved1; -+}; -+ -+struct redox_drm_map_dumb_wire { -+ uint32_t handle; -+ uint32_t pad; -+ uint64_t offset; -+}; -+ -+struct redox_drm_destroy_dumb_wire { -+ uint32_t handle; -+}; -+ -+struct redox_drm_add_fb_wire { -+ uint32_t width; -+ uint32_t height; -+ uint32_t pitch; -+ uint32_t bpp; -+ uint32_t depth; -+ uint32_t handle; -+ uint32_t fb_id; -+}; -+ -+struct redox_drm_rm_fb_wire { -+ uint32_t fb_id; -+}; -+ -+struct redox_drm_get_crtc_wire { -+ uint32_t crtc_id; -+ uint32_t fb_id; -+ uint32_t x; -+ uint32_t y; -+ uint32_t mode_valid; -+ struct redox_drm_mode_wire mode; -+}; -+ -+struct redox_drm_version_wire { -+ int32_t major; -+ int32_t minor; -+ int32_t patch; -+}; -+ -+struct redox_drm_prime_handle_to_fd_wire { -+ uint32_t handle; -+ uint32_t flags; -+}; -+ -+struct redox_drm_prime_handle_to_fd_response_wire { -+ int32_t fd; -+ uint32_t pad; -+}; -+ -+struct redox_drm_prime_fd_to_handle_wire { -+ int32_t fd; -+ uint32_t pad; -+}; -+ -+struct redox_drm_prime_fd_to_handle_response_wire { -+ uint32_t handle; -+ uint32_t pad; -+}; -+ -+unsigned long redox_translate_request(unsigned long linux_nr); -+int redox_drm_simple_ioctl(int fd, unsigned long request, void *arg); -+int redox_drm_exchange(int fd, unsigned long request_code, -+ const void *payload, size_t payload_size, -+ void *response, size_t response_capacity, -+ size_t *response_size); -+int redox_drm_exchange_alloc(int fd, unsigned long request_code, -+ const void *payload, size_t payload_size, -+ void **response, size_t *response_size); -+ -+#endif -+ -+#endif