From 280ced031cea116524cc90319d1dca04e5281d60 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C5=81ukasz=20Stelmach?= Date: Thu, 19 Oct 2023 16:21:02 +0200 Subject: [PATCH] Fix for virglrenderer MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit virglrenderer used by QEMU together with virtio-gpu allows allocations that are at most 16384 pixels wide or high. This means it can provide buffers as large as 256 MiB but they need to be 16k by 16k pixels and not 256M by 1. Square root approximation is quick and although it results in buffers being allocated slightly larger than requested, but the error isn't significant. Change-Id: Ife231fd5ac4eae0181680e86ec9c239920cdef41 Signed-off-by: Łukasz Stelmach --- src/tbm_backend_dumb.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/tbm_backend_dumb.c b/src/tbm_backend_dumb.c index 5963f49..0edb5dc 100644 --- a/src/tbm_backend_dumb.c +++ b/src/tbm_backend_dumb.c @@ -640,6 +640,24 @@ tbm_dumb_bufmgr_get_plane_data(hal_tbm_bufmgr *bufmgr, return HAL_TBM_ERROR_NONE; } +#define LOG2(x) ((unsigned int)(sizeof(unsigned int) * 8 - 1 - __builtin_clz(x))) + +static inline unsigned int dirty_sqrt(unsigned int v) +{ + unsigned int log2 = LOG2(v); + + if (log2 < 0) + return 0; + + if (log2 == 0) + return 1; + + log2 += !!(v & (1 << (log2 - 1))); + log2 >>= 1; + + return 1 << log2; +} + static hal_tbm_bo * tbm_dumb_bufmgr_alloc_bo(hal_tbm_bufmgr *bufmgr, unsigned int size, hal_tbm_bo_memory_type flags, hal_tbm_error *error) @@ -662,9 +680,18 @@ tbm_dumb_bufmgr_alloc_bo(hal_tbm_bufmgr *bufmgr, unsigned int size, //as we know only size for new bo set height=1 and bpp=8 and in this case //width will by equal to size in bytes; - create_dumb_arg.height = 1; create_dumb_arg.bpp = 32; // virtio-gpu refuses to accept bpp=8 - create_dumb_arg.width = (size + 4 - 1) / 4; + if (size <= 16384) { + create_dumb_arg.height = 1; + create_dumb_arg.width = (size + 4 - 1) / 4; + } else { + unsigned int words = (size + 4 - 1) / 4; + unsigned int root = dirty_sqrt(words); + + create_dumb_arg.height = root; + create_dumb_arg.width = (words + root - 1) / root; + } + create_dumb_arg.flags = dumb_flags; if (drmIoctl(bufmgr_data->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb_arg)) { TBM_BACKEND_ERR("fail to DRM_IOCTL_MODE_CREATE_DUMB flag:%x size:%d", -- 2.34.1