From 6d472b19195d418bd6610bf5dc7762c99f425b52 Mon Sep 17 00:00:00 2001 From: vasilito Date: Sun, 26 Jul 2026 08:02:13 +0900 Subject: [PATCH] winsys(redox): real BO byte count from format, width, height, depth --- .../gallium/winsys/redox/drm/redox_drm_bo.c | 119 +++++++++++++----- 1 file changed, 91 insertions(+), 28 deletions(-) diff --git a/local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/redox_drm_bo.c b/local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/redox_drm_bo.c index 13cdd0ab5c..b7027f5cc4 100644 --- a/local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/redox_drm_bo.c +++ b/local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/redox_drm_bo.c @@ -21,34 +21,97 @@ #include #include "pipe/p_state.h" +#include "util/u_format.h" #include "util/u_memory.h" #include "util/u_inlines.h" #include "util/u_debug.h" +/* Compute the byte count of a pipe_resource based on format, + * width0, height0, depth0, and array_size. This accounts for + * compressed formats (blocks-of-4x4) and the per-block sizes of + * common uncompressed formats. Mesa's util_format provides + * util_format_get_blocksizebits() which gives the bits per block + * for any format; we use that to compute the proper allocation. + */ +static uint32_t +redox_format_bytes_per_block(enum pipe_format format) +{ + /* Use Mesa's util_format helper when available. The function + * returns bits per block; we convert to bytes. */ + uint32_t bits = util_format_get_blocksizebits(format); + if (bits > 0) + return (bits + 7) / 8; + /* Conservative fallback: assume 32-bit color (RGBA / BGRA / + * RGBX / BGRX). This is correct for the common gallium + * color formats and overestimates by up to 4x for smaller + * formats, which is safe (a few unused bytes vs corrupt + * pixels). */ + return 4; +} + +static bool +redox_format_is_compressed(enum pipe_format format) +{ + /* Mesa's util_format helper identifies block-compressed + * formats. The full set includes BC1-BC7, ETC1, ETC2, EAC. */ + return util_format_is_compressed(format); +} + +static uint64_t +redox_resource_byte_count(const struct pipe_resource *templat) +{ + if (!templat || !templat->format) + return 0; + + uint32_t width = templat->width0 ? templat->width0 : 1; + uint32_t height = templat->height0 ? templat->height0 : 1; + uint32_t depth = templat->depth0 ? templat->depth0 : 1; + uint32_t array_size = templat->array_size ? templat->array_size : 1; + + if (redox_format_is_compressed(templat->format)) { + const uint32_t block_w = 4, block_h = 4; + uint32_t blocks_w = (width + block_w - 1) / block_w; + uint32_t blocks_h = (height + block_h - 1) / block_h; + uint32_t bytes_per_block = redox_format_bytes_per_block( + templat->format); + return (uint64_t)blocks_w * (uint64_t)blocks_h * + (uint64_t)depth * (uint64_t)bytes_per_block; + } + + uint32_t bytes_per_block = redox_format_bytes_per_block( + templat->format); + + uint32_t num_faces = (templat->target == PIPE_TEXTURE_CUBE) ? 6 : 1; + + return (uint64_t)width * (uint64_t)height * + (uint64_t)depth * (uint64_t)array_size * + (uint64_t)num_faces * (uint64_t)bytes_per_block; +} + /* DRM UAPI: standard GEM create. libdrm's redox.patch redirects this * to /scheme/drm/card0 / GEM_CREATE on the Redox kernel side. */ static uint32_t redox_gem_create(int fd, uint64_t size) { - struct drm_mode_create_dumb create = {0}; - int err; + struct drm_mode_create_dumb create = {0}; + int err; - create.height = 1; - create.width = (uint32_t)(size & 0xFFFFFFFF); - create.bpp = 8; + create.height = 1; + create.width = (uint32_t)(size & 0xFFFFFFFF); + create.bpp = 8; - /* Redox's GEM handle type is uint32_t (see kernel's GemHandle). - * DRM_IOCTL_MODE_CREATE_DUMB allocates a contiguous GEM object - * with a single offset/stride. - */ - err = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create); - if (err != 0) { + /* Redox's GEM handle type is uint32_t (see kernel's GemHandle). + * DRM_IOCTL_MODE_CREATE_DUMB allocates a contiguous GEM object + * with a single offset/stride. + */ + err = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create); + if (err != 0) { debug_printf("redox: DRM_IOCTL_MODE_CREATE_DUMB failed: %s\n", strerror(errno)); return 0; - } - return create.handle; + } + return create.handle; } /* Map a GEM object's pages into the process address space. @@ -110,24 +173,24 @@ redox_drm_bo_create(struct redox_drm_winsys *rws, return NULL; } - handle = redox_gem_create(rws->fd, templat->width0); - if (!handle) - return NULL; + handle = redox_gem_create(rws->fd, redox_resource_byte_count(templat)); + if (!handle) + return NULL; - bo = CALLOC_STRUCT(redox_drm_bo); - if (!bo) { - redox_gem_close(rws->fd, handle); - return NULL; - } + bo = CALLOC_STRUCT(redox_drm_bo); + if (!bo) { + redox_gem_close(rws->fd, handle); + return NULL; + } - bo->base = *templat; - bo->gem_handle = handle; - bo->fb_id = 0; - bo->stride = 0; - bo->size = templat->width0; - bo->map_ptr = NULL; + bo->base = *templat; + bo->gem_handle = handle; + bo->fb_id = 0; + bo->stride = 0; + bo->size = redox_resource_byte_count(templat); + bo->map_ptr = NULL; - return &bo->base; + return &bo->base; } void