winsys(redox): real BO byte count from format, width, height, depth

This commit is contained in:
2026-07-26 08:02:13 +09:00
parent 4480a5754a
commit 6d472b1919
@@ -21,34 +21,97 @@
#include <xf86drm.h>
#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