winsys(redox): real BO byte count from format, width, height, depth
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user